/* * Written by Cristian Gafton */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include char *username = NULL; /* username we are changing the password for */ char *password = NULL; /* password we are changing the password to */ /* a dummy coversation function */ static int dummy_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int i; struct pam_response *response = NULL; (void)appdata_ptr; response = malloc(sizeof(struct pam_response) * num_msg); if (response == (struct pam_response *) 0) return PAM_CONV_ERR; for (i = 0; i < num_msg; i++) { response[i].resp_retcode = PAM_SUCCESS; switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: response[i].resp = username; break; case PAM_PROMPT_ECHO_OFF: response[i].resp = password; break; case PAM_TEXT_INFO: case PAM_ERROR_MSG: /* ignore it, but pam still wants a NULL response... */ response[i].resp = NULL; break; default: /* Must be an error of some sort... */ free(response); return PAM_CONV_ERR; } } *resp = response; return PAM_SUCCESS; } /* conversation function & corresponding structure */ static struct pam_conv conv = { &dummy_conv, NULL }; int main(int argc, char *const argv[]) { int retval; pam_handle_t *pamh = NULL; /* XXX; expand me: * * here you should obtains somehow the username and password and * set the global variables */ (void)argc; (void)argv; assert(username != NULL); assert(password != NULL); retval = pam_start("passwd", username, &conv, &pamh); while (retval == PAM_SUCCESS) { /* use loop to avoid goto... */ retval = pam_chauthtok(pamh, 0); if (retval != PAM_SUCCESS) break; /* all done */ retval = pam_end(pamh, PAM_SUCCESS); if (retval != PAM_SUCCESS) break; /* quit gracefully */ exit(0); } if (retval != PAM_SUCCESS) fprintf(stderr, "changing password: %s\n", pam_strerror(pamh, retval)); if (pamh != NULL) { (void) pam_end(pamh, PAM_SUCCESS); pamh = NULL; } exit(1); }