/* * OpenPBS (Portable Batch System) v2.3 Software License * * Copyright (c) 1999-2000 Veridian Information Solutions, Inc. * All rights reserved. * * --------------------------------------------------------------------------- * For a license to use or redistribute the OpenPBS software under conditions * other than those described below, or to purchase support for this software, * please contact Veridian Systems, PBS Products Department ("Licensor") at: * * www.OpenPBS.org +1 650 967-4675 sales@OpenPBS.org * 877 902-4PBS (US toll-free) * --------------------------------------------------------------------------- * * This license covers use of the OpenPBS v2.3 software (the "Software") at * your site or location, and, for certain users, redistribution of the * Software to other sites and locations. Use and redistribution of * OpenPBS v2.3 in source and binary forms, with or without modification, * are permitted provided that all of the following conditions are met. * After December 31, 2001, only conditions 3-6 must be met: * * 1. Commercial and/or non-commercial use of the Software is permitted * provided a current software registration is on file at www.OpenPBS.org. * If use of this software contributes to a publication, product, or * service, proper attribution must be given; see www.OpenPBS.org/credit.html * * 2. Redistribution in any form is only permitted for non-commercial, * non-profit purposes. There can be no charge for the Software or any * software incorporating the Software. Further, there can be no * expectation of revenue generated as a consequence of redistributing * the Software. * * 3. Any Redistribution of source code must retain the above copyright notice * and the acknowledgment contained in paragraph 6, this list of conditions * and the disclaimer contained in paragraph 7. * * 4. Any Redistribution in binary form must reproduce the above copyright * notice and the acknowledgment contained in paragraph 6, this list of * conditions and the disclaimer contained in paragraph 7 in the * documentation and/or other materials provided with the distribution. * * 5. Redistributions in any form must be accompanied by information on how to * obtain complete source code for the OpenPBS software and any * modifications and/or additions to the OpenPBS software. The source code * must either be included in the distribution or be available for no more * than the cost of distribution plus a nominal fee, and all modifications * and additions to the Software must be freely redistributable by any party * (including Licensor) without restriction. * * 6. All advertising materials mentioning features or use of the Software must * display the following acknowledgment: * * "This product includes software developed by NASA Ames Research Center, * Lawrence Livermore National Laboratory, and Veridian Information * Solutions, Inc. * Visit www.OpenPBS.org for OpenPBS software support, * products, and information." * * 7. DISCLAIMER OF WARRANTY * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT * ARE EXPRESSLY DISCLAIMED. * * IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE * U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This license will be governed by the laws of the Commonwealth of Virginia, * without reference to its choice of law rules. */ #include /* the master config generated by configure */ #include #include #include "pbs_ifl.h" #include #include #include #include #include #include "server_limits.h" #include "list_link.h" #include "attribute.h" #include "pbs_job.h" #include "server.h" #include "pbs_error.h" #include "svrfunc.h" #include "log.h" #include "../lib/Liblog/pbs_log.h" #include "utils.h" #ifdef _CRAY #include #endif /* _CRAY */ #include "svrfunc.h" /* get_svr_attr_* */ /* External Data */ extern char server_host[]; extern int LOGLEVEL; /* * geteusernam - get effective user name * Get the user name under which the job should be run on this host: * 1. from user_list use name with host name that matches this host * 2. from user_list use name with no host specification * 3. user owner name * * Returns pointer to the user name */ static char *geteusernam( job *pjob, pbs_attribute *pattr) /* pointer to User_List pbs_attribute */ { int rule3 = 0; char *hit = 0; int i; struct array_strings *parst; char *pn; char *ptr; char username[PBS_MAXUSER + 1]; char *ret_user; /* search the user-list pbs_attribute */ if ((pattr->at_flags & ATR_VFLAG_SET) && (parst = pattr->at_val.at_arst)) { for (i = 0;i < parst->as_usedptr;i++) { pn = parst->as_string[i]; ptr = strchr(pn, '@'); if (ptr != NULL) { /* has host specification */ if (!strncmp(server_host, ptr + 1, strlen(ptr + 1))) { hit = pn; /* option 1. */ break; } } else { /* wildcard host (null) */ hit = pn; /* option 2. */ } } } if (!hit) { /* default to the job owner ( 3.) */ hit = pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str; rule3 = 1; } /* copy user name into return buffer, strip off host name */ get_jobowner(hit, username); if (rule3) { ptr = site_map_user(username, get_variable(pjob, (char *)"PBS_O_HOST")); if (ptr != username) snprintf(username, sizeof(username), "%s", ptr); } ret_user = (char *)calloc(1, strlen(username) + 1); strcpy(ret_user,username); return(ret_user); } /* END geteusernam() */ /* * getegroup - get specified effective group name * Get the group name under which the job is specified to be run on * this host: * 1. from group_list use name with host name that matches this host * 2. from group_list use name with no host specification * 3. NULL, not specified. * * Returns pointer to the group name or null */ char *getegroup( job *pjob, /* I */ pbs_attribute *pattr) /* I group_list pbs_attribute */ { char *hit = 0; int i; struct array_strings *parst; char *pn; char *ptr; char groupname[PBS_MAXUSER + 1]; char *ret_group; /* search the group-list pbs_attribute */ if ((pattr->at_flags & ATR_VFLAG_SET) && (parst = pattr->at_val.at_arst)) { for (i = 0;i < parst->as_usedptr;i++) { pn = parst->as_string[i]; ptr = strchr(pn, '@'); if (ptr != NULL) { /* has host specification */ if (!strncmp(server_host, ptr + 1, strlen(ptr + 1))) { hit = pn; /* option 1. */ break; } } else { /* wildcard host (null) */ hit = pn; /* option 2. */ } } } if (!hit) /* nothing specified, return null */ { return(NULL); } /* copy group name into return buffer, strip off host name */ /* get_jobowner() works for group as well, same size */ get_jobowner(hit, groupname); ret_group = (char *)calloc(1, strlen(groupname) + 1); strcpy(ret_group,groupname); return(ret_group); } /* END getegroup() */ /* * set_jobexid - validate and set the execution user (JOB_ATR_euser) and * execution group (JOB_ATR_egroup) job attributes. * * 1. Get the execution user name. * 1a. Get the corresponding password entry. * 1b. Uid of 0 (superuser) is not allowed, might cause root-rot * 1c. If job owner name is not being used, does the job owner have * permission to map to the execution name? * 1d. Set JOB_ATR_euser to the execution user name. * 2. Get the execution group name. * 2a. Is the execution user name a member of this group? * 2b. Set JOB_ATR_egroup to the execution group name. * * Returns: 0 if set, non-zero error number if any error */ int set_jobexid( job *pjob, /* I */ pbs_attribute *attrry, /* I */ char *EMsg) /* O (optional,minsize=1024) */ { int addflags = 0; pbs_attribute *pattr; char **pmem; struct group *gpent; int free_puser = FALSE; char *puser = NULL; char *at; char *usr_at_host = NULL; int len; struct passwd *pwent = NULL; char *pgrpn; int free_pgrpn = TRUE; char gname[PBS_MAXGRPN + 1]; #ifdef _CRAY struct udb *pudb; #endif char tmpLine[1024 + 1]; char log_buf[LOCAL_LOG_BUF_SIZE]; long disable_id_check = 0; int CheckID; /* boolean */ if (EMsg != NULL) EMsg[0] = '\0'; /* use the passed User_List if set, may be a newly modified one */ /* if not set, fall back to the job's actual User_List, may be same */ if (get_svr_attr_l(SRV_ATR_DisableServerIdCheck, &disable_id_check) != PBSE_NONE) CheckID = 1; else CheckID = !disable_id_check; if (CheckID == 0) { /* NOTE: use owner, not userlist - should this be changed? */ /* Yes, changed 10/17/2007 */ if (pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str != NULL) { /* start of change to use userlist instead of owner 10/17/2007 */ if ((attrry + JOB_ATR_userlst)->at_flags & ATR_VFLAG_SET) pattr = attrry + JOB_ATR_userlst; else pattr = &pjob->ji_wattr[JOB_ATR_userlst]; if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { puser = pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str; /* set the job's owner as the new user, appending @host if * the job's owner has that */ at = strchr(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str,'@'); len = strlen(puser) + 1; if (at != NULL) { len += strlen(at); usr_at_host = (char *)calloc(len, sizeof(char)); snprintf(usr_at_host,len,"%s%s", puser, at); } else { usr_at_host = (char *)calloc(len, sizeof(char)); snprintf(usr_at_host,len,"%s", puser); } free(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str); pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str = usr_at_host; } else if ((puser = geteusernam(pjob, pattr)) == NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate user name in job"); return(PBSE_BADUSER); } free_puser = TRUE; sprintf(tmpLine, "%s", puser); /* end of change to use userlist instead of owner 10/17/2007 */ } else { strcpy(tmpLine, "???"); } } /* END if (CheckID == 0) */ else { int perm; if ((attrry + JOB_ATR_userlst)->at_flags & ATR_VFLAG_SET) pattr = attrry + JOB_ATR_userlst; else pattr = &pjob->ji_wattr[JOB_ATR_userlst]; free_puser = TRUE; if ((puser = geteusernam(pjob, pattr)) == NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate user name in job"); return(PBSE_BADUSER); } pwent = getpwnam_ext(puser); perm = svr_get_privilege(puser,get_variable(pjob,(char *)"PBS_O_HOST")); if (pwent == NULL) { snprintf(log_buf,sizeof(log_buf), "User %s does not exist in server password file\n", puser); log_err(errno, __func__, log_buf); if (EMsg != NULL) snprintf(EMsg,1024,"%s",log_buf); free(puser); return(PBSE_BADUSER); } if ((pwent->pw_uid == 0) || (perm & ATR_DFLAG_MGWR)) { struct array_strings *pas = NULL; get_svr_attr_arst(SRV_ATR_AclRoot, &pas); /* add check here for virtual user */ if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { free(puser); free_puser = FALSE; puser = pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str; pwent = getpwnam_ext(puser); if (pwent == NULL) { snprintf(log_buf,sizeof(log_buf), "User %s does not exist in server password file\n", puser); log_err(errno, __func__, log_buf); if (EMsg != NULL) snprintf(EMsg,1024,"%s",log_buf); return(PBSE_BADUSER); } /* set the job's owner as the new user */ at = strchr(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str,'@'); len = strlen(puser) + 1; if (at != NULL) { len += strlen(at); usr_at_host = (char *)calloc(len, sizeof(char)); snprintf(usr_at_host,len,"%s%s", puser, at); } else { usr_at_host = (char *)calloc(len, sizeof(char)); snprintf(usr_at_host,len,"%s", puser); } free(pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str); pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str = usr_at_host; } else if (get_svr_attr_arst(SRV_ATR_AclRoot, &pas) == PBSE_NONE) { if (acl_check_my_array_string(pas, pjob->ji_wattr[JOB_ATR_job_owner].at_val.at_str, ACL_User) == 0) { if (EMsg != NULL) snprintf(EMsg, 1024, "root user %s fails ACL check", puser); if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); /* root not allowed */ } } else if (pwent->pw_uid == 0) { if (EMsg != NULL) snprintf(EMsg, 1024, "root user %s not allowed", puser); if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); /* root not allowed */ } } /* END if (pwent->pw_uid == 0) */ else if (pjob->ji_wattr[JOB_ATR_proxy_user].at_flags & ATR_VFLAG_SET) { /* cannot submit a proxy job if not root or a manager */ if (EMsg != NULL) { snprintf(EMsg, 1024, "User '%s' is attempting to submit a proxy job for user '%s' but is not a manager", puser, pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str); } snprintf(log_buf, 1024, "User '%s' is attempting to submit a proxy job for user '%s' but is not a manager", puser, pjob->ji_wattr[JOB_ATR_proxy_user].at_val.at_str); log_err(PBSE_BADUSER, __func__, log_buf); if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); } if (site_check_user_map(pjob, puser, EMsg, LOGLEVEL) == -1) { if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); } snprintf(tmpLine, sizeof(tmpLine), "%s", puser); } /* END else (CheckID == 0) */ pattr = attrry + JOB_ATR_euser; job_attr_def[JOB_ATR_euser].at_free(pattr); job_attr_def[JOB_ATR_euser].at_decode(pattr, NULL, NULL, tmpLine, 0); #ifdef _CRAY /* on cray check UDB (user data base) for permission to batch it */ if ((pwent != NULL) && (puser != NULL)) { pudb = getudbuid(pwent->pw_uid); endudb(); if (pudb == UDB_NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "user %s not located in user data base", puser); if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); } if (pudb->ue_permbits & (PERMBITS_NOBATCH | PERMBITS_RESTRICTED)) { if (free_puser == TRUE) free(puser); return(PBSE_QACESS); } /* if account (qsub -A) not specified, set default from UDB */ pattr = attrry + JOB_ATR_account; if ((pattr->at_flags & ATR_VFLAG_SET) == 0) { job_attr_def[JOB_ATR_account].at_decode( pattr, NULL, NULL, (char *)acid2nam(pudb->ue_acids[0])); } } /* END if ((pwent != NULL) && (puser != NULL)) */ #endif /* _CRAY */ /* * now figure out the group name under which the job should execute * PBS requires that each group have an entry in the group file, * see the admin guide for the reason why... * * use the passed group_list if set, may be a newly modified one * if not set, fall back to the job's actual group_list, may be same */ if ((attrry + JOB_ATR_grouplst)->at_flags & ATR_VFLAG_SET) pattr = attrry + JOB_ATR_grouplst; else pattr = &pjob->ji_wattr[JOB_ATR_grouplst]; /* extract user-specified egroup if it exists */ pgrpn = getegroup(pjob, pattr); if (pgrpn == NULL) { free_pgrpn = FALSE; if ((pwent != NULL) || ((pwent = getpwnam_ext(puser)) != NULL)) { /* egroup not specified - use user login group */ gpent = getgrgid(pwent->pw_gid); if (gpent != NULL) { pgrpn = gpent->gr_name; /* use group name */ } else { sprintf(gname, "%ld", (long)pwent->pw_gid); pgrpn = gname; /* turn gid into string */ } } else if (CheckID == 0) { strcpy(gname, "???"); pgrpn = gname; } else { log_err(errno, __func__, "getpwnam failed"); if (EMsg != NULL) snprintf(EMsg, 1024, "user does not exist in server password file"); if (free_puser == TRUE) free(puser); return(PBSE_BADUSER); } /* * setting the DEFAULT flag is a "kludgy" way to keep MOM from * having to do an unneeded look up of the group file. * We needed to have JOB_ATR_egroup set for the server but * MOM only wants it if it is not the login group, so there! */ addflags = ATR_VFLAG_DEFLT; } /* END if ((pgrpn = getegroup(pjob,pattr))) */ else if (CheckID == 0) { /* egroup specified - do not validate group within server */ /* NO-OP */ } else { /* user specified a group, group must exist and either */ /* must be user's primary group or the user must be in it */ gpent = getgrnam_ext(pgrpn); if (gpent == NULL) { if (EMsg != NULL) snprintf(EMsg, 1024, "cannot locate group %s in server group file", pgrpn); if (free_puser == TRUE) free(puser); free(pgrpn); return(PBSE_BADGRP); /* no such group */ } if (gpent->gr_gid != pwent->pw_gid) { /* not primary group */ pmem = gpent->gr_mem; while (*pmem != NULL) { if (!strcmp(puser, *pmem)) break; ++pmem; } if (*pmem == NULL) { /* requested group not allowed */ snprintf(log_buf,sizeof(log_buf), "user %s is not a member of group %s in server password file", puser, pgrpn); log_err(-1, __func__, log_buf); if (EMsg != NULL) snprintf(EMsg, 1024, "%s",log_buf); if (free_puser == TRUE) free(puser); free(pgrpn); return(PBSE_BADGRP); /* user not in group */ } } } /* END if ((pgrpn = getegroup(pjob,pattr))) */ /* set new group */ pattr = attrry + JOB_ATR_egroup; job_attr_def[JOB_ATR_egroup].at_free(pattr); job_attr_def[JOB_ATR_egroup].at_decode(pattr, NULL, NULL, pgrpn, 0); pattr->at_flags |= addflags; /* SUCCESS */ if (free_puser == TRUE) free(puser); if (free_pgrpn == TRUE) free(pgrpn); return(0); } /* END set_jobexid() */ /* END geteusernam.c */