4 * PAM password management functions for pam_krb5
6 * $FreeBSD: src/lib/libpam/modules/pam_krb5/pam_krb5_pass.c,v 1.1.2.1 2001/06/07 09:37:07 markm Exp $
7 * $DragonFly: src/lib/libpam/modules/pam_krb5/Attic/pam_krb5_pass.c,v 1.2 2003/06/17 04:26:50 dillon Exp $
10 static const char rcsid[] = "$Id: pam_krb5_pass.c,v 1.3 1999/01/19 23:43:11 fcusack Exp $";
13 #include <stdio.h> /* sprintf */
14 #include <stdlib.h> /* malloc */
15 #include <syslog.h> /* syslog */
16 #include <security/pam_appl.h>
17 #include <security/pam_modules.h>
22 /* A useful logging macro */
23 #define DLOG(error_func, error_msg) \
25 syslog(LOG_DEBUG, "pam_krb5: pam_sm_chauthtok(%s %s): %s: %s", \
26 service, name, error_func, error_msg)
28 /* Change a user's password */
30 pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
32 krb5_error_code krbret;
33 krb5_context pam_context;
36 krb5_get_init_creds_opt opts;
39 krb5_data result_code_string, result_string;
42 char *name, *service = NULL, *pass = NULL, *pass2;
43 char *princ_name = NULL;
47 int try_first_pass = 0, use_first_pass = 0;
49 if (!(flags & PAM_UPDATE_AUTHTOK))
50 return PAM_AUTHTOK_ERR;
52 for (i = 0; i < argc; i++) {
53 if (strcmp(argv[i], "debug") == 0)
55 else if (strcmp(argv[i], "try_first_pass") == 0)
57 else if (strcmp(argv[i], "use_first_pass") == 0)
62 if ((pam_get_item(pamh, PAM_USER, (const void **) &name)) != 0) {
63 return PAM_SERVICE_ERR;
66 /* Get service name */
67 (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
73 if ((krbret = krb5_init_context(&pam_context)) != 0) {
74 DLOG("krb5_init_context()", error_message(krbret));
75 return PAM_SERVICE_ERR;
78 if ((krbret = krb5_init_context(&pam_context)) != 0) {
79 DLOG("krb5_init_context()", error_message(krbret));
80 return PAM_SERVICE_ERR;
82 krb5_get_init_creds_opt_init(&opts);
83 memset(&creds, 0, sizeof(krb5_creds));
85 /* Get principal name */
86 if ((krbret = krb5_parse_name(pam_context, name, &princ)) != 0) {
87 DLOG("krb5_parse_name()", error_message(krbret));
88 pamret = PAM_USER_UNKNOWN;
92 /* Now convert the principal name into something human readable */
93 if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) {
94 DLOG("krb5_unparse_name()", error_message(krbret));
95 pamret = PAM_SERVICE_ERR;
100 prompt = malloc(16 + strlen(princ_name));
102 DLOG("malloc()", "failure");
103 pamret = PAM_BUF_ERR;
106 (void) sprintf(prompt, "Password for %s: ", princ_name);
108 if (try_first_pass || use_first_pass)
109 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass);
114 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF,
116 DLOG("get_user_info()", pam_strerror(pamh, pamret));
117 pamret = PAM_SERVICE_ERR;
120 /* We have to free pass. */
121 if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) {
122 DLOG("pam_set_item()", pam_strerror(pamh, pamret));
124 pamret = PAM_SERVICE_ERR;
128 /* Now we get it back from the library. */
129 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass);
132 if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ,
133 pass, pam_prompter, pamh, 0, "kadmin/changepw", &opts)) != 0) {
134 DLOG("krb5_get_init_creds_password()", error_message(krbret));
135 if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
139 pamret = PAM_AUTH_ERR;
143 /* Now get the new password */
145 prompt = "Enter new password: ";
146 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass))
148 DLOG("get_user_info()", pam_strerror(pamh, pamret));
150 pamret = PAM_SERVICE_ERR;
153 prompt = "Enter it again: ";
154 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass2))
156 DLOG("get_user_info()", pam_strerror(pamh, pamret));
158 pamret = PAM_SERVICE_ERR;
163 if (strcmp(pass, pass2) != 0) {
164 DLOG("strcmp()", "passwords not equal");
165 pamret = PAM_AUTHTOK_ERR;
170 if ((krbret = krb5_change_password(pam_context, &creds, pass,
171 &result_code, &result_code_string, &result_string)) != 0) {
172 DLOG("krb5_change_password()", error_message(krbret));
173 pamret = PAM_AUTHTOK_ERR;
177 DLOG("krb5_change_password() (result_code)", "");
178 pamret = PAM_AUTHTOK_ERR;
182 if (result_string.data)
183 free(result_string.data);
184 if (result_code_string.data)
185 free(result_code_string.data);
188 krb5_free_cred_contents(pam_context, &creds);
190 krb5_free_principal(pam_context, princ);
197 krb5_free_context(pam_context);
198 DLOG("exit", pamret ? "failure" : "success");