|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 9416 (0x24c8) Types: TextFile Names: »pw_passwd.c«
└─⟦4f9d7c866⟧ Bits:30007245 EUUGD6: Sikkerheds distributionen └─⟦123909933⟧ »./npasswd/npasswd.tar.Z« └─⟦22a202e7d⟧ └─⟦this⟧ »npass-new/npasswd_jpl/pw_passwd.c«
/* -------------------------------------------------------------------- */ /* */ /* Author: Clyde Hoover */ /* Computation Center */ /* The University of Texas at Austin */ /* Austin, Texas 78712 */ /* clyde@emx.utexas.edu */ /* uunet!cs.utexas.edu!ut-emx!clyde */ /* */ /*This code may be distributed freely, provided this notice is retained. */ /* */ /* -------------------------------------------------------------------- */ /* * pw_passwd - Routines for dealing with password files. * Handles V7 / *.* BSD / Sys V format. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <errno.h> #include <pwd.h> #include <fcntl.h> #ifndef lint static char sccsid[] = "@(#)pw_passwd.c 1.9 1/24/91 (cc.utexas.edu)"; #endif #define SLOP 128 /* Size difference tolerated old <> new passwd file */ #ifdef SYSV /* * System V password aging stuff */ #define SEC_PER_WEEK ((long )24 * 7 * 60 * 60) extern long a64l(); extern char *l64a(); static time_t pwage = 0, maxpwtime = 0, minpwtime = 0, now; #endif typedef struct passwd passwd; typedef struct passwd *passwdp; static passwd theUser, /* The user to change */ Me; /* The user who invoked command */ static int myuid, /* Uid of program */ mytempfile = 0; /* Does PASSWD_TEMP belong to me? */ /* * File names */ #ifndef PASSWD_FILE #define PASSWD_FILE "/etc/passwd" #endif #ifndef PASSWD_SAVE #define PASSWD_SAVE "/etc/opasswd" #endif #ifndef PASSWD_TEMP #define PASSWD_TEMP "/etc/ptmp" #endif #define PASSWD_MODE 0644 #ifdef DEBUG static char *passwdtemp = "./etc_ptmp", *passwdfile = "./etc_passwd", *savefile = "./etc_opasswd"; #else static char *passwdtemp = PASSWD_TEMP, *passwdfile = PASSWD_FILE, *savefile = PASSWD_SAVE; #endif extern int errno; char *getlogin(), *crypt(); /* * pw_initialize - set up */ pw_initialize() { passwdp me; /* Temp */ char *myname = getlogin(); /* Name of invoker */ #ifdef DEBUG setpwfile(passwdfile); #endif myuid = getuid(); if (myname && *myname) { if ((me = getpwnam(myname)) == NULL) quit(1, "Cannot get user identification from name.\n"); } else { if ((me = getpwuid(myuid)) == NULL) quit(1, "Cannot get user identification from uid.\n"); } _cppasswd(me, &Me); return(1); } /* * pw_getuserbyname - get password * * Returns 1 if passwd info found for <name> * 0 otherwise */ pw_getuserbyname(name, passwdb) char *name, /* User name */ *passwdb; /* Where to stuff password */ { passwdp p; /* Temp */ if ((p = getpwnam(name)) == NULL) return(0); _cppasswd(p, &theUser); (void) strcpy(passwdb, p->pw_passwd); return(1); } /* * pw_permission - check password change permission * * Returns 1 if password can be changed * 0 if not */ pw_permission() { if (strcmp(Me.pw_name, theUser.pw_name) && myuid) return(0); /* * Other checks can be put here to determine if the invoker should * be allowed to change this password. */ #ifdef SYSV if (theUser.pw_age) { pwage = a64l(theUser.pw_age); maxpwtime = pwage & 077; minpwtime = (pwage >> 6) & 077; pwage >>= 12; (void) time(&now); now /= SEC_PER_WEEK; if (pwage <= now) { if (myuid && (now < (pwage + minpwtime))) { fprintf(stderr, "Sorry: < %ld weeks since last change\n", minpwtime); return(0); } if ((minpwtime > maxpwtime) && myuid) { fprintf(stderr, "You may not change this password.\n"); return(0); } } } #endif return(1); } /* * pw_compare - compare old and new passwords * * Returns 1 if check = new, 0 if not */ pw_compare(current, check) char *current, /* Current pw (encrypted) */ *check; /* check pw (plain) */ { if (!*current) return(0); return(!strcmp(current, crypt(check, current))); } /* * pw_check - sanity check password. Right now just calls * the password check program * * Returns 1 if password is ok to use, 0 otherwise */ pw_check(newpw) char *newpw; /* New password (plain) */ { /* Put other administrative checks here */ return(checkpasswd(theUser.pw_uid, newpw)); } /* * pw_replace - replace password in passwd file */ pw_replace(newpwd, curpwd) char *newpwd, /* New password (plain) */ *curpwd; /* Old password (plain) */ { #ifdef SYSV int (*sigint)(), /* Save SIGINT */ (*sigquit)(); /* Save SIGQUIT */ #else long oldsigs, /* Signal mask save */ blocksigs = sigmask(SIGINT) | /* Signals to block */ sigmask(SIGQUIT) | /* while updating */ sigmask(SIGTSTP); /* password file */ #endif passwdp px; /* Temp */ char salt[4]; /* Encryption salt */ FILE *tf; /* File ptr to new passwd file */ int fd; /* File desc. to new passwd file */ struct stat oldstat, /* Stat of current passwd file */ newstat; /* Stat of new passwd file */ /* * Prepare password entry 'theUser' for replacement */ randomstring(salt, sizeof(salt)); theUser.pw_passwd = crypt(newpwd, salt); #ifdef SYSV /* * Update password age field */ if (theUser.pw_age) { if (maxpwtime == 0) *theUser.pw_age = '\0'; else { now = time((time_t *)0) / SEC_PER_WEEK; pwage = maxpwtime + (minpwtime << 6) + (now << 12); theUser.pw_age = l64a(pwage); } } #endif (void) umask(0); (void) stat(passwdfile, &oldstat); fd = open(passwdtemp, O_WRONLY|O_CREAT|O_EXCL, PASSWD_MODE); if (fd < 0) { if (errno == EEXIST) quit(0, "Password file busy - try again.\n"); perror("Tempfile create"); quit(1, "Cannot create temp file.\n"); } mytempfile = 1; if ((tf = fdopen(fd, "w")) == NULL) quit(1, "Cannot fdopen temp file."); #ifdef SYSV sigint = signal(SIGINT, SIG_IGN); sigquit = signal(SIGQUIT, SIG_IGN); #else oldsigs = sigblock(blocksigs); #endif setpwent(); while ((px = getpwent()) != NULL) { if (px->pw_name == 0 || px->pw_name[0] == 0) /* Sanity check */ continue; if (strcmp(px->pw_name, theUser.pw_name) == 0) px = &theUser; (void) putpwent(px, tf); } endpwent(); (void) fflush(tf); (void) fstat(fileno(tf), &newstat); (void) fclose(tf); /* * Check if the new password file is complete. Since the encrypted * password is of a fixed length, the new file should be roughly * the same size as the old one. */ if (newstat.st_size < (oldstat.st_size - SLOP)) quit(1, "New password file appears to be incomplete - aborting.\n"); if (rename(passwdfile, savefile) < 0) { perror("Password file save"); unlink(passwdtemp); quit(1, "Can't save password file"); } if (rename(passwdtemp, passwdfile) < 0) { perror("Password file replace"); (void) unlink(passwdtemp); (void) link(savefile, passwdfile); quit(1, "Can't replace password file"); } #ifdef BSD4_3 updatedbm(); #endif #ifdef SYSV (void) signal(SIGINT, sigint); (void) signal(SIGQUIT, sigquit); #else (void) sigsetmask(oldsigs); #endif } /* * pw_cleanup - clean up after myself */ pw_cleanup(code) int code; /* 0 for normal, 1 for abort */ /*NOTUSED*/ { if (mytempfile) (void) unlink(passwdtemp); } /* * _newstr - copy string into new storage */ static char * _newstr(s) char *s; /* String to copy */ { register char *t; /* Temp */ char *malloc(); if (s == NULL) return(0); t = malloc(strlen(s) + 1); if (t == NULL) quit(1, "No memory.\n"); (void) strcpy(t, s); return(t); } /* * _cppasswd - copy a passwd structure */ static _cppasswd(f,t) passwdp f, /* From */ t; /* To */ { *t = *f; t->pw_name = _newstr(f->pw_name); #ifdef SYSV t->pw_age = _newstr(f->pw_age); #endif t->pw_passwd = _newstr(f->pw_passwd); t->pw_comment = _newstr(f->pw_comment); t->pw_gecos = _newstr(f->pw_gecos); t->pw_dir = _newstr(f->pw_dir); t->pw_shell = _newstr(f->pw_shell); } #ifdef BSD4_3 /* * Update the hashed password data base */ #include <ndbm.h> #define SCOPY(S) xp = (S); while (*cp++ = *xp++) #define BCOPY(B) bcopy((char *)&(B), cp, sizeof(int)); cp += sizeof(int) updatedbm() { DBM *pwd; /* DBM data base passwd */ register char *cp, /* Data storage pointer */ *xp; /* String copy pointer */ datum key, /* DBM key datum */ data; /* DBM data store datum */ char buf[512]; /* Data buffer */ pwd = dbm_open(passwdfile, O_RDWR, 0); if (pwd == 0) return; cp = buf; /* Pack passwd entry in the form expected by the getpw* routines */ SCOPY(theUser.pw_name); SCOPY(theUser.pw_passwd); BCOPY(theUser.pw_uid); BCOPY(theUser.pw_gid); BCOPY(theUser.pw_quota); SCOPY(theUser.pw_comment); SCOPY(theUser.pw_gecos); SCOPY(theUser.pw_dir); SCOPY(theUser.pw_shell); data.dptr = buf; data.dsize = cp - buf; key.dptr = theUser.pw_name; key.dsize = strlen(theUser.pw_name); if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) { perror("dbm_store (name)"); quit(1, "Can't store passwd entry (name key).\n"); } key.dptr = (char *)&theUser.pw_uid; key.dsize = sizeof (int); if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) { perror("dbm_store (uid)"); quit(1, "Can't store passwd entry (uid key).\n"); } dbm_close(pwd); } #endif