int main(int argc, char **argv) { char hostname[MAXHOSTNAMELEN]; struct passwd *pwd = NULL; int o, pam_err; uid_t uid; while ((o = getopt(argc, argv, "d:h:loy")) != -1) switch (o) { case 'd': yp_domain = optarg; break; case 'h': yp_host = optarg; break; case 'l': case 'o': case 'y': /* compatibility */ break; default: usage(); } argc -= optind; argv += optind; uid = getuid(); switch (argc) { case 0: if ((pwd = getpwuid(uid)) == NULL) errx(1, "who are you?"); break; case 1: if ((pwd = getpwnam(*argv)) == NULL) errx(1, "%s: no such user", *argv); break; default: usage(); } if (uid != 0 && uid != pwd->pw_uid) errx(1, "permission denied"); /* check where the user's from */ switch (pwd->pw_fields & _PWF_SOURCE) { case _PWF_FILES: fprintf(stderr, "Changing local password for %s\n", pwd->pw_name); break; case _PWF_NIS: fprintf(stderr, "Changing NIS password for %s\n", pwd->pw_name); break; default: fprintf(stderr, "Changing password for %s\n", pwd->pw_name); } #define pam_check(func) do { \ if (pam_err != PAM_SUCCESS) { \ if (pam_err == PAM_AUTH_ERR || pam_err == PAM_PERM_DENIED || \ pam_err == PAM_AUTHTOK_RECOVERY_ERR) \ warnx("sorry"); \ else \ warnx("%s(): %s", func, pam_strerror(pamh, pam_err)); \ goto end; \ } \ } while (0) /* initialize PAM */ pam_err = pam_start("passwd", pwd->pw_name, &pamc, &pamh); pam_check("pam_start"); pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO)); pam_check("pam_set_item"); gethostname(hostname, sizeof hostname); pam_err = pam_set_item(pamh, PAM_RHOST, hostname); pam_check("pam_set_item"); pam_err = pam_set_item(pamh, PAM_RUSER, getlogin()); pam_check("pam_set_item"); /* set YP domain and host */ pam_err = pam_set_data(pamh, "yp_domain", yp_domain, NULL); pam_check("pam_set_data"); pam_err = pam_set_data(pamh, "yp_server", yp_host, NULL); pam_check("pam_set_data"); /* set new password */ pam_err = pam_chauthtok(pamh, 0); pam_check("pam_chauthtok"); end: pam_end(pamh, pam_err); exit(pam_err == PAM_SUCCESS ? 0 : 1); }
void pwpam_process(const char *username, int argc, char **argv) { int ch, pam_err; char hostname[MAXHOSTNAMELEN + 1]; /* details about the invoking user for logging */ const uid_t i_uid = getuid(); const struct passwd *const i_pwd = getpwuid(i_uid); const char *const i_username = (i_pwd && i_pwd->pw_name) ? i_pwd->pw_name : "(null)"; while ((ch = getopt(argc, argv, "")) != -1) { switch (ch) { default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; switch (argc) { case 0: /* username already provided */ break; case 1: username = argv[0]; break; default: usage(); /* NOTREACHED */ } (void)printf("Changing password for %s.\n", username); /* initialize PAM -- always use the program name "passwd" */ pam_err = pam_start("passwd", username, &pamc, &pamh); if (pam_err != PAM_SUCCESS) errx(1, "unable to start PAM session: %s", pam_strerror(NULL, pam_err)); pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO)); pam_check("unable to set TTY"); (void)gethostname(hostname, sizeof hostname); pam_err = pam_set_item(pamh, PAM_RHOST, hostname); pam_check("unable to set RHOST"); pam_err = pam_set_item(pamh, PAM_RUSER, getlogin()); pam_check("unable to set RUSER"); /* set new password */ pam_err = pam_chauthtok(pamh, 0); if (pam_err != PAM_SUCCESS) { if (pam_err == PAM_PERM_DENIED) { syslog(LOG_AUTH | LOG_NOTICE, "user %s (UID %lu) failed to change the " "PAM authentication token of user %s: %s", i_username, (unsigned long)i_uid, username, pam_strerror(pamh, pam_err)); } printf("Unable to change auth token: %s\n", pam_strerror(pamh, pam_err)); } else { syslog(LOG_AUTH | LOG_INFO, "user %s (UID %lu) successfully changed the " "PAM authentication token of user %s", i_username, (unsigned long)i_uid, username); } end: pam_end(pamh, pam_err); if (pam_err == PAM_SUCCESS) return; exit(1); }