1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
15 #include <kadm5/admin.h>
16 #include "admin_internal.h"
20 #define string_text error_message
23 * Function: kadm5_chpass_principal_util
25 * Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages
29 * princ (input) a krb5b_principal structure for the
30 * principal whose password we should change.
32 * new_password (input) NULL or a null terminated string with the
33 * the principal's desired new password. If new_password
34 * is NULL then this routine will read a new password.
36 * pw_ret (output) if non-NULL, points to a static buffer
37 * containing the new password (if password is prompted
38 * internally), or to the new_password argument (if
39 * that is non-NULL). If the former, then the buffer
40 * is only valid until the next call to the function,
41 * and the caller should be sure to zero it when
42 * it is no longer needed.
44 * msg_ret (output) a useful message is copied here.
46 * <return value> exit status of 0 for success, else the com err code
47 * for the last significant routine called.
51 * A msg_ret should point to a buffer large enough for the messasge.
60 kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
70 static char buffer[255];
72 kadm5_principal_ent_rec princ_ent;
73 kadm5_policy_ent_rec policy_ent;
75 _KADM5_CHECK_HANDLE(server_handle);
81 new_password = new_pw;
82 } else { /* read the password */
85 if ((code = (int) kadm5_init_krb5_context(&context)) == 0) {
86 pwsize = sizeof(buffer);
87 code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,
88 KADM5_PW_SECOND_PROMPT,
90 krb5_free_context(context);
94 new_password = buffer;
97 memset(buffer, 0, sizeof(buffer));
99 if (code == KRB5_LIBOS_BADPWDMATCH) {
100 strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
102 msg_ret[msg_len - 1] = '\0';
105 snprintf(msg_ret, msg_len, "%s %s\n\n%s",
107 string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
108 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
109 msg_ret[msg_len - 1] = '\0';
115 memset(buffer, 0, sizeof(buffer));
117 strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1);
118 msg_ret[msg_len - 1] = '\0';
119 return(KRB5_LIBOS_CANTREADPWD); /* could do better */
124 *ret_pw = new_password;
126 code = kadm5_chpass_principal(server_handle, princ, new_password);
130 memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */
133 if (code == KADM5_OK) {
134 strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1);
135 msg_ret[msg_len - 1] = '\0';
139 if ((code != KADM5_PASS_Q_TOOSHORT) &&
140 (code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) &&
141 (code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) {
142 /* Can't get more info for other errors */
143 snprintf(msg_ret, msg_len, "%s\n%s %s\n",
144 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
146 string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
150 /* Ok, we have a password quality error. Return a good message */
152 if (code == KADM5_PASS_REUSE) {
153 strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1);
154 msg_ret[msg_len - 1] = '\0';
158 if (code == KADM5_PASS_Q_DICT) {
159 strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY),
161 msg_ret[msg_len - 1] = '\0';
165 /* Look up policy for the remaining messages */
167 code2 = kadm5_get_principal (lhandle, princ, &princ_ent,
168 KADM5_PRINCIPAL_NORMAL_MASK);
170 snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n",
171 error_message(code2),
172 string_text(CHPASS_UTIL_GET_PRINC_INFO),
174 string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
175 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
176 msg_ret[msg_len - 1] = '\0';
180 if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {
181 /* Some module implements its own password policy. */
182 snprintf(msg_ret, msg_len, "%s\n\n%s",
184 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
185 msg_ret[msg_len - 1] = '\0';
186 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
190 code2 = kadm5_get_policy(lhandle, princ_ent.policy,
193 snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n ", error_message(code2),
194 string_text(CHPASS_UTIL_GET_POLICY_INFO),
196 string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
197 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
198 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
202 if (code == KADM5_PASS_Q_TOOSHORT) {
203 snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT),
204 policy_ent.pw_min_length);
205 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
206 (void) kadm5_free_policy_ent(lhandle, &policy_ent);
210 /* Can't get more info for other errors */
212 if (code == KADM5_PASS_Q_CLASS) {
213 snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_TOO_FEW_CLASSES),
214 policy_ent.pw_min_classes);
215 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
216 (void) kadm5_free_policy_ent(lhandle, &policy_ent);
220 if (code == KADM5_PASS_TOOSOON) {
222 char *time_string, *ptr;
224 until = princ_ent.last_pwd_change + policy_ent.pw_min_life;
226 time_string = ctime(&until);
227 if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
230 snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON),
232 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
233 (void) kadm5_free_policy_ent(lhandle, &policy_ent);
237 /* We should never get here, but just in case ... */
238 snprintf(msg_ret, msg_len, "%s\n%s %s\n",
239 string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
241 string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
242 (void) kadm5_free_principal_ent(lhandle, &princ_ent);
243 (void) kadm5_free_policy_ent(lhandle, &policy_ent);