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.3 2004/01/23 14:37:01 joerg 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 */
17 #include <security/pam_appl.h>
18 #include <security/pam_modules.h>
23 /* A useful logging macro */
24 #define DLOG(error_func, error_msg) \
26 syslog(LOG_DEBUG, "pam_krb5: pam_sm_chauthtok(%s %s): %s: %s", \
27 service, name, error_func, error_msg)
29 /* Change a user's password */
31 pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
33 krb5_error_code krbret;
34 krb5_context pam_context;
37 krb5_get_init_creds_opt opts;
40 krb5_data result_code_string, result_string;
43 char *name, *service = NULL, *pass = NULL, *pass2;
44 char *princ_name = NULL;
48 int try_first_pass = 0, use_first_pass = 0;
50 if (!(flags & PAM_UPDATE_AUTHTOK))
51 return PAM_AUTHTOK_ERR;
53 for (i = 0; i < argc; i++) {
54 if (strcmp(argv[i], "debug") == 0)
56 else if (strcmp(argv[i], "try_first_pass") == 0)
58 else if (strcmp(argv[i], "use_first_pass") == 0)
63 if ((pam_get_item(pamh, PAM_USER, (const void **) &name)) != 0) {
64 return PAM_SERVICE_ERR;
67 /* Get service name */
68 (void) pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
74 if ((krbret = krb5_init_context(&pam_context)) != 0) {
75 DLOG("krb5_init_context()", error_message(krbret));
76 return PAM_SERVICE_ERR;
79 if ((krbret = krb5_init_context(&pam_context)) != 0) {
80 DLOG("krb5_init_context()", error_message(krbret));
81 return PAM_SERVICE_ERR;
83 krb5_get_init_creds_opt_init(&opts);
84 memset(&creds, 0, sizeof(krb5_creds));
86 /* Get principal name */
87 if ((krbret = krb5_parse_name(pam_context, name, &princ)) != 0) {
88 DLOG("krb5_parse_name()", error_message(krbret));
89 pamret = PAM_USER_UNKNOWN;
93 /* Now convert the principal name into something human readable */
94 if ((krbret = krb5_unparse_name(pam_context, princ, &princ_name)) != 0) {
95 DLOG("krb5_unparse_name()", error_message(krbret));
96 pamret = PAM_SERVICE_ERR;
101 prompt = malloc(16 + strlen(princ_name));
103 DLOG("malloc()", "failure");
104 pamret = PAM_BUF_ERR;
107 (void) sprintf(prompt, "Password for %s: ", princ_name);
109 if (try_first_pass || use_first_pass)
110 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass);
115 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF,
117 DLOG("get_user_info()", pam_strerror(pamh, pamret));
118 pamret = PAM_SERVICE_ERR;
121 /* We have to free pass. */
122 if ((pamret = pam_set_item(pamh, PAM_AUTHTOK, pass)) != 0) {
123 DLOG("pam_set_item()", pam_strerror(pamh, pamret));
125 pamret = PAM_SERVICE_ERR;
129 /* Now we get it back from the library. */
130 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **) &pass);
133 if ((krbret = krb5_get_init_creds_password(pam_context, &creds, princ,
134 pass, pam_prompter, pamh, 0, "kadmin/changepw", &opts)) != 0) {
135 DLOG("krb5_get_init_creds_password()", error_message(krbret));
136 if (try_first_pass && krbret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
140 pamret = PAM_AUTH_ERR;
144 /* Now get the new password */
146 prompt = "Enter new password: ";
147 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass))
149 DLOG("get_user_info()", pam_strerror(pamh, pamret));
151 pamret = PAM_SERVICE_ERR;
154 prompt = "Enter it again: ";
155 if ((pamret = get_user_info(pamh, prompt, PAM_PROMPT_ECHO_OFF, &pass2))
157 DLOG("get_user_info()", pam_strerror(pamh, pamret));
159 pamret = PAM_SERVICE_ERR;
164 if (strcmp(pass, pass2) != 0) {
165 DLOG("strcmp()", "passwords not equal");
166 pamret = PAM_AUTHTOK_ERR;
171 if ((krbret = krb5_change_password(pam_context, &creds, pass,
172 &result_code, &result_code_string, &result_string)) != 0) {
173 DLOG("krb5_change_password()", error_message(krbret));
174 pamret = PAM_AUTHTOK_ERR;
178 DLOG("krb5_change_password() (result_code)", "");
179 pamret = PAM_AUTHTOK_ERR;
183 if (result_string.data)
184 free(result_string.data);
185 if (result_code_string.data)
186 free(result_code_string.data);
189 krb5_free_cred_contents(pam_context, &creds);
191 krb5_free_principal(pam_context, princ);
198 krb5_free_context(pam_context);
199 DLOG("exit", pamret ? "failure" : "success");