void print_passwd(char *string, int operation, void *extra) { char msalt[3], *salt, *cryptstr; login_cap_t *lc; int pwd_gensalt(char *, int, login_cap_t *, char); void to64(char *, u_int32_t, int n); switch(operation) { case DO_MAKEKEY: /* * makekey mode: parse string into separate DES key and salt. */ if (strlen(string) != 10) { /* To be compatible... */ errx(1, "%s", strerror(EFTYPE)); } strlcpy(msalt, &string[8], sizeof msalt); salt = msalt; break; case DO_MD5: strlcpy(buffer, "$1$", sizeof buffer); to64(&buffer[3], arc4random(), 4); to64(&buffer[7], arc4random(), 4); strlcpy(buffer + 11, "$", sizeof buffer - 11); salt = buffer; break; case DO_BLF: strlcpy(buffer, bcrypt_gensalt(*(int *)extra), _PASSWORD_LEN); salt = buffer; break; case DO_DES: salt = extra; break; default: if ((lc = login_getclass(extra)) == NULL) errx(1, "unable to get login class `%s'", extra ? (char *)extra : "default"); if (!pwd_gensalt(buffer, _PASSWORD_LEN, lc, 'l')) errx(1, "can't generate salt"); salt = buffer; break; } if ((cryptstr = crypt(string, salt)) == NULL) errx(1, "crypt failed"); fputs(cryptstr, stdout); }
int main(int argc, char *argv[]) { struct rlimit rl; login_cap_t *lc; FILE *back; char passbuf[1], salt[_PASSWORD_LEN + 1]; int mode = 0, c; rl.rlim_cur = 0; rl.rlim_max = 0; (void)setrlimit(RLIMIT_CORE, &rl); (void)setpriority(PRIO_PROCESS, 0, 0); openlog("login", LOG_ODELAY, LOG_AUTH); while ((c = getopt(argc, argv, "v:s:")) != -1) switch (c) { case 'v': break; case 's': /* service */ if (strcmp(optarg, "login") == 0) mode = 0; else if (strcmp(optarg, "challenge") == 0) mode = 1; else if (strcmp(optarg, "response") == 0) mode = 2; else { syslog(LOG_ERR, "%s: invalid service", optarg); exit(1); } break; default: syslog(LOG_ERR, "usage error"); exit(1); } switch (argc - optind) { case 2: case 1: break; default: syslog(LOG_ERR, "usage error"); exit(1); } if (!(back = fdopen(3, "r+"))) { syslog(LOG_ERR, "reopening back channel: %m"); exit(1); } if (mode == 1) { fprintf(back, BI_SILENT "\n"); exit(0); } if (mode == 2) { mode = 0; c = -1; while (read(3, passbuf, (size_t)1) == 1) { if (passbuf[0] == '\0' && ++mode == 2) break; } if (mode < 2) { syslog(LOG_ERR, "protocol error on back channel"); exit(1); } } else getpass("Password:"******"xx", sizeof(salt)); crypt("password", salt); fprintf(back, BI_REJECT "\n"); exit(1); }
char * ypgetnewpasswd(struct passwd *pw, login_cap_t *lc, char **old_pass) { static char buf[_PASSWORD_LEN+1]; char salt[_PASSWORD_LEN]; sig_t saveint, savequit; int tries, pwd_tries; char *p; saveint = signal(SIGINT, kbintr); savequit = signal(SIGQUIT, kbintr); printf("Changing YP password for %s.\n", pw->pw_name); if (old_pass) { *old_pass = NULL; if (pw->pw_passwd[0]) { p = getpass("Old password:"******""; *old_pass = strdup(p); if (*old_pass == NULL) pw_error(NULL, 1, 1); } pwd_tries = pwd_gettries(lc); for (buf[0] = '\0', tries = 0;;) { p = getpass("New password:"******"s/key") == 0) { printf("That password collides with a system feature. " "Choose another.\n"); continue; } if ((tries++ < pwd_tries || pwd_tries == 0) && pwd_check(lc, p) == 0) continue; strlcpy(buf, p, sizeof buf); p = getpass("Retype new password:"******"Mismatch; try again, EOF to quit.\n"); } if (!pwd_gensalt(salt, _PASSWORD_LEN, lc, 'y')) { (void)printf("Couldn't generate salt.\n"); pw_error(NULL, 0, 0); } p = strdup(crypt(buf, salt)); if (p == NULL) pw_error(NULL, 1, 1); (void)signal(SIGINT, saveint); (void)signal(SIGQUIT, savequit); return (p); }
void yp_chpass(char *username) { char *master; int r, rpcport, status; struct yppasswd yppasswd; struct passwd *pw; struct timeval tv; CLIENT *client; extern char *domain; (void)signal(SIGINT, kbintr); (void)signal(SIGQUIT, kbintr); if ((r = yp_get_default_domain(&domain)) != 0) { warnx("can't get local YP domain. Reason: %s", yperr_string(r)); exit(1); } /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { warnx("can't find the master YP server. Reason: %s", yperr_string(r)); exit(1); } /* Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) { warnx("master YP server not running yppasswd daemon."); warnx("Can't change password."); exit(1); } if (rpcport >= IPPORT_RESERVED) { warnx("yppasswd daemon is on an invalid port."); exit(1); } /* If user doesn't exist, just prompt for old password and exit. */ pw = ypgetpwnam(username); if (pw) { if (pw->pw_uid == 0) { syslog(LOG_ERR, "attempted root password change"); pw = NULL; } else if (*pw->pw_passwd == '\0') { syslog(LOG_ERR, "%s attempting to add password", username); pw = NULL; } } if (pw == NULL) { char *p, salt[_PASSWORD_LEN + 1]; login_cap_t *lc; /* no such user, get appropriate salt to thwart timing attack */ if ((p = getpass("Old password:"******"xx", sizeof(salt)); crypt(p, salt); memset(p, 0, strlen(p)); } warnx("YP passwd database unchanged."); exit(1); } /* prompt for new password */ yppasswd.newpw.pw_passwd = ypgetnewpasswd(pw, &yppasswd.oldpass); /* tell rpc.yppasswdd */ yppasswd.newpw.pw_name = pw->pw_name; yppasswd.newpw.pw_uid = pw->pw_uid; yppasswd.newpw.pw_gid = pw->pw_gid; yppasswd.newpw.pw_gecos = pw->pw_gecos; yppasswd.newpw.pw_dir = pw->pw_dir; yppasswd.newpw.pw_shell = pw->pw_shell; client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client == NULL) { warnx("cannot contact yppasswdd on %s: Reason: %s", master, yperr_string(YPERR_YPBIND)); free(yppasswd.newpw.pw_passwd); exit(1); } client->cl_auth = authunix_create_default(); tv.tv_sec = 2; tv.tv_usec = 0; r = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &yppasswd, xdr_int, &status, tv); if (r) warnx("rpc to yppasswdd failed."); else if (status) { printf("Couldn't change YP password.\n"); free(yppasswd.newpw.pw_passwd); exit(1); } printf("The YP password has been changed on %s, the master YP passwd server.\n", master); free(yppasswd.newpw.pw_passwd); (void)writev(BACK_CHANNEL, iov, 2); exit(0); }