/** * @brief * main - the entry point in pbs_account_win.c * * @param[in] argc - argument count * @param[in] argv - argument variables. * @param[in] env - environment values. * * @return int * @retval 0 : success * @retval !=0 : error code */ main(int argc, char *argv[]) { SID *sa_sid = NULL; /* service account SID */ char sa_name[PBS_MAXHOSTNAME+UNLEN+2] = {'\0'}; /* service account name */ /* domain\user\0 */ int ret_val = 0; int c_opt = 0; int s_opt = 0; int a_opt = 0; int p_opt = 0; int R_opt = 0; int U_opt = 0; int instid_opt = 0; char service_bin_path[MAXPATHLEN+1] = {'\0'}; char service_name[MAXPATHLEN+1] = {'\0'}; int i = 0; char outputfile[MAXPATHLEN+1] = {'\0'}; char instanceName[MAXPATHLEN+1] = {'\0'}; int output_fd = -1; struct passwd *pw = NULL; char *p = NULL; winsock_init(); /*test for real deal or just version and exit*/ execution_mode(argc, argv); strcpy(exec_unamef, getlogin_full()); strcpy(exec_dname, "."); if ((p=strchr(exec_unamef, '\\'))) { *p = '\0'; strcpy(exec_dname, exec_unamef); *p = '\\'; } strcpy(sa_password, ""); strcpy(outputfile, ""); /* with no option, check only if service account exists */ if (argc == 1) { int in_domain_environment = 0; char dname[PBS_MAXHOSTNAME+1] = {'\0'}; char dctrl[PBS_MAXHOSTNAME+1] = {'\0'}; wchar_t unamew[UNLEN+1] = {'\0'}; wchar_t dctrlw[PBS_MAXHOSTNAME+1] = {'\0'}; USER_INFO_0 *ui1_ptr = NULL; NET_API_STATUS netst = 0; /* figure out the domain controller hostname (dctrl) */ /* in domain environment, */ /* domain name (dname) != domain controller hostname */ /* in standalone environment, */ /* domain name (dname) == domain controller hostname */ in_domain_environment = GetComputerDomainName(dname); strcpy(dctrl, dname); if (in_domain_environment) { char dname_a[PBS_MAXHOSTNAME+1]; get_dcinfo(dname, dname_a, dctrl); } /* convert strings to "wide" format */ mbstowcs(unamew, service_accountname, UNLEN+1); mbstowcs(dctrlw, dctrl, PBS_MAXHOSTNAME+1); netst = wrap_NetUserGetInfo(dctrlw, unamew, 1, (LPBYTE *)&ui1_ptr); if (strlen(winlog_buffer) > 0) { fprintf(stderr, "%s\n", winlog_buffer); } if (netst == NERR_UserNotFound) { fprintf(stderr, "%s not found!\n", service_accountname); if (in_domain_environment && stricmp(exec_dname, dname) != 0) { fprintf(stderr, "But no privilege to create service account %s\\%s!\n", dname, service_accountname); ret_val=2; } else { ret_val=1; } } else if ((netst == ERROR_ACCESS_DENIED) || (netst == ERROR_LOGON_FAILURE)) { fprintf(stderr, "no privilege to obtain info for service account %s\\%s!\n", dname, service_accountname); ret_val= 2; } else { fprintf(stderr, "service account is %s\\%s!\n", dname, service_accountname); ret_val = 0; } if (ui1_ptr != NULL) NetApiBufferFree(ui1_ptr); goto end_pbs_account; } i = 1; while (i < argc) { if (strcmp(argv[i], "-c") == 0) { c_opt = 1; i++; } else if (strcmp(argv[i], "--ci") == 0) { c_opt = 1; for_info_only = 1; i++; } else if (strcmp(argv[i], "-s") == 0) { s_opt = 1; i++; } else if (strcmp(argv[i], "-a") == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No service account name argument supplied!\n"); usage(argv[0]); exit(1); } a_opt = 1; strcpy(service_accountname, argv[i+1]); i+=2; } else if (strcmp(argv[i], "-p") == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No password argument supplied!\n"); usage(argv[0]); exit(1); } p_opt = 1; strcpy(sa_password, argv[i+1]); cache_usertoken_and_homedir(service_accountname, NULL, 0, read_sa_password, (char*)service_accountname, decrypt_sa_password, 1); i+=2; } else if (strcmp(argv[i], "--reg") == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No service binary path given\n"); usage(argv[0]); exit(1); } R_opt = 1; strcpy(service_bin_path, argv[i+1]); i+=2; } else if (strcmp(argv[i], "--unreg") == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No service binary path given\n"); usage(argv[0]); exit(1); } U_opt = 1; strcpy(service_bin_path, argv[i+1]); i+=2; } else if (strcmp(argv[i], "-o") == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No output path argument supplied!\n"); usage(argv[0]); exit(1); } p_opt = 1; strcpy(outputfile, argv[i+1]); i+=2; } else if (strncmp(argv[i], "--instid", strlen("--instid")) == 0) { if ((argv[i+1] == NULL) || (argv[i+1][0] == '-')) { fprintf(stderr, "No instance id supplied!\n"); usage(argv[0]); exit(1); } instid_opt = 1; strncpy(instanceName, argv[i+1], MAXPATHLEN); i+=2; } else { fprintf(stderr, "Unknown option %s\n", argv[i]); usage(argv[0]); exit(1); } } if (strlen(outputfile) > 0) { if ((output_fd=open(outputfile, O_RDWR|O_CREAT, 0600)) != -1) { _dup2(output_fd, 1); /* put stdout in file */ _dup2(output_fd, 2); /* put stderr in file */ } } /* prompt for password if not supplied with -p */ if ((c_opt || R_opt) && (strcmp(sa_password, "") == 0)) { prompt_to_get_password(sa_password); cache_usertoken_and_homedir(service_accountname, NULL, 0, read_sa_password, (char *)service_accountname, decrypt_sa_password, 1); } /* Need to get service_name */ if (R_opt || U_opt) { char *p = NULL; int k = 0; strcpy(service_name, service_bin_path); if ((p=strrchr(service_bin_path, '\\'))) { strcpy(service_name, p+1); } if ((p=strrchr(service_name, '.'))) {/*remove .exe portion*/ *p = '\0'; } /* translate from lower-case to upper-case */ for (k=0; k < strlen(service_name); k++) { service_name[k] = toupper(service_name[k]); } if (instid_opt) { strcat_s(service_name, MAXPATHLEN, "_"); strcat_s(service_name, MAXPATHLEN, instanceName); } } if (c_opt) { if (add_service_account(sa_password) == 0) { ret_val = 3; goto end_pbs_account; } } if (s_opt || R_opt) { /* need service account name */ sa_sid = getusersid2(service_accountname, sa_name); if (sa_sid == NULL) { fprintf(stderr, "%s not found!\n", service_accountname); ret_val= 1; goto end_pbs_account; } if (!isAdminPrivilege(service_accountname)) { fprintf(stderr, "%s is not ADMIN! - %s\n", service_accountname, winlog_buffer); ret_val = 2; goto end_pbs_account; } } if (s_opt) { int r1, r2, r3, r4; printf("Setting the following privileges to %s:\n", sa_name); r1 = add_privilege(sa_sid, SE_CREATE_TOKEN_NAME); r2 = add_privilege(sa_sid, SE_ASSIGNPRIMARYTOKEN_NAME); r3 = add_privilege(sa_sid, SE_SERVICE_LOGON_NAME); r4 = add_privilege(sa_sid, SE_TCB_NAME); if ((r1 != 0) || (r2 != 0) || (r3 != 0) || (r4 != 0)) { ret_val = 4; goto end_pbs_account; } } if (R_opt) { ret_val = register_scm(__TEXT(service_name), service_bin_path, sa_name, sa_password); } if (U_opt) { ret_val = unregister_scm(__TEXT(service_name)); } end_pbs_account: if (sa_sid != NULL) LocalFree(sa_sid); if (strlen(sa_password) > 0) memset((char *)sa_password, 0, strlen(sa_password)); if (output_fd != -1) (void)close(output_fd); exit(ret_val); }
int svr_chk_owner(struct batch_request *preq, job *pjob) { char owner[PBS_MAXUSER+1]; char *pu; char *ph; char rmtuser[PBS_MAXUSER+PBS_MAXHOSTNAME+2]; extern int ruserok(const char *rhost, int suser, const char *ruser, const char *luser); #ifdef WIN32 extern int user_read_password(char *user, char **cred, size_t *len); extern int read_cred(job *pjob, char **cred, size_t *len); extern int decrypt_pwd(char *crypted, size_t len, char **passwd); #endif /* Are the owner and requestor the same? */ snprintf(rmtuser, sizeof(rmtuser), "%s", pjob->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str); pu = rmtuser; ph = strchr(rmtuser, '@'); if (!ph) return -1; *ph++ = '\0'; if (strcmp(preq->rq_user, pu) == 0) { /* Avoid the lookup if they match. */ if (strcmp(preq->rq_host, ph) == 0) return 0; /* Perform the lookup. */ if (is_same_host(preq->rq_host, ph)) return 0; } /* map requestor user@host to "local" name */ pu = site_map_user(preq->rq_user, preq->rq_host); if (pu == NULL) return (-1); (void)strncpy(rmtuser, pu, PBS_MAXUSER); /* * Get job owner name without "@host" and then map to "local" name. */ get_jobowner(pjob->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str, owner); pu = site_map_user(owner, get_hostPart(pjob->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str)); if (server.sv_attr[(int)SRV_ATR_FlatUID].at_val.at_long) { /* with flatuid, all that must match is user names */ return (strcmp(rmtuser, pu)); } else { /* non-flatuid space, must validate rmtuser vs owner */ #ifdef WIN32 if ( (server.sv_attr[SRV_ATR_ssignon_enable].at_flags & \ ATR_VFLAG_SET) && \ (server.sv_attr[SRV_ATR_ssignon_enable].at_val.at_long \ == 1) ) { /* read/cache user password */ cache_usertoken_and_homedir(pu, NULL, 0, user_read_password, (char *)pu, pbs_decrypt_pwd, 0); } else { /* read/cache job password */ cache_usertoken_and_homedir(pu, NULL, 0, read_cred, (job *)pjob, pbs_decrypt_pwd, 0); } #endif return (ruserok(preq->rq_host, 0, rmtuser, pu)); } }
/** * @brief * add_service_account: creates the PBS service account if it doesn't exist, * otherwise, validate the password against the existing the service * account. * * @param[in] password - The password to be validated. * * @return int */ int add_service_account(char *password) { char dname[PBS_MAXHOSTNAME+1]; char dctrl[PBS_MAXHOSTNAME+1]; wchar_t unamew[UNLEN+1]; wchar_t dnamew[UNLEN+1]; wchar_t dctrlw[PBS_MAXHOSTNAME+1]; NET_API_STATUS nstatus; USER_INFO_1 *ui1_ptr = NULL; /* better indicator of lookup */ /* permission */ struct passwd *pw = NULL; char sa_name[PBS_MAXHOSTNAME+UNLEN+2]; /* service account fullname */ /* domain\user\0 */ int ret_val = 0; int in_domain_environment; USER_INFO_1 ui; wchar_t passwordw[LM20_PWLEN+1]; /* find domain name, group name to add service account to */ in_domain_environment = GetComputerDomainName(dname); strcpy(dctrl, dname); if (in_domain_environment) { char dname_a[PBS_MAXHOSTNAME+1]; get_dcinfo(dname, dname_a, dctrl); } mbstowcs(unamew, service_accountname, UNLEN+1); mbstowcs(dnamew, dname, PBS_MAXHOSTNAME+1); mbstowcs(dctrlw, dctrl, PBS_MAXHOSTNAME+1); /* create account if it doesn't exist */ /* FIX: Perform the following "if action" if either */ /* 1) in a domain environment, and the */ /* executing account (i.e. intaller) is an account in */ /* the domain, */ /* 2) in a standalone environment, and the */ /* executing account (i.e. installer) is a local account */ /* in the local computer. */ /* This fix is needed as during testing, I was finding that */ /* the local "Administrator" account itself has permission */ /* to query the domain, and to create accounts on the domain. */ /* However, the created domain "pbsadmin" account would have */ /* weirdness to it in that attempts to impersonate it would */ /* initially fail, and even after adding the account to the */ /* local "Administrators" group, that user entry on the group */ /* would suddenly disappear. */ if ((stricmp(exec_dname, dname) == 0) && ((nstatus=wrap_NetUserGetInfo(dctrlw, unamew, 1, (LPBYTE *)&ui1_ptr)) == NERR_UserNotFound)) { mbstowcs(passwordw, password, LM20_PWLEN+1); ui.usri1_name = (wchar_t *)unamew; ui.usri1_password = (wchar_t *)passwordw; ui.usri1_password_age = 0; ui.usri1_priv = USER_PRIV_USER; ui.usri1_home_dir = NULL; ui.usri1_comment = NULL; ui.usri1_flags = UF_PASSWD_CANT_CHANGE|UF_DONT_EXPIRE_PASSWD; ui.usri1_script_path = NULL; if (for_info_only) nstatus = NERR_Success; else nstatus=NetUserAdd(dctrlw, 1, (LPBYTE)&ui, NULL); if ((nstatus != NERR_Success) && (nstatus != NERR_UserExists)) { fprintf(stderr, "Failed to create %s\\%S: error status=%d\n", dname, unamew, nstatus); goto end_add_service_account; } printf("%s account %s\\%S\n", (for_info_only?"Creating":"Created"), dname, unamew); set_account_expiration(dnamew, dctrlw, unamew, TIMEQ_FOREVER); /* cache new token since the account was just created */ cache_usertoken_and_homedir(service_accountname, NULL, 0, read_sa_password, (char *)service_accountname, decrypt_sa_password, 1); if (add_to_administrators_group(dnamew, unamew) != 0) goto end_add_service_account; } /* Verify password */ if (pw == NULL) { pw = getpwnam(service_accountname); if (pw == NULL) { fprintf(stderr, "Password could not be validated against %s\\%s.\n", dname, service_accountname); goto end_add_service_account; } } /* validate password */ sprintf(sa_name, "%s\\%s", dname, service_accountname); if (!for_info_only) { if (pw->pw_userlogin != INVALID_HANDLE_VALUE) { if (ImpersonateLoggedOnUser(pw->pw_userlogin) == 0) { /* fail */ if (validate_account_password(sa_name, password) == 0) { /* we still call validate_account_password() as backup since */ /* under Windows 2000, LogonUser(), called from */ /* cache_usertoken_and_homedir(), might fail due to not */ /* having the SE_TCB_NAME privilege. This must be */ /* already set before calling the "cmd" process that */ /* executes the install program. */ fprintf(stderr, "Password did not validate against %s\\%s err=%d\n\nClick BACK button to retry a different password.\nClick NEXT button to abort installation.", dname, service_accountname, GetLastError()); goto end_add_service_account; } } else { printf("Validated password for %s\n", sa_name); RevertToSelf(); } } } else { printf("Validating password for %s\n", sa_name); } /* add service account to appropriate Admin group */ if (!for_info_only && !isLocalAdminMember(service_accountname)) { if (add_to_administrators_group(dnamew, unamew) != 0) goto end_add_service_account; } wcsset(passwordw, 0); ret_val = 1; if (for_info_only) { printf("%s will need the following privileges:\n", sa_name); printf("\n\tCreate Token Object\n"); printf("\n\tReplace Process Level Token\n"); printf("\n\tLogon On As a Service\n"); printf("\n\tAct As Part of the Operating System\n"); } end_add_service_account: if (ui1_ptr != NULL) NetApiBufferFree(ui1_ptr); return (ret_val); }
int set_objexid(void *pobj, int objtype, attribute *attrry) { int addflags = 0; int isowner; attribute *pattr; char *puser; char *pgrpn; char *owner; int idx_ul, idx_gl; int idx_owner, idx_euser, idx_egroup; int idx_acct; int bad_euser, bad_egrp; attribute *objattrs; attribute_def *obj_attr_def; attribute *paclRoot; /*future: aclRoot resv != aclRoot job*/ #ifdef WIN32 char user_s[PBS_MAXHOSTNAME+ MAXNAMLEN+3]; char *p = NULL; char *p0 = NULL; int ch = '\\'; SID *sid; char *defgrp = NULL; #else char **pmem; struct group *gpent; struct passwd *pwent; char gname[PBS_MAXGRPN+1]; #endif /* determine index values and pointers based on object type */ if (objtype == JOB_OBJECT) { idx_ul = (int)JOB_ATR_userlst; idx_gl = (int)JOB_ATR_grouplst; idx_owner = (int)JOB_ATR_job_owner; idx_euser = (int)JOB_ATR_euser; idx_egroup = (int)JOB_ATR_egroup; idx_acct = (int)JOB_ATR_account; obj_attr_def = job_attr_def; objattrs = ((job *)pobj)->ji_wattr; owner = ((job *)pobj)->ji_wattr[idx_owner].at_val.at_str; paclRoot = &server.sv_attr[(int)SRV_ATR_AclRoot]; bad_euser = PBSE_BADUSER; bad_egrp = PBSE_BADGRP; } else { idx_ul = (int)RESV_ATR_userlst; idx_gl = (int)RESV_ATR_grouplst; idx_owner = (int)RESV_ATR_resv_owner; idx_euser = (int)RESV_ATR_euser; idx_egroup = (int)RESV_ATR_egroup; idx_acct = (int)RESV_ATR_account; obj_attr_def = resv_attr_def; objattrs = ((resc_resv *)pobj)->ri_wattr; owner = ((resc_resv *)pobj)->ri_wattr[idx_owner].at_val.at_str; paclRoot = &server.sv_attr[(int)SRV_ATR_AclRoot]; bad_euser = PBSE_R_UID; bad_egrp = PBSE_R_GID; } /* if passed in "User_List" attribute is set use it - this may * be a newly modified one. * if not set, fall back to the object's User_List, which may * actually be the same as what is passed into this function */ if ((attrry + idx_ul)->at_flags & ATR_VFLAG_SET) pattr = attrry + idx_ul; else pattr = &objattrs[idx_ul]; if ((puser = determine_euser(pobj, objtype, pattr, &isowner)) == NULL) return (bad_euser); #ifdef WIN32 if (isAdminPrivilege(puser)) { /* equivalent of root */ if ((paclRoot->at_flags & ATR_VFLAG_SET) == 0) return (bad_euser); /* root not allowed */ if (acl_check(paclRoot, owner, ACL_User) == 0) return (bad_euser); /* root not allowed */ } #else pwent = getpwnam(puser); if (pwent == NULL) { if (!server.sv_attr[(int)SRV_ATR_FlatUID].at_val.at_long) return (bad_euser); } else if (pwent->pw_uid == 0) { if ((paclRoot->at_flags & ATR_VFLAG_SET) == 0) return (bad_euser); /* root not allowed */ if (acl_check(paclRoot, owner, ACL_User) == 0) return (bad_euser); /* root not allowed */ } #endif if (!isowner || !server.sv_attr[(int)SRV_ATR_FlatUID].at_val.at_long) { #ifdef WIN32 if ( (server.sv_attr[SRV_ATR_ssignon_enable].at_flags & \ ATR_VFLAG_SET) && \ (server.sv_attr[SRV_ATR_ssignon_enable].at_val.at_long \ == 1) ) { /* read/cache user password */ cache_usertoken_and_homedir(puser, NULL, 0, user_read_password, (char *)puser, pbs_decrypt_pwd, 0); } else { /* read/cache job password */ cache_usertoken_and_homedir(puser, NULL, 0, read_cred, (job *)pobj, pbs_decrypt_pwd, 0); } #endif if (site_check_user_map(pobj, objtype, puser) == -1) return (bad_euser); } pattr = &objattrs[idx_euser]; obj_attr_def[idx_euser].at_free(pattr); obj_attr_def[idx_euser].at_decode(pattr, NULL, NULL, puser); #ifndef WIN32 if (pwent != NULL) { #endif /* if account (qsub -A) is not specified, set to empty string */ pattr = &objattrs[idx_acct]; if ((pattr->at_flags & ATR_VFLAG_SET) == 0) { (void)obj_attr_def[idx_acct].at_decode(pattr, NULL, NULL, "\0"); } /* * now figure out (for this host) the effective/execute "group name" * for the object. * 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 it isn't set, use the object's group_list, which may in fact * be same as what was passed */ if ((attrry + idx_gl)->at_flags & ATR_VFLAG_SET) pattr = attrry + idx_gl; else pattr = &objattrs[idx_gl]; if ((pgrpn = determine_egroup(pobj, objtype, pattr)) != NULL) { /* user specified a group, group must exists and either */ /* must be user's primary group or the user must be in it */ #ifdef WIN32 if ((sid=getgrpsid(pgrpn)) == NULL) return (bad_egrp); /* no such group */ (void)LocalFree(sid); #else gpent = getgrnam(pgrpn); if (gpent == NULL) { if (pwent != NULL) /* no such group is allowed */ return (bad_egrp); /* only when no user (flatuid)*/ } else if (gpent->gr_gid != pwent->pw_gid) { /* not primary */ pmem = gpent->gr_mem; while (*pmem) { if (!strcmp(puser, *pmem)) break; ++pmem; } if (*pmem == 0) return (bad_egrp); /* user not in group */ } #endif addflags = ATR_VFLAG_SET; } else { /* Use user login group */ #ifdef WIN32 if ((defgrp=getdefgrpname(puser)) == NULL) return (bad_egrp); /* set to a group that ALL users belong to as default */ pgrpn = defgrp; #else gpent = getgrgid(pwent->pw_gid); if (gpent != NULL) { pgrpn = gpent->gr_name; /* use group name */ } else { (void)sprintf(gname, "%d", pwent->pw_gid); pgrpn = gname; /* turn gid into string */ } #endif /* * setting the DEFAULT flag is a "kludy" 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_SET | ATR_VFLAG_DEFLT; } #ifndef WIN32 } else { /* * null password entry, * set group to "default" and set default for Mom to use login group */ pgrpn = "-default-"; addflags = ATR_VFLAG_SET | ATR_VFLAG_DEFLT; } #endif pattr = attrry + idx_egroup; obj_attr_def[idx_egroup].at_free(pattr); if (addflags != 0) { obj_attr_def[idx_egroup].at_decode(pattr, NULL, NULL, pgrpn); pattr->at_flags |= addflags; } #ifdef WIN32 if (defgrp) (void)free(defgrp); #endif return (0); }