static int _update_passwd(const char *forwho, const char *towhat) { struct passwd *tmpent = NULL; FILE *pwfile, *opwfile; int err = 1; int oldmask; oldmask = umask(077); pwfile = fopen(PW_TMPFILE, "w"); umask(oldmask); if (pwfile == NULL) { return PAM_AUTHTOK_ERR; } opwfile = fopen("/etc/passwd", "r"); if (opwfile == NULL) { fclose(pwfile); return PAM_AUTHTOK_ERR; } chown(PW_TMPFILE, 0, 0); chmod(PW_TMPFILE, 0644); tmpent = fgetpwent(opwfile); while (tmpent) { if (!strcmp(tmpent->pw_name, forwho)) { /* To shut gcc up */ union { const char *const_charp; char *charp; } assigned_passwd; assigned_passwd.const_charp = towhat; tmpent->pw_passwd = assigned_passwd.charp; err = 0; } if (putpwent(tmpent, pwfile)) { D(("error writing entry to password file: %s\n", strerror(errno))); err = 1; break; } tmpent = fgetpwent(opwfile); } fclose(opwfile); if (fclose(pwfile)) { D(("error writing entries to password file: %s\n", strerror(errno))); err = 1; } if (!err) { rename(PW_TMPFILE, "/etc/passwd"); return PAM_SUCCESS; } else { unlink(PW_TMPFILE); return PAM_AUTHTOK_ERR; } }
void LoginView::PopulateIcons() { try { FILE* fp = fopen("/etc/passwd","r"); struct passwd* psPwd; int nIcon = 0; while((psPwd = fgetpwent( fp )) != NULL ) { // Let's remove users that don't need to be there and then add them to the iconview // System users (eg "www", "mail") have uids between 1 and 99. Filter them out. if( psPwd->pw_uid >= 100 || psPwd->pw_uid == 0 ) { pcUserIconView->AddIcon(GetImageFromIcon(psPwd->pw_name),new IconData()); pcUserIconView->AddIconString(nIcon,psPwd->pw_name); nIcon++; } } pcUserIconView->Layout(); } catch (...) { Alert* pcError = new Alert("Unable to load users","I am unable to load users, please contact the Syllable development group.",0x00,"Oh no!!!",NULL); pcError->Go(new Invoker()); } }
static struct passwd * entry_generator_fgetpwent (GHashTable *users, gpointer *state) { struct passwd *pwent; FILE *fp; /* First iteration */ if (*state == NULL) { *state = fp = fopen (PATH_PASSWD, "r"); if (fp == NULL) { g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno)); return NULL; } } /* Every iteration */ fp = *state; pwent = fgetpwent (fp); if (pwent != NULL) { return pwent; } /* Last iteration */ fclose (fp); *state = NULL; return NULL; }
static struct passwd * getpwnam_virtual (const char *u) { struct passwd *pw = NULL; FILE *pfile; size_t i = 0, len = strlen (u), delim = 0; char *filename; for (i = 0; i < len && delim == 0; i++) if (u[i] == '!' || u[i] == ':' || u[i] == '@') delim = i; if (delim == 0) return NULL; filename = mu_make_file_name (mu_virtual_module_config.pwddir, &u[delim + 1]); if (filename == NULL) return NULL; pfile = fopen (filename, "r"); free (filename); if (pfile) { while ((pw = fgetpwent (pfile)) != NULL) { if (strlen (pw->pw_name) == delim && strncmp (u, pw->pw_name, delim) == 0) break; } fclose (pfile); } return pw; }
int nischeck(char *namep) { char password_file[] = "/etc/passwd"; FILE *fd; struct passwd *ent = NULL; if ((fd = fopen (password_file, "r")) == NULL) { /* * If the passwd file has dissapeared we are in a bad state. * However, returning 0 will send us back through the * authentication scheme that has checked the ia database for * passwords earlier. */ return(0); } /* * fgetpwent() only reads from password file, so we know for certain * that the user is local. */ while (ent = fgetpwent(fd)) { if (strcmp (ent->pw_name, namep) == 0) { /* Local user */ fclose (fd); return(0); } } fclose (fd); return (1); }
static struct passwd *auth_get_passwd_from_uid(uid_t uid) { if(alternate_passwd_file[0]) { #ifdef CCTOOLS_OPSYS_DRAGONFLY debug(D_AUTH, "unix: couldn't open %s: %s", alternate_passwd_file, strerror(errno)); return 0; #else struct passwd *p; FILE *file; file = fopen(alternate_passwd_file, "r"); if(file) { while(1) { p = fgetpwent(file); if(!p) break; if(p->pw_uid == uid) { fclose(file); return p; } } fclose(file); return 0; } else { debug(D_AUTH, "unix: couldn't open %s: %s", alternate_passwd_file, strerror(errno)); return 0; } #endif } else { return getpwuid(uid); } }
// Uses fgetpwent() instead of getpwnam(), to guarantee that the returned user // is a local user, and not for example from LDAP. static struct passwd *GetPwEntry(const char *puser) { FILE *fptr = fopen("/etc/passwd", "r"); if (!fptr) { Log(LOG_LEVEL_ERR, "Could not open '/etc/passwd': %s", GetErrorStr()); return NULL; } struct passwd *passwd_info; bool found = false; while ((passwd_info = fgetpwent(fptr))) { if (strcmp(puser, passwd_info->pw_name) == 0) { found = true; break; } } fclose(fptr); if (found) { return passwd_info; } else { // Failure to find the user means we just set errno to zero. // Perhaps not optimal, but we cannot pass ENOENT, because the fopen might // fail for this reason, and that should not be treated the same. errno = 0; return NULL; } }
int main(int argc, char **argv) { char fbuf[PATH_MAX+1], *fb; FILE *pwf; int c; struct passwd *pw; struct disk *entry; while ((c = getopt(argc, argv, "p:u:")) != EOF) { switch (c) { case 'u': if ((nchrg = fopen(optarg, "w")) == NULL) openerr(optarg); (void) chmod(optarg, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break; case 'p': pfile = optarg; break; default: exit(1); } } if (pfile) { if ((pwf = fopen(pfile, "r")) == NULL) { openerr(pfile); } /* fill usglist with the user's in the passwd file */ while ((pw = fgetpwent(pwf)) != NULL) { if ((entry = hash_find(pw->pw_uid)) == NULL) entry = hash_insert(pw->pw_uid); validate_entry(entry, pw); } (void) fclose(pwf); } /* charge the files listed in names to users listed in the usglist */ while (fgets(fbuf, sizeof (fbuf), stdin) != NULL) { if ((fb = strchr(fbuf, '\n')) != NULL) { /* * replace the newline char at the end of the * filename with a null character */ *fb = '\0'; } charge(fbuf); } output(); if (nchrg) (void) fclose(nchrg); #ifdef DEBUG pdisk(); #endif return (0); }
static int _update_passwd(const char *forwho, const char *towhat) { struct passwd *tmpent = NULL; FILE *pwfile, *opwfile; int retval = 0; int err = 0; int oldmask; oldmask = umask(077); pwfile = fopen(PW_TMPFILE, "w"); umask(oldmask); opwfile = fopen("/etc/passwd", "r"); if (pwfile == NULL || opwfile == NULL) return PAM_AUTHTOK_ERR; chown(PW_TMPFILE, 0, 0); chmod(PW_TMPFILE, 0644); tmpent = fgetpwent(opwfile); while (tmpent) { if (!strcmp(tmpent->pw_name, forwho)) { tmpent->pw_passwd = towhat; } if (putpwent(tmpent, pwfile)) { fprintf(stderr, "error writing entry to password file: %s\n", strerror(errno)); err = 1; retval = PAM_AUTHTOK_ERR; break; } tmpent = fgetpwent(opwfile); } fclose(opwfile); if (fclose(pwfile)) { fprintf(stderr, "error writing entries to password file: %s\n", strerror(errno)); retval = PAM_AUTHTOK_ERR; err = 1; } if (!err) rename(PW_TMPFILE, "/etc/passwd"); else unlink(PW_TMPFILE); return retval; }
static struct passwd *p_getpwent(void) { if (!pwdf) p_setpwent(); if (!pwdf) return NULL; return fgetpwent(pwdf); }
static struct passwd *af_getpwent(void) { struct passwd *pwd = NULL, *res = NULL; if (af_user_file == NULL || af_user_file->af_file == NULL) { errno = EINVAL; return NULL; } while (TRUE) { #ifdef HAVE_FGETPWENT pr_signals_handle(); pwd = fgetpwent(af_user_file->af_file); #else char buf[BUFSIZ+1] = {'\0'}; pr_signals_handle(); memset(buf, '\0', sizeof(buf)); pwd = NULL; while (fgets(buf, sizeof(buf)-1, af_user_file->af_file) != NULL) { pr_signals_handle(); af_user_file->af_lineno++; /* Ignore empty and comment lines */ if (buf[0] == '\0' || buf[0] == '#') { memset(buf, '\0', sizeof(buf)); continue; } buf[strlen(buf)-1] = '\0'; pwd = af_getpasswd(buf, af_user_file->af_lineno); break; } #endif /* !HAVE_FGETPWENT */ /* If pwd is NULL now, the file is empty - nothing more to be read. */ if (pwd == NULL) { break; } if (af_allow_pwent(pwd) < 0) { #ifndef HAVE_FGETPWENT memset(buf, '\0', sizeof(buf)); #endif continue; } res = pwd; break; } return res; }
PASS_R_RETURN fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) { struct passwd *pw = fgetpwent(f); int res; if (pw == NULL) return (PASS_R_BAD); res = copy_passwd(pw, pwptr, PASS_R_COPY); return (res ? PASS_R_BAD : PASS_R_OK); }
struct passwd * getpwent(void) { if (!pwdb) { open_it(); } if (!pwdb) { return NULL; } return fgetpwent(pwdb); }
struct passwd *getpwent (void) { struct passwd *(*o_getpwent)(void) = NULL; if (!pwstream) pwstream = fopen(passwd_file, "r"); if (pwstream) { struct passwd *pw = fgetpwent(pwstream); if (pw) return pw; } if (!o_getpwent) o_getpwent = dlsym(RTLD_NEXT, "getpwent"); return o_getpwent(); }
/* EDR recoded such that the uid may be passed in *p */ static int passwd_study(const char *filename, struct passwd *p) { struct passwd *pw; FILE *passwd; const int min = 500; const int max = 65000; passwd = bb_wfopen(filename, "r"); if (!passwd) return 4; /* EDR if uid is out of bounds, set to min */ if ((p->pw_uid > max) || (p->pw_uid < min)) p->pw_uid = min; /* stuff to do: * make sure login isn't taken; * find free uid and gid; */ while ((pw = fgetpwent(passwd))) { if (strcmp(pw->pw_name, p->pw_name) == 0) { /* return 0; */ return 1; } if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max) && (pw->pw_uid >= min)) { p->pw_uid = pw->pw_uid + 1; } } if (p->pw_gid == 0) { /* EDR check for an already existing gid */ while (getgrgid(p->pw_uid) != NULL) p->pw_uid++; /* EDR also check for an existing group definition */ if (getgrnam(p->pw_name) != NULL) return 3; /* EDR create new gid always = uid */ p->pw_gid = p->pw_uid; } /* EDR bounds check */ if ((p->pw_uid > max) || (p->pw_uid < min)) return 2; /* return 1; */ return 0; }
struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[]) { sec_passwd_rec_t pwr; sec_login_handle_t lhdl; boolean32 rstpwd; sec_login_auth_src_t asrc; error_status_t status; FILE *fd; /* easy case */ if (pw->pw_passwd && pw->pw_passwd[0] && pw->pw_passwd[1] && !strcmp (pw->pw_passwd,(char *) crypt (pass,pw->pw_passwd))) return pw; /* try DCE password cache file */ if (fd = fopen (PASSWD_OVERRIDE,"r")) { char *usr = cpystr (pw->pw_name); while ((pw = fgetpwent (fd)) && strcmp (usr,pw->pw_name)); fclose (fd); /* finished with cache file */ /* validate cached password */ if (pw && pw->pw_passwd && pw->pw_passwd[0] && pw->pw_passwd[1] && !strcmp (pw->pw_passwd,(char *) crypt (pass,pw->pw_passwd))) { fs_give ((void **) &usr); return pw; } if (!pw) pw = getpwnam (usr); fs_give ((void **) &usr); } if (pw) { /* try S-L-O-W DCE... */ sec_login_setup_identity ((unsigned_char_p_t) pw->pw_name, sec_login_no_flags,&lhdl,&status); if (status == error_status_ok) { pwr.key.tagged_union.plain = (idl_char *) pass; pwr.key.key_type = sec_passwd_plain; pwr.pepper = NIL; pwr.version_number = sec_passwd_c_version_none; /* validate password with login context */ sec_login_validate_identity (lhdl,&pwr,&rstpwd,&asrc,&status); if (!rstpwd && (asrc == sec_login_auth_src_network) && (status == error_status_ok)) { sec_login_purge_context (&lhdl,&status); if (status == error_status_ok) return pw; } } } return NIL; /* password validation failed */ }
struct passwd *getpwuid (__uid_t __uid) { struct passwd *(*o_getpwuid)(__uid_t __uid) = NULL; struct passwd *pw; FILE *pwf = fopen(passwd_file, "r"); if (pwf) { do { pw = fgetpwent(pwf); if (pw && pw->pw_uid == __uid) break; } while (pw); fclose(pwf); if (pw && pw->pw_uid == __uid) return pw; } if (!o_getpwuid) o_getpwuid = dlsym(RTLD_NEXT, "getpwuid"); return o_getpwuid(__uid); }
struct passwd *getpwnam (const char *__name) { struct passwd *(*o_getpwnam)(const char *__name) = NULL; struct passwd *pw; FILE *pwf = fopen(passwd_file, "r"); if (pwf) { do { pw = fgetpwent(pwf); if (pw && !strcmp(pw->pw_name, __name)) break; } while (pw); fclose(pwf); if (pw && !strcmp(pw->pw_name, __name)) return pw; } if (!o_getpwnam) o_getpwnam = dlsym(RTLD_NEXT, "getpwnam"); return o_getpwnam(__name); }
// the same as getpwnam(), but it only parses /etc/passwd and allows name to be id string struct passwd *hyper_getpwnam(const char *name) { uid_t uid = (uid_t)id_or_max(name); FILE *file = fopen("/etc/passwd", "r"); if (!file) { perror("faile to open /etc/passwd"); return NULL; } for (;;) { struct passwd *pwd = fgetpwent(file); if (!pwd) break; if (!strcmp(pwd->pw_name, name) || pwd->pw_uid == uid) { fclose(file); return pwd; } } fclose(file); return NULL; }
long my_getpwnam(const char *name) { struct passwd *myuser; FILE *stream; stream = bb_xfopen(PASSWD_PATH, "r"); while(1) { errno = 0; myuser = fgetpwent(stream); if (myuser == NULL) bb_error_msg_and_die("unknown user name: %s", name); if (errno) bb_perror_msg_and_die("fgetpwent"); if (!strcmp(name, myuser->pw_name)) break; } fclose(stream); return myuser->pw_uid; }
int toaru_auth_check_pass(char * user, char * pass) { /* Generate SHA512 */ char hash[SHA512_DIGEST_STRING_LENGTH]; SHA512_Data(pass, strlen(pass), hash); /* Open up /etc/master.passwd */ FILE * master = fopen(MASTER_PASSWD, "r"); struct passwd * p; while ((p = fgetpwent(master))) { if (!strcmp(p->pw_name, user) && !strcmp(p->pw_passwd, hash)) { fclose(master); return p->pw_uid; } } fclose(master); return -1; }
/* return -1 if no valid user was found */ int __magic_find_user(char* user_buf, unsigned int user_name_len){ FILE* passwd_fd; struct passwd* pass; /* open /etc/passwd */ passwd_fd = fopen("/etc/passwd", "r"); if (NULL == passwd_fd) printf("failed to open passwd file\n"); while ( (pass = fgetpwent(passwd_fd)) != NULL) { if (pass->pw_uid > 999) {/* user! */ /* if the user uses bash (or zsh :) ), it's a real user */ if ( (strstr(pass->pw_shell,"bash") ) || (strstr(pass->pw_shell,"zsh") ) ){ strncpy(user_buf, pass->pw_name, user_name_len); return 0; } } } return -1; }
static GPtrArray * data2passwdents (const char *data) { struct passwd *ent = NULL; _cleanup_stdio_file_ FILE *mf = NULL; GPtrArray *ret = g_ptr_array_new_with_free_func (conv_passwd_ent_free); mf = fmemopen ((void *)data, strlen (data), "r"); while ((ent = fgetpwent (mf))) { struct conv_passwd_ent *convent = g_new (struct conv_passwd_ent, 1); convent->name = g_strdup (ent->pw_name); convent->uid = ent->pw_uid; convent->gid = ent->pw_gid; /* Want to add anymore, like dir? */ g_ptr_array_add (ret, convent); } return ret; }
int main(int argc, char **argv) { int ch, ret = 0, rflag = 0, argindex, tries; struct passwd *pstruct; struct stat statbuf; #ifndef att FILE *pwf; /* fille ptr for opened passwd file */ #endif char *usertype = NULL; int rc; cmdname = argv[0]; if( geteuid() != 0 ) { errmsg( M_PERM_DENIED ); exit( EX_NO_PERM ); } opterr = 0; /* no print errors from getopt */ usertype = getusertype(argv[0]); while( (ch = getopt(argc, argv, "r")) != EOF ) { switch(ch) { case 'r': rflag++; break; case '?': if (is_role(usertype)) errmsg( M_DRUSAGE ); else errmsg( M_DUSAGE ); exit( EX_SYNTAX ); } } if( optind != argc - 1 ) { if (is_role(usertype)) errmsg( M_DRUSAGE ); else errmsg( M_DUSAGE ); exit( EX_SYNTAX ); } logname = argv[optind]; #ifdef att pstruct = getpwnam(logname); #else /* * Do this with fgetpwent to make sure we are only looking on local * system (since passmgmt only works on local system). */ if ((pwf = fopen("/etc/passwd", "r")) == NULL) { errmsg( M_OOPS, "open", "/etc/passwd"); exit(EX_FAILURE); } while ((pstruct = fgetpwent(pwf)) != NULL) if (strcmp(pstruct->pw_name, logname) == 0) break; fclose(pwf); #endif if (pstruct == NULL) { errmsg( M_EXIST, logname ); exit( EX_NAME_NOT_EXIST ); } if( isbusy(logname) ) { errmsg( M_BUSY, logname, "remove" ); exit( EX_BUSY ); } /* that's it for validations - now do the work */ /* set up arguments to passmgmt in nargv array */ nargv[0] = PASSMGMT; nargv[1] = "-d"; /* delete */ argindex = 2; /* next argument */ /* finally - login name */ nargv[argindex++] = logname; /* set the last to null */ nargv[argindex++] = NULL; /* remove home directory */ if( rflag ) { /* Check Permissions */ if( stat( pstruct->pw_dir, &statbuf ) ) { errmsg(M_OOPS, "find status about home directory", strerror(errno)); exit( EX_HOMEDIR ); } if( check_perm( statbuf, pstruct->pw_uid, pstruct->pw_gid, S_IWOTH|S_IXOTH ) != 0 ) { errmsg( M_NO_PERM, logname, pstruct->pw_dir ); exit( EX_HOMEDIR ); } if( rm_files(pstruct->pw_dir, logname) != EX_SUCCESS ) exit( EX_HOMEDIR ); } /* now call passmgmt */ ret = PEX_FAILED; for( tries = 3; ret != PEX_SUCCESS && tries--; ) { switch( ret = call_passmgmt( nargv ) ) { case PEX_SUCCESS: ret = edit_group( logname, (char *)0, (int **)0, 1 ); if( ret != EX_SUCCESS ) errmsg( M_UPDATE, "deleted" ); break; case PEX_BUSY: break; case PEX_HOSED_FILES: errmsg( M_HOSED_FILES ); exit( EX_INCONSISTENT ); break; case PEX_SYNTAX: case PEX_BADARG: /* should NEVER occur that passmgmt usage is wrong */ if (is_role(usertype)) errmsg( M_DRUSAGE ); else errmsg( M_DUSAGE ); exit( EX_SYNTAX ); break; case PEX_BADUID: /* uid is used - shouldn't happen but print message anyway */ errmsg( M_UID_USED, pstruct->pw_uid ); exit( EX_ID_EXISTS ); break; case PEX_BADNAME: /* invalid loname */ errmsg( M_USED, logname); exit( EX_NAME_EXISTS ); break; default: errmsg( M_UPDATE, "deleted" ); exit( ret ); break; } } if( tries == 0 ) errmsg( M_UPDATE, "deleted" ); /* * Now, remove this user from all project entries */ rc = edit_project(logname, (char *)0, (projid_t **)0, 1); if (rc != EX_SUCCESS) { errmsg(M_UPDATE, "modified"); exit(rc); } exit( ret ); /*NOTREACHED*/ }
bool KUserFiles::loadpwd() { passwd *p; KU::KUser *tmpKU = 0; struct stat st; QString filename; QString passwd_filename; QString nispasswd_filename; int rc = 0; int passwd_errno = 0; int nispasswd_errno = 0; char processing_file = '\0'; #define P_PASSWD 0x01 #define P_NISPASSWD 0x02 #define MAXFILES 2 // Read KUser configuration passwd_filename = mCfg->passwdsrc(); nispasswd_filename = mCfg->nispasswdsrc(); // Handle unconfigured environments if(passwd_filename.isEmpty() && nispasswd_filename.isEmpty()) { mCfg->setPasswdsrc( PASSWORD_FILE ); mCfg->setGroupsrc( GROUP_FILE ); passwd_filename = mCfg->passwdsrc(); KMessageBox::error( 0, i18n("KUser sources were not configured.\nLocal passwd source set to %1\nLocal group source set to %2.").arg(mCfg->passwdsrc().arg(mCfg->groupsrc())) ); } if(!passwd_filename.isEmpty()) { processing_file = processing_file | P_PASSWD; filename.append(passwd_filename); } // Start reading passwd file(s) for(int i = 0; i < MAXFILES; i++) { rc = stat(QFile::encodeName(filename), &st); if(rc != 0) { KMessageBox::error( 0, i18n("Stat call on file %1 failed: %2\nCheck KUser settings.").arg(filename).arg(QString::fromLocal8Bit(strerror(errno))) ); if( (processing_file & P_PASSWD) != 0 ) { passwd_errno = errno; if(!nispasswd_filename.isEmpty()) { processing_file = processing_file & ~P_PASSWD; processing_file = processing_file | P_NISPASSWD; filename.truncate(0); filename.append(nispasswd_filename); } continue; } else{ nispasswd_errno = errno; break; } } pwd_mode = st.st_mode & 0666; pwd_uid = st.st_uid; pwd_gid = st.st_gid; // We are reading our configuration specified passwd file QString tmp; #ifdef HAVE_FGETPWENT FILE *fpwd = fopen(QFile::encodeName(filename), "r"); if(fpwd == NULL) { KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(filename) ); return FALSE; } while ((p = fgetpwent(fpwd)) != NULL) { #else setpwent(); //This should be enough for BSDs while ((p = getpwent()) != NULL) { #endif tmpKU = new KU::KUser(); tmpKU->setCaps( KU::KUser::Cap_POSIX ); tmpKU->setUID(p->pw_uid); tmpKU->setGID(p->pw_gid); tmpKU->setName(QString::fromLocal8Bit(p->pw_name)); tmp = QString::fromLocal8Bit( p->pw_passwd ); if ( tmp != "x" && tmp != "*" && !tmp.startsWith("!") ) tmpKU->setDisabled( false ); else tmpKU->setDisabled( true ); if ( tmp.startsWith("!") ) tmp.remove(0, 1); tmpKU->setPwd( tmp ); tmpKU->setHomeDir(QString::fromLocal8Bit(p->pw_dir)); tmpKU->setShell(QString::fromLocal8Bit(p->pw_shell)); #if defined(__FreeBSD__) || defined(__bsdi__) tmpKU->setClass(QString::fromLatin1(p->pw_class)); tmpKU->setLastChange(p->pw_change); tmpKU->setExpire(p->pw_expire); #endif if ((p->pw_gecos != 0) && (p->pw_gecos[0] != 0)) fillGecos(tmpKU, p->pw_gecos); mUsers.append(tmpKU); } // End reading passwd_filename #ifdef HAVE_FGETPWENT fclose(fpwd); #else endpwent(); #endif if((!nispasswd_filename.isEmpty()) && (nispasswd_filename != passwd_filename)) { processing_file = processing_file & ~P_PASSWD; processing_file = processing_file | P_NISPASSWD; filename.truncate(0); filename.append(nispasswd_filename); } else break; } // end of processing files, for loop if( (passwd_errno == 0) && (nispasswd_errno == 0) ) return (TRUE); if( (passwd_errno != 0) && (nispasswd_errno != 0) ) return (FALSE); else return(TRUE); } // Load shadow passwords bool KUserFiles::loadsdw() { #ifdef HAVE_SHADOW QString shadow_file,tmp; struct spwd *spw; KU::KUser *up = NULL; struct stat st; shadow_file = mCfg->shadowsrc(); if ( shadow_file.isEmpty() ) return TRUE; stat( QFile::encodeName(shadow_file), &st); sdw_mode = st.st_mode & 0666; sdw_uid = st.st_uid; sdw_gid = st.st_gid; #ifdef HAVE_FGETSPENT FILE *f; kdDebug() << "open shadow file: " << shadow_file << endl; if ((f = fopen( QFile::encodeName(shadow_file), "r")) == NULL) { KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(shadow_file) ); caps &= ~Cap_Shadow; return TRUE; } while ((spw = fgetspent( f ))) { // read a shadow password structure #else setspent(); while ((spw = getspent())) { // read a shadow password structure #endif kdDebug() << "shadow entry: " << spw->sp_namp << endl; if ((up = lookup(QString::fromLocal8Bit(spw->sp_namp))) == NULL) { KMessageBox::error( 0, i18n("No /etc/passwd entry for %1.\nEntry will be removed at the next `Save'-operation.").arg(QString::fromLocal8Bit(spw->sp_namp)) ); continue; } tmp = QString::fromLocal8Bit( spw->sp_pwdp ); if ( tmp.startsWith("!!") || tmp == "*" ) { up->setDisabled( true ); tmp.remove( 0, 2 ); } else up->setDisabled( false ); up->setSPwd( tmp ); // cp the encrypted pwd up->setLastChange( daysToTime( spw->sp_lstchg ) ); up->setMin(spw->sp_min); up->setMax(spw->sp_max); #ifndef _SCO_DS up->setWarn(spw->sp_warn); up->setInactive(spw->sp_inact); up->setExpire( daysToTime( spw->sp_expire ) ); up->setFlag(spw->sp_flag); #endif } #ifdef HAVE_FGETSPENT fclose(f); #else endspent(); #endif #endif // HAVE_SHADOW return TRUE; } // Save password file #define escstr(a,b) tmp2 = user->a(); \ tmp2.replace(':',"_"); \ tmp2.replace(',',"_"); \ user->b( tmp2 ); bool KUserFiles::savepwd() { FILE *passwd_fd = NULL; FILE *nispasswd_fd = NULL; uid_t minuid = 0; int nis_users_written = 0; uid_t tmp_uid = 0; QString s; QString s1; QString tmp, tmp2; QString passwd_filename; QString nispasswd_filename; char errors_found = '\0'; #define NOMINUID 0x01 #define NONISPASSWD 0x02 // Read KUser configuration info passwd_filename = mCfg->passwdsrc(); nispasswd_filename = mCfg->nispasswdsrc(); QString new_passwd_filename = passwd_filename + QString::fromLatin1(KU_CREATE_EXT); QString new_nispasswd_filename = nispasswd_filename+QString::fromLatin1(KU_CREATE_EXT); if( nispasswd_filename != passwd_filename ) { minuid = mCfg->nisminuid(); } // Backup file(s) if(!passwd_filename.isEmpty()) { if (!pw_backuped) { if (!backup(passwd_filename)) return FALSE; pw_backuped = TRUE; } } if(!nispasswd_filename.isEmpty() && (nispasswd_filename != passwd_filename)) { if (!pn_backuped) { if (!backup(nispasswd_filename)) return FALSE; pn_backuped = TRUE; } } // Open file(s) if(!passwd_filename.isEmpty()) { if ((passwd_fd = fopen(QFile::encodeName(new_passwd_filename),"w")) == NULL) KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(passwd_filename) ); } if(!nispasswd_filename.isEmpty() && (nispasswd_filename != passwd_filename)){ if ((nispasswd_fd = fopen(QFile::encodeName(new_nispasswd_filename),"w")) == NULL) KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(nispasswd_filename) ); } QPtrListIterator<KU::KUser> it( mUsers ); KU::KUser *user; bool addok = false; user = (*it); while (true) { if ( user == 0 ) { if ( addok ) break; it = QPtrListIterator<KU::KUser> ( mAdd ); user = (*it); addok = true; if ( user == 0 ) break; }; if ( mDel.containsRef( user ) ) { ++it; user = (*it); continue; } if ( mMod.contains( user ) ) user = &( mMod[ user ] ); tmp_uid = user->getUID(); if ( caps & Cap_Shadow ) tmp = "x"; else { tmp = user->getPwd(); if ( user->getDisabled() && tmp != "x" && tmp != "*" ) tmp = "!" + tmp; } escstr( getName, setName ); escstr( getHomeDir, setHomeDir ); escstr( getShell, setShell ); escstr( getName, setName ); escstr( getFullName, setFullName ); #if defined(__FreeBSD__) || defined(__bsdi__) escstr( getClass, setClass ); escstr( getOffice, setOffice ); escstr( getWorkPhone, setWorkPhone ); escstr( getHomePhone, setHomePhone ); s = user->getName() + ":" + tmp + ":" + QString::number( user->getUID() ) + ":" + QString::number( user->getGID() ) + ":" + user->getClass() + ":" + QString::number( user->getLastChange() ) + ":" + QString::number( user->getExpire() ) + ":"; s1 = user->getFullName() + "," + user->getOffice() + "," + user->getWorkPhone() + "," + user->getHomePhone(); #else escstr( getOffice1, setOffice1 ); escstr( getOffice2, setOffice2 ); escstr( getAddress, setAddress ); s = user->getName() + ":" + tmp + ":" + QString::number( user->getUID() ) + ":" + QString::number( user->getGID() ) + ":"; s1 = user->getFullName() + "," + user->getOffice1() + "," + user->getOffice2() + "," + user->getAddress(); #endif for (int j=(s1.length()-1); j>=0; j--) { if (s1[j] != ',') break; s1.truncate(j); } s += s1 + ":" + user->getHomeDir() + ":" + user->getShell() + "\n"; if( (nispasswd_fd != 0) && (minuid != 0) ) { if (minuid <= tmp_uid) { fputs(s.local8Bit().data(), nispasswd_fd); nis_users_written++; ++it; user = (*it); continue; } } if( (nispasswd_fd != 0) && (minuid == 0) ) { errors_found = errors_found | NOMINUID; } if( (nispasswd_fd == 0) && (minuid != 0) ) { errors_found = errors_found | NONISPASSWD; } kdDebug() << s << endl; fputs(s.local8Bit().data(), passwd_fd); ++it; user = (*it); } if(passwd_fd) { fclose(passwd_fd); chmod(QFile::encodeName(new_passwd_filename), pwd_mode); chown(QFile::encodeName(new_passwd_filename), pwd_uid, pwd_gid); rename(QFile::encodeName(new_passwd_filename), QFile::encodeName(passwd_filename)); } if(nispasswd_fd) { fclose(nispasswd_fd); chmod(QFile::encodeName(new_nispasswd_filename), pwd_mode); chown(QFile::encodeName(new_nispasswd_filename), pwd_uid, pwd_gid); rename(QFile::encodeName(new_nispasswd_filename), QFile::encodeName(nispasswd_filename)); } if( (errors_found & NOMINUID) != 0 ) { KMessageBox::error( 0, i18n("Unable to process NIS passwd file without a minimum UID specified.\nPlease update KUser settings (Files).") ); } if( (errors_found & NONISPASSWD) != 0 ) { KMessageBox::error( 0, i18n("Specifying NIS minimum UID requires NIS file(s).\nPlease update KUser settings (Files).") ); } // need to run a utility program to build /etc/passwd, /etc/pwd.db // and /etc/spwd.db from /etc/master.passwd #if defined(__FreeBSD__) || defined(__bsdi__) if (system(PWMKDB) != 0) { KMessageBox::error( 0, i18n("Unable to build password database.") ); return FALSE; } #else if( (nis_users_written > 0) || (nispasswd_filename == passwd_filename) ) { if (system(PWMKDB) != 0) { KMessageBox::error( 0, i18n("Unable to build password databases.") ); return FALSE; } } #endif return TRUE; }
// {{{ user_add() /// Create a valid user account void user_add(user_t *o, char *username, volatile char *passwd) { o->error[0]=0; struct passwd p; struct passwd *pw; struct spwd sp; FILE *f; int min = 1000; int max = 65000; char home[256]; snprintf(home, sizeof(home), "/home/%s", username); p.pw_name = (char *)username; p.pw_passwd = "x"; p.pw_uid = USER_DEFAULT_ID; p.pw_gid = USER_GROUP_ID; p.pw_gecos = "OpenDomo User"; p.pw_dir = home; p.pw_shell = "/bin/sh"; f = fopen("/etc/passwd", "r"); /* check user and get valid id */ while ((pw = fgetpwent(f))) { if (strcmp(pw->pw_name, p.pw_name) == 0) { sstrncpy(o->error, "user_add(): user exists", USER_ERROR_SIZE); return; } if ((pw->pw_uid >= p.pw_uid) && (pw->pw_uid < max) && (pw->pw_uid >= min)) { p.pw_uid = pw->pw_uid + 1; } } fclose(f); f = fopen("/etc/passwd", "a+"); if(!f) { sstrncpy(o->error, "user_add(): cannot open /etc/passwd",USER_ERROR_SIZE); return; } /* add to passwd */ if (putpwent(&p, f) == -1) { sstrncpy(o->error, "user_add(): putpwent() error", USER_ERROR_SIZE); return; } fclose(f); /* salt */ struct timeval tv; static char salt[40]; salt[0] = '\0'; gettimeofday (&tv, (struct timezone *) 0); strcat(salt, l64a (tv.tv_usec)); strcat(salt, l64a (tv.tv_sec + getpid () + clock ())); if (strlen (salt) > 3 + 8) salt[11] = '\0'; /* shadow */ sp.sp_namp = p.pw_name; sp.sp_pwdp = (char*)crypt((const char*)passwd, salt); sp.sp_min = 0; sp.sp_max = (10000L * DAY) / SCALE; sp.sp_lstchg = time((time_t *) 0) / SCALE; sp.sp_warn = -1; sp.sp_expire = -1; sp.sp_inact = -1; sp.sp_flag = -1; /* add to shadow */ f = fopen("/etc/shadow", "a+"); if(!f) { sstrncpy(o->error, "user_add(): cannot open /etc/shadow",USER_ERROR_SIZE); return; } if (putspent(&sp, f) == -1) { sstrncpy(o->error, "user_add(): putspent() error",USER_ERROR_SIZE); return; } fclose(f); /* Create home */ mkdir(home, 0700); chown(home, p.pw_uid, USER_GROUP_ID); }
void changepasswd(SVCXPRT *transp) { /* * Put these numeric constants into const variables so * a) they're visible in a debugger * b) the compiler can play it's cool games with em */ static const int cryptpwsize = CRYPT_MAXCIPHERTEXTLEN; static const int fingersize = FINGERSIZE; static const int shellsize = SHELLSIZE; struct yppasswd yppwd; struct passwd newpw, opwd; struct spwd ospwd; struct sigaction sa, osa1, osa2, osa3; struct stat pwstat, spstat, adjstat; char *oldpass_crypt = NULL; char newpasswdfile[FILENAME_MAX]; char newshadowfile[FILENAME_MAX]; char newadjunctfile[FILENAME_MAX]; char tmppasswdfile[FILENAME_MAX]; char tmpshadowfile[FILENAME_MAX]; char tmpadjunctfile[FILENAME_MAX]; char pwbuf[NSS_LINELEN_PASSWD], spbuf[NSS_LINELEN_SHADOW]; char adjbuf[BUFSIZ+1], adjbuf_new[BUFSIZ+1], cmdbuf[BUFSIZ]; char adj_encrypt[CRYPT_MAXCIPHERTEXTLEN + 1]; /* * The adj_crypt_* pointers are used to point into adjbuf * NOT adj_encrypt */ char *adj_crypt_begin, *adj_crypt_end; char name[UTUSERLEN + sizeof (":")]; char *p; FILE *opwfp = NULL, *ospfp = NULL, *oadjfp = NULL, *npwfp = NULL, *nspfp = NULL, *nadjfp = NULL; int npwfd = -1, nspfd = -1, nadjfd = -1; int i, ans, chsh, chpw, chgecos, namelen; int gotadjunct = 0, gotshadow = 0, gotpasswd = 0; int doneflag = 0, root_on_master = 0; pid_t retval; time_t now; long pwpos = 0, sppos = 0; /* Globals :-( */ extern int single, nogecos, noshell, nopw, mflag, Mstart, Argc; extern char **Argv; extern char passwd_file[], shadow_file[], adjunct_file[]; extern int useadjunct; extern int useshadow; /* Clean out yppwd */ memset(&yppwd, 0, sizeof (struct yppasswd)); /* Get the RPC args */ if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) { svcerr_decode(transp); return; } /* Perform basic validation */ if (/* (!validstr(yppwd.oldpass, PWSIZE)) || */ /* see PR:nis/38 */ (!validstr(yppwd.newpw.pw_passwd, cryptpwsize)) || (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) || (!validstr(yppwd.newpw.pw_gecos, fingersize)) || (!validstr(yppwd.newpw.pw_shell, shellsize))) { svcerr_decode(transp); return; } /* * Special case: root on the master server can change other users' * passwords without first entering the old password. We need to * ensure that this is indeed root on the master server. (bug 1253949) */ if (strcmp(transp->xp_netid, "ticlts") == 0) { svc_local_cred_t cred; if (!svc_get_local_cred(transp, &cred)) { syslog(LOG_ERR, "yppasswdd: Couldn't get " "local user credentials.\n"); } else if (cred.ruid == 0) root_on_master = 1; } newpw = yppwd.newpw; strcpy(name, newpw.pw_name); strcat(name, ":"); namelen = strlen(name); ans = 2; chsh = chpw = chgecos = 0; /* Get all the filenames straight */ strcpy(newpasswdfile, passwd_file); strcat(newpasswdfile, ".ptmp"); strcpy(newshadowfile, shadow_file); strcat(newshadowfile, ".ptmp"); strcpy(newadjunctfile, adjunct_file); strcat(newadjunctfile, ".ptmp"); memset(&sa, 0, sizeof (struct sigaction)); sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, (struct sigaction *)0); sigaction(SIGHUP, &sa, &osa1); sigaction(SIGINT, &sa, &osa2); sigaction(SIGQUIT, &sa, &osa3); /* Lock, then open the passwd and shadow files */ if (yplckpwdf() < 0) { syslog(LOG_ERR, "yppasswdd: Password file(s) busy. " "Try again later.\n"); ans = 8; goto cleanup; } if ((opwfp = fopen(passwd_file, "r")) == NULL) { syslog(LOG_ERR, "yppasswdd: Could not open %s\n", passwd_file); goto cleanup; } fstat(fileno(opwfp), &pwstat); if (useshadow) { if ((ospfp = fopen(shadow_file, "r")) == NULL) { syslog(LOG_ERR, "yppasswdd: Could not open %s\n", shadow_file); goto cleanup; } fstat(fileno(ospfp), &spstat); } if (useadjunct) { if ((oadjfp = fopen(adjunct_file, "r")) == NULL) { syslog(LOG_ERR, "yppasswdd: Could not open %s\n", adjunct_file); goto cleanup; } fstat(fileno(oadjfp), &adjstat); } /* * Open the new passwd and shadow tmp files, * first with open and then create a FILE * with fdopen() */ if ((npwfd = open(newpasswdfile, O_WRONLY | O_CREAT | O_EXCL, pwstat.st_mode)) < 0) { if (errno == EEXIST) { syslog(LOG_WARNING, "yppasswdd: passwd file busy - try again\n"); ans = 8; } else { syslog(LOG_ERR, "yppasswdd: %s: %m", newpasswdfile); ans = 9; } goto cleanup; } fchown(npwfd, pwstat.st_uid, pwstat.st_gid); if ((npwfp = fdopen(npwfd, "w")) == NULL) { syslog(LOG_ERR, "yppasswdd: fdopen() on %s failed\n", newpasswdfile); goto cleanup; } if (useshadow) { if ((nspfd = open(newshadowfile, O_WRONLY | O_CREAT | O_EXCL, spstat.st_mode)) < 0) { if (errno == EEXIST) { syslog(LOG_WARNING, "yppasswdd: shadow file busy - try " "again\n"); ans = 8; } else { syslog(LOG_ERR, "yppasswdd: %s: %m", newshadowfile); ans = 9; } goto cleanup; } fchown(nspfd, spstat.st_uid, spstat.st_gid); if ((nspfp = fdopen(nspfd, "w")) == NULL) { syslog(LOG_ERR, "yppasswdd: fdopen() on %s failed\n", newshadowfile); goto cleanup; } } if (useadjunct) { if ((nadjfd = open(newadjunctfile, O_WRONLY | O_CREAT | O_EXCL, adjstat.st_mode)) < 0) { if (errno == EEXIST) { syslog(LOG_WARNING, "yppasswdd: adjunct file busy - try " "again\n"); ans = 8; } else { syslog(LOG_ERR, "yppasswdd: %s: %m", newadjunctfile); ans = 9; } goto cleanup; } fchown(nadjfd, adjstat.st_uid, adjstat.st_gid); if ((nadjfp = fdopen(nadjfd, "w")) == NULL) { syslog(LOG_ERR, "yppasswdd: fdopen() on %s failed\n", newadjunctfile); goto cleanup; } } /* * The following code may not seem all that elegant, but my * interpretation of the man pages relating to the passwd and * shadow files would seem to indicate that there is no guarantee * that the entries contained in those files will be in the same * order... * * So here's the high level overview: * * Loop through the passwd file reading in lines and writing them * out to the new file UNTIL we get to the correct entry. * IF we have a shadow file, loop through it reading in lines and * writing them out to the new file UNTIL we get to the correct * entry. IF we have an adjunct file, loop through it reading in * lines and writing them out to the new file UNTIL we get to the * correct entry. * * Figure out what's changing, contruct the new passwd, shadow, * and adjunct entries and spit em out to the temp files. * At this point, set the done flag and leap back into the loop(s) * until you're finished with the files and then leap to the * section that installs the new files. */ loop_in_files: /* While we find things in the passwd file */ while (fgets(pwbuf, NSS_LINELEN_PASSWD, opwfp)) { /* * Is this the passwd entry we want? * If not, then write it out to the new passwd temp file * and remember our position. */ if (doneflag || strncmp(name, pwbuf, namelen)) { if (fputs(pwbuf, npwfp) == EOF) { syslog(LOG_ERR, "yppasswdd: write to passwd file " "failed.\n"); goto cleanup; } pwpos = ftell(opwfp); continue; } gotpasswd = 1; break; } /* no match */ if (!gotpasswd) { syslog(LOG_ERR, "yppasswdd: user %s does not exist\n", name); goto cleanup; } /* While we find things in the shadow file */ while (useshadow && fgets(spbuf, NSS_LINELEN_SHADOW, ospfp)) { /* * Is this the shadow entry that we want? * If not, write it out to the new shadow temp file * and remember our position. */ if (doneflag || strncmp(name, spbuf, namelen)) { if (fputs(spbuf, nspfp) == EOF) { syslog(LOG_ERR, "yppasswdd: write to shadow file " "failed.\n"); goto cleanup; } sppos = ftell(ospfp); continue; } gotshadow = 1; break; } /* While we find things in the adjunct file */ while (useadjunct && fgets(adjbuf, BUFSIZ, oadjfp)) { /* * is this the adjunct entry that we want? * If not, write it out to the new temp file * and remember our position. */ if (doneflag || strncmp(name, adjbuf, namelen)) { if (fputs(adjbuf, nadjfp) == EOF) { syslog(LOG_ERR, "yppasswdd: write to adjunct file " "failed.\n"); goto cleanup; } continue; } gotadjunct = 1; break; } if (doneflag) goto install_files; if (useshadow && !gotshadow) { syslog(LOG_ERR, "yppasswdd: no passwd in shadow for %s\n", newpw.pw_name); ans = 4; goto cleanup; } if (useadjunct && !gotadjunct) { syslog(LOG_ERR, "yppasswdd: no passwd in adjunct for %s\n", newpw.pw_name); ans = 4; goto cleanup; } /* * Now that we've read in the correct passwd AND * shadow lines, we'll rewind to the beginning of * those lines and let the fget*ent() calls do * the work. Since we are only working with the * first two fields of the adjunct entry, leave * it as a char array. */ fseek(opwfp, pwpos, SEEK_SET); opwd = *fgetpwent(opwfp); if (useshadow) { fseek(ospfp, sppos, SEEK_SET); ospwd = *fgetspent(ospfp); } oldpass_crypt = cryptoldpasswd(yppwd.oldpass, newpw.pw_passwd, newpw.pw_name); if (oldpass_crypt == NULL) { ans = 3; goto cleanup; } p = newpw.pw_passwd; if ((!nopw) && p && *p && !((*p++ == '#') && (*p++ == '#') && (strcmp(p, opwd.pw_name) == 0)) && (strcmp(oldpass_crypt, newpw.pw_passwd) != 0)) chpw = 1; oldpass_crypt = NULL; if ((!noshell) && (strcmp(opwd.pw_shell, newpw.pw_shell) != 0)) { if (single) chpw = 0; chsh = 1; } if ((!nogecos) && (strcmp(opwd.pw_gecos, newpw.pw_gecos) != 0)) { if (single) { chpw = 0; chsh = 0; } chgecos = 1; } if (!(chpw + chsh + chgecos)) { syslog(LOG_NOTICE, "yppasswdd: no change for %s\n", newpw.pw_name); ans = 3; goto cleanup; } if (useshadow && !root_on_master) { oldpass_crypt = cryptoldpasswd(yppwd.oldpass, ospwd.sp_pwdp, newpw.pw_name); if (oldpass_crypt == NULL) goto cleanup; if (ospwd.sp_pwdp && *ospwd.sp_pwdp && (strcmp(oldpass_crypt, ospwd.sp_pwdp) != 0)) { syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", newpw.pw_name); ans = 7; goto cleanup; } } else if (useadjunct) { /* * Clear the adj_encrypt array. Extract the encrypted passwd * into adj_encrypt by setting adj_crypt_begin and * adj_crypt_end to point at the first character of the * encrypted passwd and the first character following the * encrypted passwd in adjbuf, respectively, and copy the * stuff between (there may not be anything) into adj_ecrypt. * Then, check that adj_encrypt contains something and that * the old passwd is correct. */ memset(adj_encrypt, 0, sizeof (adj_encrypt)); adj_crypt_begin = adjbuf + namelen; adj_crypt_end = strchr(adj_crypt_begin, ':'); strncpy(adj_encrypt, adj_crypt_begin, adj_crypt_end - adj_crypt_begin); oldpass_crypt = cryptoldpasswd(yppwd.oldpass, adj_encrypt, newpw.pw_name); if (oldpass_crypt == NULL) goto cleanup; if (!root_on_master && *adj_encrypt && (strcmp(oldpass_crypt, adj_encrypt) != 0)) { syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", newpw.pw_name); ans = 7; goto cleanup; } } else { oldpass_crypt = cryptoldpasswd(yppwd.oldpass, opwd.pw_passwd, newpw.pw_name); if (oldpass_crypt == NULL) goto cleanup; if (!root_on_master && opwd.pw_passwd && *opwd.pw_passwd && (strcmp(oldpass_crypt, opwd.pw_passwd) != 0)) { syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", newpw.pw_name); ans = 7; goto cleanup; } } #ifdef DEBUG printf("%d %d %d\n", chsh, chgecos, chpw); printf("%s %s %s\n", yppwd.newpw.pw_shell, yppwd.newpw.pw_gecos, yppwd.newpw.pw_passwd); printf("%s %s %s\n", opwd.pw_shell, opwd.pw_gecos, ospwd.sp_pwdp); #endif if (chsh && !validloginshell(opwd.pw_shell, newpw.pw_shell, root_on_master)) { goto cleanup; } /* security hole fix from original source */ for (p = newpw.pw_name; (*p != '\0'); p++) if ((*p == ':') || !(isprint(*p))) *p = '$'; /* you lose buckwheat */ for (p = newpw.pw_passwd; (*p != '\0'); p++) if ((*p == ':') || !(isprint(*p))) *p = '$'; /* you lose buckwheat */ if (chgecos) opwd.pw_gecos = newpw.pw_gecos; if (chsh) opwd.pw_shell = newpw.pw_shell; /* * If we're changing the shell or gecos fields and we're * using a shadow or adjunct file or not changing the passwd * then go ahead and update the passwd file. The case where * the passwd is being changed and we are not using a shadow * or adjunct file is handled later. */ if ((chsh || chgecos) && (useshadow || useadjunct || !chpw) && putpwent(&opwd, npwfp)) { syslog(LOG_ERR, "yppasswdd: putpwent failed: %s\n", passwd_file); goto cleanup; } if (chpw) { if (useshadow) { ospwd.sp_pwdp = newpw.pw_passwd; now = DAY_NOW; /* password aging - bug for bug compatibility */ if (ospwd.sp_max != -1) { if (now < ospwd.sp_lstchg + ospwd.sp_min) { syslog(LOG_ERR, "yppasswdd: Sorry: < %ld days " "since the last change.\n", ospwd.sp_min); goto cleanup; } } ospwd.sp_lstchg = now; if (putspent(&ospwd, nspfp)) { syslog(LOG_ERR, "yppasswdd: putspent failed: %s\n", shadow_file); goto cleanup; } } else if (useadjunct) { sprintf(adjbuf_new, "%s%s%s", name, newpw.pw_passwd, adj_crypt_end); if (fputs(adjbuf_new, nadjfp) == EOF) { syslog(LOG_ERR, "yppasswdd: write to adjunct failed: %s\n", adjunct_file); goto cleanup; } } else { opwd.pw_passwd = newpw.pw_passwd; if (putpwent(&opwd, npwfp)) { syslog(LOG_ERR, "yppasswdd: putpwent failed: %s\n", passwd_file); goto cleanup; } } } if (!doneflag) { doneflag = 1; goto loop_in_files; } install_files: /* * Critical section, nothing special needs to be done since we * hold exclusive access to the *.ptmp files */ fflush(npwfp); if (useshadow) fflush(nspfp); if (useadjunct) fflush(nadjfp); strcpy(tmppasswdfile, passwd_file); strcat(tmppasswdfile, "-"); if (useshadow) { strcpy(tmpshadowfile, shadow_file); strcat(tmpshadowfile, "-"); } if (useadjunct) { strcpy(tmpadjunctfile, adjunct_file); strcat(tmpadjunctfile, "-"); } if ((!useshadow && !useadjunct) || (chsh || chgecos)) { if (rename(passwd_file, tmppasswdfile) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to backup " "passwd file: %m"); goto cleanup; } else { if (rename(newpasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to mv passwd: %m"); if (rename(tmppasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of passwd file: %m"); } goto cleanup; } } } if (useshadow && chpw) { if (rename(shadow_file, tmpshadowfile) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to back up " "shadow file: %m"); if (rename(tmppasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of passwd file: %m"); } goto cleanup; } else { if (rename(newshadowfile, shadow_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to mv shadow: %m"); if (rename(tmpshadowfile, shadow_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of shadow file: %m"); } if (rename(tmppasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of passwd file: %m"); } goto cleanup; } } } else if (useadjunct && chpw) { if (rename(adjunct_file, tmpadjunctfile) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to back up " "adjunct file: %m"); if (rename(tmppasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore backup " "of passwd: %m"); } goto cleanup; } else { if (rename(newadjunctfile, adjunct_file) < 0) { syslog(LOG_CRIT, "yppassdd: failed to mv adjunct: %m"); if (rename(tmppasswdfile, passwd_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of passwd file: %m"); } if (rename(tmpadjunctfile, adjunct_file) < 0) { syslog(LOG_CRIT, "yppasswdd: failed to restore " "backup of adjunct file: %m"); } goto cleanup; } } } if (doneflag) ans = 0; /* End critical section */ /* * Here we have come only after the new files have been successfully * renamed to original files. At this point, the temp files would still * be existing we need to remove them from the /etc directory */ unlink(tmppasswdfile); if (useshadow) unlink(tmpshadowfile); if (useadjunct) unlink(tmpadjunctfile); cleanup: /* If we don't have opwfp, then we didn't do anything */ if (opwfp) { fclose(opwfp); if (ospfp) { fclose(ospfp); } if (oadjfp) { fclose(oadjfp); } unlink(newpasswdfile); /* These tests are cheaper than failing syscalls */ if (useshadow) unlink(newshadowfile); if (useadjunct) unlink(newadjunctfile); if (npwfp) { fclose(npwfp); if (nspfp) { fclose(nspfp); } if (nadjfp) { fclose(nadjfp); } } } ypulckpwdf(); if (doneflag && mflag) { retval = fork(); if (retval < 0) { syslog(LOG_ERR, "yppasswdd: Fork failed %m"); } else if (retval == 0) { strcpy(cmdbuf, "/usr/ccs/bin/make"); for (i = Mstart + 1; i < Argc; i++) { strcat(cmdbuf, " "); strcat(cmdbuf, Argv[i]); } #ifdef DEBUG syslog(LOG_ERR, "yppasswdd: about to " "execute %s\n", cmdbuf); #else if (yplckpwdf() < 0) { syslog(LOG_ERR, "yppasswdd: Couldn't get the " "lock to update the maps"); } else { setpgrp(); system(cmdbuf); ypulckpwdf(); } #endif exit(0); } } sigaction(SIGHUP, &osa1, (struct sigaction *)0); sigaction(SIGINT, &osa2, (struct sigaction *)0); sigaction(SIGQUIT, &osa3, (struct sigaction *)0); if (!svc_sendreply(transp, xdr_int, (char *)&ans)) syslog(LOG_WARNING, "yppasswdd: couldn\'t reply to RPC call\n"); }
PAMH_ARG_DECL(int unix_update_passwd, const char *forwho, const char *towhat) { struct passwd *tmpent = NULL; struct stat st; FILE *pwfile, *opwfile; int err = 1; int oldmask; #ifdef WITH_SELINUX security_context_t prev_context=NULL; #endif oldmask = umask(077); #ifdef WITH_SELINUX if (SELINUX_ENABLED) { security_context_t passwd_context=NULL; if (getfilecon("/etc/passwd",&passwd_context)<0) { return PAM_AUTHTOK_ERR; }; if (getfscreatecon(&prev_context)<0) { freecon(passwd_context); return PAM_AUTHTOK_ERR; } if (setfscreatecon(passwd_context)) { freecon(passwd_context); freecon(prev_context); return PAM_AUTHTOK_ERR; } freecon(passwd_context); } #endif pwfile = fopen(PW_TMPFILE, "w"); umask(oldmask); if (pwfile == NULL) { err = 1; goto done; } opwfile = fopen("/etc/passwd", "r"); if (opwfile == NULL) { fclose(pwfile); err = 1; goto done; } if (fstat(fileno(opwfile), &st) == -1) { fclose(opwfile); fclose(pwfile); err = 1; goto done; } if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { fclose(opwfile); fclose(pwfile); err = 1; goto done; } if (fchmod(fileno(pwfile), st.st_mode) == -1) { fclose(opwfile); fclose(pwfile); err = 1; goto done; } tmpent = fgetpwent(opwfile); while (tmpent) { if (!strcmp(tmpent->pw_name, forwho)) { /* To shut gcc up */ union { const char *const_charp; char *charp; } assigned_passwd; assigned_passwd.const_charp = towhat; tmpent->pw_passwd = assigned_passwd.charp; err = 0; } if (putpwent(tmpent, pwfile)) { D(("error writing entry to password file: %m")); err = 1; break; } tmpent = fgetpwent(opwfile); } fclose(opwfile); if (fflush(pwfile) || fsync(fileno(pwfile))) { D(("fflush or fsync error writing entries to password file: %m")); err = 1; } if (fclose(pwfile)) { D(("fclose error writing entries to password file: %m")); err = 1; } done: if (!err) { if (!rename(PW_TMPFILE, "/etc/passwd")) pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho); else err = 1; } #ifdef WITH_SELINUX if (SELINUX_ENABLED) { if (setfscreatecon(prev_context)) { err = 1; } if (prev_context) freecon(prev_context); prev_context=NULL; } #endif if (!err) { return PAM_SUCCESS; } else { unlink(PW_TMPFILE); return PAM_AUTHTOK_ERR; } }
struct passwd *_spfgetpwent(FILE *F) { return(_spsubspwd(fgetpwent(F))); }