int job_or_resv_save_fs(void *pobj, int updatetype, int objtype) { int fds; int openflags; int redo; char *filename; char namebuf1[MAXPATHLEN+1]; char namebuf2[MAXPATHLEN+1]; char *path = (char*)0; char *err_msg = (char*)0; char *err_msgl = (char*)0; char *prefix = (char*)0; char *suffix = (char*)0; char *cpsuffix = (char*)0; char *p_oid = (char*)0; long *p_mtime = (long*)0; int *p_modified = (int*)0; void *pfixed = (void*)0; ssize_t i; size_t fixed_size; attribute_def *p_attr_def = (attribute_def*)0; attribute *wattr = (attribute*)0; int final_attr; int eventclass; int pmode; #ifdef WIN32 pmode = _S_IWRITE | _S_IREAD; #else pmode = 0600; #endif if (objtype == RESC_RESV_OBJECT || objtype == RESV_JOB_OBJECT) { #ifndef PBS_MOM /* MOM knows not of resc_resv structs */ resc_resv *presv; presv = (resc_resv *)pobj; err_msg = "reservation_save"; err_msgl = "Link in reservation_save failed"; path = path_resvs; prefix = presv->ri_qs.ri_fileprefix; suffix = RESV_FILE_SUFFIX; cpsuffix = RESV_FILE_COPY; p_modified = &presv->ri_modified; pfixed = (void *)&presv->ri_qs; fixed_size = sizeof(struct resvfix); p_attr_def = resv_attr_def; wattr = presv->ri_wattr; final_attr = RESV_ATR_LAST; p_mtime = &presv->ri_wattr[RESV_ATR_mtime].at_val.at_long; p_oid = presv->ri_qs.ri_resvID; eventclass = PBS_EVENTCLASS_RESV; #else /* PBS_MOM only: Execution will never come here for MOM */ return (-1); #endif } else if (objtype == JOB_OBJECT) { job *pj = (job *)pobj; #ifndef PBS_MOM /*MOM knows not of resc_resv structs*/ if (pj->ji_resvp) { int rc = 0; if (updatetype == SAVEJOB_QUICK) rc = job_or_resv_save((void *)pj->ji_resvp, SAVERESV_QUICK, RESC_RESV_OBJECT); else if ((updatetype == SAVEJOB_FULL) || (updatetype == SAVEJOB_FULLFORCE) || (updatetype == SAVEJOB_NEW)) rc = job_or_resv_save((void *)pj->ji_resvp, SAVERESV_FULL, RESC_RESV_OBJECT); if (rc) return (rc); } #endif err_msg = "job_save"; err_msgl = "Link in job_save failed"; path = path_jobs; if (*pj->ji_qs.ji_fileprefix != '\0') prefix = pj->ji_qs.ji_fileprefix; else prefix = pj->ji_qs.ji_jobid; suffix = JOB_FILE_SUFFIX; cpsuffix = JOB_FILE_COPY; p_modified = &pj->ji_modified; pfixed = (void *)&pj->ji_qs; fixed_size = sizeof(struct jobfix); p_attr_def = job_attr_def; wattr = pj->ji_wattr; final_attr = JOB_ATR_LAST; p_mtime = &pj->ji_wattr[JOB_ATR_mtime].at_val.at_long; p_oid = pj->ji_qs.ji_jobid; eventclass = PBS_EVENTCLASS_JOB; return (job_save_fs(pj, updatetype)); } else { /*Don't expect to get here; incorrect object type*/ return (-1); } (void)strcpy(namebuf1, path); /* directory path */ (void)strcat(namebuf1, prefix); (void)strcpy(namebuf2, namebuf1); /* setup for later */ (void)strcat(namebuf1, suffix); /*if an attribute changed (modified==1) update mtime*/ if (*p_modified) { *p_mtime = time_now; } if (updatetype == SAVEJOB_QUICK || updatetype == SAVERESV_QUICK) { openflags = O_WRONLY | O_Sync; fds = open(namebuf1, openflags, pmode); if (fds < 0) { log_err(errno, err_msg, "error on open"); return (-1); } #ifdef WIN32 secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif /* just write the "critical" base structure to the file */ while ((i = write(fds, (char *)pfixed, fixed_size)) != fixed_size) { if ((i < 0) && (errno == EINTR)) { /* retry the write */ if (lseek(fds, (off_t)0, SEEK_SET) < 0) { log_err(errno, err_msg, "lseek"); (void)close(fds); return (-1); } continue; } else { log_err(errno, err_msg, "quickwrite"); (void)close(fds); return (-1); } } #ifdef WIN32 if (_commit(fds) != 0) { log_err(errno, err_msg, "flushing job file to disk failed!"); (void)close(fds); return (-1); } #endif (void)close(fds); } else { /* * write the whole structure to the file. * For a update, this is done to a new file to protect the * old against crashs. * The file is written in four parts: * (1) the job (resc_resv) structure, * (2) the attributes in "encoded" form, * (3) the attributes in the "external" form, and last * (4) the dependency list. */ (void)strcat(namebuf2, cpsuffix); openflags = O_CREAT | O_WRONLY | O_Sync; #ifdef WIN32 fix_perms2(namebuf2, namebuf1); #endif if (updatetype == SAVEJOB_NEW || updatetype == SAVERESV_NEW) filename = namebuf1; else filename = namebuf2; fds = open(filename, openflags, pmode); if (fds < 0) { log_err(errno, err_msg, "open for full save"); return (-1); } #ifdef WIN32 secure_file(filename, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif redo = 0; /* try to save twice */ do { save_setup(fds); if (save_struct((char *)pfixed, fixed_size) != 0) { redo++; } else if (save_attr_fs(p_attr_def, wattr, final_attr) != 0) { redo++; } else if (save_flush() != 0) { redo++; } if (redo != 0) { if (lseek(fds, (off_t)0, SEEK_SET) < 0) { log_err(errno, err_msg, "full lseek"); redo++; } } } while (redo == 1); #ifdef WIN32 if (_commit(fds) != 0) { log_err(errno, err_msg, "flush job file to disk failed!"); close(fds); return (-1); } #endif (void)close(fds); if (redo > 1) { if (updatetype == SAVEJOB_FULL || updatetype == SAVEJOB_FULLFORCE || updatetype == SAVERESV_FULL) (void)unlink(namebuf2); return (-1); } if (updatetype == SAVEJOB_FULL || updatetype == SAVEJOB_FULLFORCE || updatetype == SAVERESV_FULL) { #ifdef WIN32 if (MoveFileEx(namebuf2, namebuf1, MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH) == 0) { errno = GetLastError(); sprintf(log_buffer, "MoveFileEx(%s,%s) failed!", namebuf2, namebuf1); log_err(errno, err_msg, log_buffer); } secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); #else if (rename(namebuf2, namebuf1) == -1) { log_event(PBSEVENT_ERROR|PBSEVENT_SECURITY, eventclass, LOG_ERR, p_oid, err_msgl); } #endif } *p_modified = 0; } return (0); }
int job_save_fs(job *pjob, int updatetype) { #ifndef PBS_MOM int isarray = 0; #endif /* PBS_MOM */ int fds; int i; char *filename; char namebuf1[MAXPATHLEN+1]; char namebuf2[MAXPATHLEN+1]; int openflags; int redo; int pmode; #ifdef WIN32 pmode = _S_IWRITE | _S_IREAD; #else pmode = 0600; #endif (void)strcpy(namebuf1, path_jobs); /* job directory path */ if (*pjob->ji_qs.ji_fileprefix != '\0') (void)strcat(namebuf1, pjob->ji_qs.ji_fileprefix); else (void)strcat(namebuf1, pjob->ji_qs.ji_jobid); (void)strcpy(namebuf2, namebuf1); /* setup for later */ (void)strcat(namebuf1, JOB_FILE_SUFFIX); /* if ji_modified is set, ie an attribute changed, then update mtime */ if (pjob->ji_modified) { pjob->ji_wattr[JOB_ATR_mtime].at_val.at_long = time_now; pjob->ji_wattr[JOB_ATR_mtime].at_flags |= ATR_VFLAG_MODCACHE; } /* don't save if SubJob unless FULLFORCE. This is done by Windows */ /* Server when ready to run job since separate send_job program needs */ /* needs to be able to read up job structure from disk, not sharing */ /* the memory structures */ if ((pjob->ji_qs.ji_svrflags & JOB_SVFLG_SubJob) && (updatetype != SAVEJOB_FULLFORCE)) { pjob->ji_modified = 0; return 0; /* don't save subjob */ } if (pjob->ji_qs.ji_jsversion != JSVERSION) { /* version of job structure changed, force full write */ pjob->ji_qs.ji_jsversion = JSVERSION; updatetype = SAVEJOB_FULLFORCE; } if (updatetype == SAVEJOB_QUICK) { openflags = O_WRONLY | O_Sync; fds = open(namebuf1, openflags, pmode); if (fds < 0) { log_err(errno, "job_save", "error on open"); return (-1); } #ifdef WIN32 secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif /* just write the "critical" base structure to the file */ save_setup(fds); if ((save_struct((char *)&pjob->ji_qs, fixedsize) == 0) && (save_struct((char *)&pjob->ji_extended, extndsize) == 0) && (save_flush() == 0)) { #ifdef WIN32 /* since the open() POSIX call provided does not */ /* have O_Sync for synchronous writes, the following */ /* will force flushing things onto disk */ if (_commit(fds) != 0) { log_err(errno, "job_save", "flushing file to disk failed!"); (void)close(fds); return (-1); } #endif (void)close(fds); } else { log_err(errno, "job_save", "error quickwrite"); (void)close(fds); return (-1); } } else { /* * write the whole structure to the file. * For a update, this is done to a new file to protect the * old against crashs. * The file is written in four parts: * (1) the job structure, * (2) the extended area, * (3) if a Array Job, the index tracking table * (4) the attributes in the "encoded "external form, and last * (5) the dependency list. */ #ifndef PBS_MOM /* * For an Array Job, we only update it to disk periodically, * otherwise we would be spending way too much time writting. */ isarray = (pjob->ji_qs.ji_svrflags & JOB_SVFLG_ArrayJob); if (isarray) { if ((pjob->ji_modifyct > 0) && (updatetype != SAVEJOB_FULLFORCE)) { pjob->ji_modifyct--; return 0; } else { /* reset count and do write this time */ pjob->ji_modifyct = 600; } } #endif (void)strcat(namebuf2, JOB_FILE_COPY); openflags = O_CREAT | O_WRONLY | O_Sync; #ifdef WIN32 fix_perms2(namebuf2, namebuf1); #endif if (updatetype == SAVEJOB_NEW) filename = namebuf1; else filename = namebuf2; fds = open(filename, openflags, pmode); if (fds < 0) { log_err(errno, "job_save", "error opening for full save"); return (-1); } #ifdef WIN32 secure_file(filename, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif for (i=0; i<MAX_SAVE_TRIES; ++i) { redo = 0; /* try to save twice */ save_setup(fds); if (save_struct((char *)&pjob->ji_qs, fixedsize) != 0) { redo++; } else if (save_struct((char *)&pjob->ji_extended, extndsize) != 0) { redo++; #ifndef PBS_MOM } else if (isarray && (save_struct((char *)pjob->ji_ajtrk, pjob->ji_ajtrk->tkm_size) != 0)) { redo++; #endif } else if (save_attr_fs(job_attr_def, pjob->ji_wattr, (int)JOB_ATR_LAST) != 0) { redo++; } else if (save_flush() != 0) { redo++; } if (redo != 0) { if (lseek(fds, (off_t)0, SEEK_SET) < 0) { log_err(errno, "job_save", "error lseek"); } } else break; } #ifdef WIN32 if (_commit(fds) != 0) { log_err(errno, "job_save", "flushing file to disk failed!"); (void)close(fds); return (-1); } #endif (void)close(fds); if (i >= MAX_SAVE_TRIES) { if ((updatetype == SAVEJOB_FULL) || (updatetype == SAVEJOB_FULLFORCE)) (void)unlink(namebuf2); return (-1); } if ((updatetype == SAVEJOB_FULL) || (updatetype == SAVEJOB_FULLFORCE)) { #ifdef WIN32 if (MoveFileEx(namebuf2, namebuf1, MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH) == 0) { errno = GetLastError(); sprintf(log_buffer, "MoveFileEx(%s,%s) failed!", namebuf2, namebuf1); log_err(errno, "job_save", log_buffer); } secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); #else if (rename(namebuf2, namebuf1) == -1) { log_event(PBSEVENT_ERROR|PBSEVENT_SECURITY, PBS_EVENTCLASS_JOB, LOG_ERR, pjob->ji_qs.ji_jobid, "rename in job_save failed"); } #endif } pjob->ji_modified = 0; } return (0); }
int que_save_fs(pbs_queue *pque) { int fds; int i; char namebuf1[MAXPATHLEN]; char namebuf2[MAXPATHLEN]; (void)strcpy(namebuf1, path_queues); (void)strcat(namebuf1, pque->qu_qs.qu_name); (void)strcpy(namebuf2, namebuf1); (void)strcat(namebuf2, ".new"); #ifdef WIN32 fix_perms2(namebuf2, namebuf1); #endif fds = open(namebuf2, O_CREAT | O_WRONLY | O_Sync, 0600); if (fds < 0) { sprintf(log_buffer, "error opening %s", namebuf2); log_err(errno, __func__, log_buffer); return (-1); } #ifdef WIN32 secure_file(namebuf2, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif /* set up save buffering system */ save_setup(fds); /* save basic queue structure (fixed length stuff) */ if (save_struct((char *)&pque->qu_qs, sizeof(struct queuefix)) != 0) { log_err(-1, __func__, "save_struct failed"); (void)close(fds); return (-1); } /* save queue attributes */ if (save_attr_fs(que_attr_def, pque->qu_attr, (int)QA_ATR_LAST) != 0) { log_err(-1, __func__, "save_attr failed"); (void)close(fds); return (-1); } if (save_flush() != 0) { /* flush the save buffer */ log_err(-1, __func__, "save_flush failed"); (void)close(fds); return (-1); } #ifdef WIN32 if (_commit(fds) != 0) { log_err(errno, __func__, "flush queue file to disk failed!"); close(fds); return (-1); } #endif (void)close(fds); #ifdef WIN32 if (MoveFileEx(namebuf2, namebuf1, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0) { errno = GetLastError(); sprintf(log_buffer, "MoveFileEx(%s, %s) failed!", namebuf2, namebuf1); log_err(errno, __func__, log_buffer); } secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); #else if (rename(namebuf2, namebuf1) < 0) log_err(errno, __func__, "unable to rename queue name"); #endif /* * now search queue's attributes for access control lists, * they are saved separately in their own file: * ../priv/(attr name)/(queue name) */ for (i=0; i < (int)QA_ATR_LAST; i++) { if (pque->qu_attr[i].at_type == ATR_TYPE_ACL) { save_acl(&pque->qu_attr[i], &que_attr_def[i], que_attr_def[i].at_name, pque->qu_qs.qu_name); } } return (0); }
int job_save_fs(job *pjob, int updatetype) { int fds; int i; char *filename; char namebuf1[MAXPATHLEN+1]; char namebuf2[MAXPATHLEN+1]; int openflags; int redo; int pmode; #ifdef WIN32 pmode = _S_IWRITE | _S_IREAD; #else pmode = 0600; #endif (void)strcpy(namebuf1, path_jobs); /* job directory path */ if (*pjob->ji_qs.ji_fileprefix != '\0') (void)strcat(namebuf1, pjob->ji_qs.ji_fileprefix); else (void)strcat(namebuf1, pjob->ji_qs.ji_jobid); (void)strcpy(namebuf2, namebuf1); /* setup for later */ (void)strcat(namebuf1, JOB_FILE_SUFFIX); /* if ji_modified is set, ie an attribute changed, then update mtime */ if (pjob->ji_modified) { pjob->ji_wattr[JOB_ATR_mtime].at_val.at_long = time_now; pjob->ji_wattr[JOB_ATR_mtime].at_flags |= ATR_VFLAG_MODCACHE; } if (pjob->ji_qs.ji_jsversion != JSVERSION) { /* version of job structure changed, force full write */ pjob->ji_qs.ji_jsversion = JSVERSION; updatetype = SAVEJOB_FULLFORCE; } if (updatetype == SAVEJOB_QUICK) { openflags = O_WRONLY; fds = open(namebuf1, openflags, pmode); if (fds < 0) { log_err(errno, "job_save", "error on open"); return (-1); } #ifdef WIN32 secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif /* just write the "critical" base structure to the file */ save_setup(fds); if ((save_struct((char *)&pjob->ji_qs, fixedsize) == 0) && (save_struct((char *)&pjob->ji_extended, extndsize) == 0) && (save_flush() == 0)) { (void)close(fds); } else { log_err(errno, "job_save", "error quickwrite"); (void)close(fds); return (-1); } } else { /* * write the whole structure to the file. * For a update, this is done to a new file to protect the * old against crashs. * The file is written in four parts: * (1) the job structure, * (2) the extended area, * (3) if a Array Job, the index tracking table * (4) the attributes in the "encoded "external form, and last * (5) the dependency list. */ (void)strcat(namebuf2, JOB_FILE_COPY); openflags = O_CREAT | O_WRONLY; #ifdef WIN32 fix_perms2(namebuf2, namebuf1); #endif if (updatetype == SAVEJOB_NEW) filename = namebuf1; else filename = namebuf2; fds = open(filename, openflags, pmode); if (fds < 0) { log_err(errno, "job_save", "error opening for full save"); return (-1); } #ifdef WIN32 secure_file(filename, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fds, O_BINARY); #endif for (i=0; i<MAX_SAVE_TRIES; ++i) { redo = 0; /* try to save twice */ save_setup(fds); if (save_struct((char *)&pjob->ji_qs, fixedsize) != 0) { redo++; } else if (save_struct((char *)&pjob->ji_extended, extndsize) != 0) { redo++; #ifndef PBS_MOM } else if ((pjob->ji_qs.ji_svrflags & JOB_SVFLG_ArrayJob) && (save_struct((char *)pjob->ji_ajtrk, pjob->ji_ajtrk->tkm_size) != 0)) { redo++; #endif } else if (save_attr_fs(job_attr_def, pjob->ji_wattr, (int)JOB_ATR_LAST) != 0) { redo++; } else if (save_flush() != 0) { redo++; } if (redo != 0) { if (lseek(fds, (off_t)0, SEEK_SET) < 0) { log_err(errno, "job_save", "error lseek"); } } else break; } (void)close(fds); if (i >= MAX_SAVE_TRIES) { if ((updatetype == SAVEJOB_FULL) || (updatetype == SAVEJOB_FULLFORCE)) (void)unlink(namebuf2); return (-1); } if ((updatetype == SAVEJOB_FULL) || (updatetype == SAVEJOB_FULLFORCE)) { #ifdef WIN32 if (MoveFileEx(namebuf2, namebuf1, MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH) == 0) { errno = GetLastError(); sprintf(log_buffer, "MoveFileEx(%s,%s) failed!", namebuf2, namebuf1); log_err(errno, "job_save", log_buffer); } secure_file(namebuf1, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); #else if (rename(namebuf2, namebuf1) == -1) { log_event(PBSEVENT_ERROR|PBSEVENT_SECURITY, PBS_EVENTCLASS_JOB, LOG_ERR, pjob->ji_qs.ji_jobid, "rename in job_save failed"); } #endif } pjob->ji_modified = 0; } return (0); }
/** * @brief * The main function in C - entry point * * @param[in] argc - argument count * @param[in] argv - pointer to argument array * * @return int * @retval 0 - success * @retval !0 - error */ int main(int argc, char *argv[]) { int i, rc; char passwd[MAX_PASSWORD_LEN + 1] = {'\0'}; char passwd2[MAX_PASSWORD_LEN + 1]; char *pquoted; char pwd_file[MAXPATHLEN + 1]; char userid[LOGIN_NAME_MAX + 1]; int fd, errflg = 0; int gen_pwd = 0; char sqlbuff[1024]; int db_conn_error=0; char *db_errmsg = NULL; int pmode; int change_user = 0; char *olduser; int update_db = 0; char getopt_format[5]; char prog[]="pbs_ds_password"; char errmsg[PBS_MAX_DB_CONN_INIT_ERR + 1]; conn = NULL; pwd_file_new[0]=0; /*test for real deal or just version and exit*/ PRINT_VERSION_AND_EXIT(argc, argv); /* read configuration file */ if (pbs_loadconf(0) == 0) { fprintf(stderr, "%s: Could not load pbs configuration\n", prog); return (-1); } /* backup old user name */ if ((olduser = pbs_get_dataservice_usr(errmsg, PBS_MAX_DB_CONN_INIT_ERR)) == NULL) { fprintf(stderr, "%s: Could not retrieve current data service user\n", prog); if (strlen(errmsg) > 0) fprintf(stderr, "%s\n", errmsg); return (-1); } if (pbs_conf.pbs_data_service_host == NULL) update_db = 1; userid[0]=0; /* empty user id */ strcpy(getopt_format, "rC:"); while ((i = getopt(argc, argv, getopt_format)) != EOF) { switch (i) { case 'r': gen_pwd = 1; break; case 'C': strcpy(userid, optarg); break; case '?': default: errflg++; } } if (errflg) { fprintf(stderr, "\nusage:\t%s [-r] [-C username]\n", prog); fprintf(stderr, " \t%s --version\n", prog); return (-1); } /* NOTE : This functionality is added just for the automation testing purpose. * Usage: pbs_ds_password <password> */ if (argv[optind] != NULL) { gen_pwd = 0; strncpy(passwd, argv[optind], sizeof(passwd)); passwd[sizeof(passwd) - 1] = '\0'; } /* check admin privileges */ #ifdef WIN32 if (!isAdminPrivilege(getlogin())) { fprintf(stderr, "pbs_ds_password: Must be run by Admin\n"); return (1); } #else if ((getuid() != 0) || (geteuid() != 0)) { fprintf(stderr, "%s: Must be run by root\n", prog); return (1); } #endif /* WIN32 */ change_user = 0; /* if the -C option was specified read the user from pbs.conf */ if (userid[0] != 0) { if (strcmp(olduser, userid) != 0) { change_user = 1; } } if (change_user == 1) { /* check that the supplied user-id exists (and is non-root on unix) */ if (check_user(userid) != 0) { #ifdef WIN32 fprintf(stderr, "\n%s: User-id %s does not exist\n", prog, userid); #else fprintf(stderr, "\n%s: User-id %s does not exist/is root user/home dir is not accessible\n", prog, userid); #endif return (-1); } } atexit(cleanup); if (update_db == 1) { /* then connect to database */ conn = pbs_db_init_connection(NULL, PBS_DB_CNT_TIMEOUT_NORMAL, 1, &db_conn_error, errmsg, PBS_MAX_DB_CONN_INIT_ERR); if (!conn) { get_db_errmsg(db_conn_error, &db_errmsg); fprintf(stderr, "%s: %s\n", prog, db_errmsg); if (strlen(errmsg) > 0) fprintf(stderr, "%s\n", errmsg); return -1; } db_conn_error = pbs_db_connect(conn); if (db_conn_error == PBS_DB_SUCCESS && change_user == 1) { /* able to connect ? Thats bad, PBS or dataservice is running */ fprintf(stderr, "%s: PBS Services and/or PBS Data Service is running\n", prog); fprintf(stderr, " Stop PBS and Data Services before changing Data Service user\n"); return (-1); } if (db_conn_error != PBS_DB_SUCCESS) { if (db_conn_error == PBS_DB_CONNREFUSED) { /* start db only if it was not already running */ if (pbs_startup_db(&db_errmsg) != 0) { if (db_errmsg) fprintf(stderr, "%s: Failed to start PBS dataservice:[%s]\n", prog, db_errmsg); else fprintf(stderr, "%s: Failed to start PBS dataservice\n", prog); return (-1); } started_db = 1; } db_conn_error = pbs_db_connect(conn); if (db_conn_error != PBS_DB_SUCCESS) { get_db_errmsg(db_conn_error, &db_errmsg); if (conn->conn_db_err) fprintf(stderr, "%s: Could not connect to PBS data service:%s:[%s]\n", prog, db_errmsg, (char*)conn->conn_db_err); else fprintf(stderr, "%s: Could not connect to PBS data service:%s\n", prog, db_errmsg); return (-1); } } } if (gen_pwd == 0 && passwd[0] == '\0') { /* ask user to enter password twice */ printf("Enter the password:"******"\nRe-enter the password:"******"\n\n"); if (strcmp(passwd, passwd2) != 0) { fprintf(stderr, "Entered passwords do not match\n"); return (-2); } if (strlen(passwd) == 0) { fprintf(stderr, "Blank password is not allowed\n"); return (-2); } } else if (gen_pwd == 1) { gen_password(passwd, 16); } rc = pbs_encrypt_pwd(passwd, &cred_type, &cred_buf, &cred_len); if (rc != 0) { fprintf(stderr, "%s: Failed to encrypt password\n", prog); return (-1); } /* escape password to use in sql strings later */ if ((pquoted = pbs_db_escape_str(conn, passwd)) == NULL) { fprintf(stderr, "%s: Out of memory\n", prog); return -1; } #ifdef WIN32 sprintf(pwd_file_new, "%s\\server_priv\\db_password.new", pbs_conf.pbs_home_path); sprintf(pwd_file, "%s\\server_priv\\db_password", pbs_conf.pbs_home_path); #else sprintf(pwd_file_new, "%s/server_priv/db_password.new", pbs_conf.pbs_home_path); sprintf(pwd_file, "%s/server_priv/db_password", pbs_conf.pbs_home_path); #endif /* write encrypted password to the password file */ #ifdef WIN32 pmode = _S_IWRITE | _S_IREAD; fix_perms2(pwd_file_new, pwd_file); if ((fd = open(pwd_file_new, O_WRONLY | O_TRUNC | O_CREAT | O_Sync | O_BINARY, pmode)) == -1) #else pmode = 0600; if ((fd = open(pwd_file_new, O_WRONLY | O_TRUNC | O_CREAT | O_Sync, pmode)) == -1) #endif { perror("open/create failed"); fprintf(stderr, "%s: Unable to create file %s\n", prog, pwd_file_new); return (-1); } #ifdef WIN32 secure_file(pwd_file_new, "Administrators", READS_MASK|WRITES_MASK|STANDARD_RIGHTS_REQUIRED); setmode(fd, O_BINARY); #endif if (update_db == 1) { /* change password only if this config option is not set */ if (pbs_db_begin_trx(conn, 0, 0) != 0) { fprintf(stderr, "%s: Could not start transaction\n", prog); unlink(pwd_file_new); return -1; } if (change_user == 1) { /* check whether user exists */ snprintf(sqlbuff, sizeof(sqlbuff), "select usename from pg_user where usename = '%s'", userid); if (pbs_db_execute_str(conn, sqlbuff) == 1) { /* now attempt to create new user & set the database passwd to the un-encrypted password */ snprintf(sqlbuff, sizeof(sqlbuff), "create user \"%s\" SUPERUSER ENCRYPTED PASSWORD '%s'", userid, pquoted); } else { /* attempt to alter new user & set the database passwd to the un-encrypted password */ snprintf(sqlbuff, sizeof(sqlbuff), "alter user \"%s\" SUPERUSER ENCRYPTED PASSWORD '%s'", userid, pquoted); } memset(passwd, 0, sizeof(passwd)); memset(passwd2, 0, sizeof(passwd2)); memset(pquoted, 0, (sizeof(char) * strlen(pquoted))); if (pbs_db_execute_str(conn, sqlbuff) == -1) { fprintf(stderr, "%s: Failed to create/alter user id %s\n", prog, userid); (void) pbs_db_end_trx(conn, PBS_DB_ROLLBACK); return -1; } } else { /* now attempt to set the database passwd to the un-encrypted password */ /* alter user ${user} SUPERUSER ENCRYPTED PASSWORD '${passwd}' */ sprintf(sqlbuff, "alter user \"%s\" SUPERUSER ENCRYPTED PASSWORD '%s'", olduser, pquoted); memset(passwd, 0, sizeof(passwd)); memset(passwd2, 0, sizeof(passwd2)); memset(pquoted, 0, (sizeof(char) * strlen(pquoted))); if (pbs_db_execute_str(conn, sqlbuff) == -1) { fprintf(stderr, "%s: Failed to create/alter user id %s\n", prog, userid); (void) pbs_db_end_trx(conn, PBS_DB_ROLLBACK); return -1; } } } if (write(fd, cred_buf, cred_len) != cred_len) { perror("write failed"); fprintf(stderr, "%s: Unable to write to file %s\n", prog, pwd_file_new); if (update_db == 1) { (void) pbs_db_end_trx(conn, PBS_DB_ROLLBACK); } return -1; } close(fd); free(cred_buf); #ifdef WIN32 if (MoveFileEx(pwd_file_new, pwd_file, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0) { errno = GetLastError(); fprintf(stderr, "MoveFileEx(%s, %s) failed!", pwd_file_new, pwd_file); if (update_db == 1) { (void) pbs_db_end_trx(conn, PBS_DB_ROLLBACK); } return (-1); } #else if (rename(pwd_file_new, pwd_file) != 0) { if (update_db == 1) { (void) pbs_db_end_trx(conn, PBS_DB_ROLLBACK); } return (-1); } #endif if (update_db == 1) { /* commit to database */ (void) pbs_db_end_trx(conn, PBS_DB_COMMIT); cleanup(); /* cleanup will disconnect and delete tmp file too */ } printf("---> Updated user password\n"); if (update_db == 1 && change_user == 1) { printf("---> Updated user in datastore\n"); printf("---> Stored user password in datastore\n"); } if (change_user == 1) { char usr_file[MAXPATHLEN + 1]; #ifdef WIN32 sprintf(usr_file, "%s\\server_priv\\db_user", pbs_conf.pbs_home_path); #else sprintf(usr_file, "%s/server_priv/db_user", pbs_conf.pbs_home_path); #endif /* update PBS_HOME/server_priv/db_user file with the new user name */ if (update_db_usr(usr_file, userid) != 0) { fprintf(stderr, "Unable to update file %s\n", usr_file); return -1; } printf("---> Updated new user\n"); } if (update_db == 1 && change_user == 1) { char datastore[MAXPATHLEN + 1]; #ifndef WIN32 /* ownership is changed only for Unix users * On windows, these files are allways owned by the user who installed the database * and writable by administrators anyway */ sprintf(datastore, "%s/datastore", pbs_conf.pbs_home_path); /* change ownership of the datastore directories to the new user, so that db can be started again */ if (change_ownership(datastore, userid) != 0) { fprintf(stderr, "%s: Failed to change ownership on path %s\n", prog, datastore); return -1; } printf("---> Changed ownership of %s to user %s\n", datastore, userid); #endif /* reload configuration file */ if (pbs_loadconf(1) == 0) { fprintf(stderr, "%s: Could not load pbs configuration\n", prog); return (-1); } if (pbs_startup_db(&db_errmsg) != 0) { if (db_errmsg) fprintf(stderr, "%s: Failed to start PBS dataservice as new user:[%s]\n", prog, db_errmsg); else fprintf(stderr, "%s: Failed to start PBS dataservice as new user\n", prog); return (-1); } started_db = 1; /* connect again to drop the old user */ conn = pbs_db_init_connection(NULL, PBS_DB_CNT_TIMEOUT_NORMAL, 1, &db_conn_error, errmsg, PBS_MAX_DB_CONN_INIT_ERR); if (!conn) { get_db_errmsg(db_conn_error, &db_errmsg); fprintf(stderr, "%s: %s\n", prog, db_errmsg); if (strlen(errmsg) > 0) fprintf(stderr, "%s\n", errmsg); return -1; } db_conn_error = pbs_db_connect(conn); if (db_conn_error != PBS_DB_SUCCESS) { get_db_errmsg(db_conn_error, &db_errmsg); if (conn->conn_db_err) fprintf(stderr, "%s: Could not connect to PBS data service as new user:%s[%s]\n", prog, db_errmsg, (char*)conn->conn_db_err); else fprintf(stderr, "%s: Could not connect to PBS data service as new user:%s\n", prog, db_errmsg); return (-1); } /* delete the old user from the database */ sprintf(sqlbuff, "drop user \"%s\"", olduser); pbs_db_execute_str(conn, sqlbuff); } printf("---> Success\n"); return (0); }