diff -urN ypserv-1.3.11.orig/update.c ypserv-1.3.11/update.c --- ypserv-1.3.11.orig/update.c Sun Mar 19 14:58:28 2000 +++ ypserv-1.3.11/update.c Tue May 30 18:28:57 2000 @@ -64,6 +64,9 @@ #define _PATH_SHELLS "/etc/shells" #endif +#define OPW_TMPFILE "/etc/security/nopasswd" +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" + /* How often to retry locking the passwd file... */ #define MAX_RETRIES 5 @@ -79,10 +82,13 @@ /* Will be set by the main function */ char *external_update_program = NULL; +int remember_old_passwords = 0; + static int external_update_env (yppasswd *yppw); static int external_update_pipe (yppasswd *yppw); static int update_files (yppasswd *yppw, char *logbuf, int *shadow_changed, int *passwd_changed, int *chfn, int *chsh); +static int save_old_password(const yppasswd *ypw, int howmany); /* Argument validation. Avoid \n... (ouch). We can't use isprint, because people may use 8bit chars which @@ -296,6 +302,8 @@ return &res; } + save_old_password(yppw,remember_old_passwords); + res = update_files (yppw, logbuf, &shadow_changed, &passwd_changed, &chfn, &chsh); @@ -667,6 +675,84 @@ _exit (1); /* fall-through */ } return res; +} + +static int +save_old_password(const yppasswd *ypw, int howmany) +{ + char buf[16384]; + char nbuf[16384]; + char *s_luser, *s_uid, *s_npas, *s_pas; + int npas, oldmask; + FILE *pwfile, *opwfile; + int err = 0; + int found = 0; + char *pass = ypw->oldpass; + char *forwho = ypw->newpw.pw_name; + int foruid = ypw->newpw.pw_uid; + + if (howmany <= 0) + return 0; + + if (pass == NULL) + return 0; + + oldmask = umask(077); + pwfile = fopen(OPW_TMPFILE, "w"); + umask(oldmask); + opwfile = fopen(OLD_PASSWORDS_FILE, "r"); + if (pwfile == NULL || opwfile == NULL) + return 1; + chown(OPW_TMPFILE, 0, 0); + chmod(OPW_TMPFILE, 0600); + + while (fgets(buf, 16380, opwfile)) { + if (!strncmp(buf, forwho, strlen(forwho))) { + buf[strlen(buf) - 1] = '\0'; + s_luser = strtok(buf, ":"); + s_uid = strtok(NULL, ":"); + s_npas = strtok(NULL, ":"); + s_pas = strtok(NULL, ":"); + npas = strtol(s_npas, NULL, 10) + 1; + while (npas > howmany) { + s_pas = strpbrk(s_pas, ","); + if (s_pas != NULL) + s_pas++; + npas--; + } + if (s_pas == NULL) + sprintf(nbuf, "%s:%s:%d:%s\n", + s_luser, s_uid, npas, crypt(pass, "$1$")); + else + sprintf(nbuf, "%s:%s:%d:%s,%s\n", + s_luser, s_uid, npas, s_pas, crypt(pass, "$1$")); + if (fputs(nbuf, pwfile) < 0) { + err = 1; + break; + } + found = 1; + } else if (fputs(buf, pwfile) < 0) { + err = 1; + break; + } + } + fclose(opwfile); + if (!found) { + sprintf(nbuf, "%s:%d:1:%s\n", + forwho, foruid, crypt(pass, "$1$")); + if (fputs(nbuf, pwfile) < 0) { + err = 1; + } + } + if (fclose(pwfile)) { + err = errno; + } + if (!err) + rename(OPW_TMPFILE, OLD_PASSWORDS_FILE); + else + unlink(OPW_TMPFILE); + + return err; } /*===============================================================* diff -urN ypserv-1.3.11.orig/yppasswd.h ypserv-1.3.11/yppasswd.h --- ypserv-1.3.11.orig/yppasswd.h Tue May 18 22:11:04 1999 +++ ypserv-1.3.11/yppasswd.h Tue May 30 18:22:00 2000 @@ -70,6 +70,7 @@ extern char *path_shadow_tmp; extern char *path_shadow_old; extern char *external_update_program; +extern int remember_old_passwords; /* This command is forked to rebuild the NIS maps after a successful * update. MAP_UPDATE0 is used as argv[0]. diff -urN ypserv-1.3.11.orig/yppasswdd.c ypserv-1.3.11/yppasswdd.c --- ypserv-1.3.11.orig/yppasswdd.c Tue May 30 18:20:56 2000 +++ ypserv-1.3.11/yppasswdd.c Tue May 30 18:22:00 2000 @@ -279,10 +279,11 @@ {"help", no_argument, NULL, 'h'}, {"execute", required_argument, NULL, 'x'}, {"debug", no_argument, NULL, '\254'}, + {"remember", required_argument, NULL, 'r'}, {NULL, 0, NULL, '\0'} }; - c=getopt_long (argc, argv, "e:p:s:uhvD:E:x:m", long_options, + c=getopt_long (argc, argv, "e:p:s:uhvD:E:x:r:m", long_options, &option_index); if (c == EOF) break; @@ -350,6 +351,11 @@ exit (0); case '\254': /* --debug */ debug_flag = 1; + break; + case 'r': + remember_old_passwords = strtol(optarg, NULL, 10); + if (remember_old_passwords > 400) + remember_old_passwords = 400; break; default: usage (stderr, 1);