Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/kadm5/chpass_util.c
39536 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
4
*/
5
6
7
#include "k5-int.h"
8
9
#include <kadm5/admin.h>
10
#include "admin_internal.h"
11
12
13
#define string_text error_message
14
15
/*
16
* Function: kadm5_chpass_principal_util
17
*
18
* Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages
19
*
20
* Arguments:
21
*
22
* princ (input) a krb5b_principal structure for the
23
* principal whose password we should change.
24
*
25
* new_password (input) NULL or a null terminated string with the
26
* the principal's desired new password. If new_password
27
* is NULL then this routine will read a new password.
28
*
29
* pw_ret (output) if non-NULL, points to a static buffer
30
* containing the new password (if password is prompted
31
* internally), or to the new_password argument (if
32
* that is non-NULL). If the former, then the buffer
33
* is only valid until the next call to the function,
34
* and the caller should be sure to zero it when
35
* it is no longer needed.
36
*
37
* msg_ret (output) a useful message is copied here.
38
*
39
* <return value> exit status of 0 for success, else the com err code
40
* for the last significant routine called.
41
*
42
* Requires:
43
*
44
* A msg_ret should point to a buffer large enough for the messasge.
45
*
46
* Effects:
47
*
48
* Modifies:
49
*
50
*
51
*/
52
53
kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
54
void *lhandle,
55
krb5_principal princ,
56
char *new_pw,
57
char **ret_pw,
58
char *msg_ret,
59
unsigned int msg_len)
60
{
61
int code, code2;
62
unsigned int pwsize;
63
static char buffer[255];
64
char *new_password;
65
kadm5_principal_ent_rec princ_ent;
66
kadm5_policy_ent_rec policy_ent;
67
68
_KADM5_CHECK_HANDLE(server_handle);
69
70
if (ret_pw)
71
*ret_pw = NULL;
72
73
if (new_pw != NULL) {
74
new_password = new_pw;
75
} else { /* read the password */
76
krb5_context context;
77
78
if ((code = (int) kadm5_init_krb5_context(&context)) == 0) {
79
pwsize = sizeof(buffer);
80
code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,
81
KADM5_PW_SECOND_PROMPT,
82
buffer, &pwsize);
83
krb5_free_context(context);
84
}
85
86
if (code == 0)
87
new_password = buffer;
88
else {
89
#ifdef ZEROPASSWD
90
memset(buffer, 0, sizeof(buffer));
91
#endif
92
if (code == KRB5_LIBOS_BADPWDMATCH) {
93
strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
94
msg_len - 1);
95
msg_ret[msg_len - 1] = '\0';
96
return(code);
97
} else {
98
snprintf(msg_ret, msg_len, "%s %s\n\n%s",
99
error_message(code),
100
string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
101
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
102
msg_ret[msg_len - 1] = '\0';
103
return(code);
104
}
105
}
106
if (pwsize == 0) {
107
#ifdef ZEROPASSWD
108
memset(buffer, 0, sizeof(buffer));
109
#endif
110
strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1);
111
msg_ret[msg_len - 1] = '\0';
112
return(KRB5_LIBOS_CANTREADPWD); /* could do better */
113
}
114
}
115
116
if (ret_pw)
117
*ret_pw = new_password;
118
119
code = kadm5_chpass_principal(server_handle, princ, new_password);
120
121
#ifdef ZEROPASSWD
122
if (!ret_pw)
123
memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */
124
#endif
125
126
if (code == KADM5_OK) {
127
strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1);
128
msg_ret[msg_len - 1] = '\0';
129
return(0);
130
}
131
132
if ((code != KADM5_PASS_Q_TOOSHORT) &&
133
(code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) &&
134
(code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) {
135
/* Can't get more info for other errors */
136
snprintf(msg_ret, msg_len, "%s\n%s %s\n",
137
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
138
error_message(code),
139
string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
140
return(code);
141
}
142
143
/* Ok, we have a password quality error. Return a good message */
144
145
if (code == KADM5_PASS_REUSE) {
146
strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1);
147
msg_ret[msg_len - 1] = '\0';
148
return(code);
149
}
150
151
if (code == KADM5_PASS_Q_DICT) {
152
strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY),
153
msg_len - 1);
154
msg_ret[msg_len - 1] = '\0';
155
return(code);
156
}
157
158
/* Look up policy for the remaining messages */
159
160
code2 = kadm5_get_principal (lhandle, princ, &princ_ent,
161
KADM5_PRINCIPAL_NORMAL_MASK);
162
if (code2 != 0) {
163
snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n",
164
error_message(code2),
165
string_text(CHPASS_UTIL_GET_PRINC_INFO),
166
error_message(code),
167
string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
168
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
169
msg_ret[msg_len - 1] = '\0';
170
return(code);
171
}
172
173
if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {
174
/* Some module implements its own password policy. */
175
snprintf(msg_ret, msg_len, "%s\n\n%s",
176
error_message(code),
177
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
178
msg_ret[msg_len - 1] = '\0';
179
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
180
return(code);
181
}
182
183
code2 = kadm5_get_policy(lhandle, princ_ent.policy,
184
&policy_ent);
185
if (code2 != 0) {
186
snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n ", error_message(code2),
187
string_text(CHPASS_UTIL_GET_POLICY_INFO),
188
error_message(code),
189
string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
190
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
191
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
192
return(code);
193
}
194
195
if (code == KADM5_PASS_Q_TOOSHORT) {
196
snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT),
197
policy_ent.pw_min_length);
198
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
199
(void) kadm5_free_policy_ent(lhandle, &policy_ent);
200
return(code);
201
}
202
203
/* Can't get more info for other errors */
204
205
if (code == KADM5_PASS_Q_CLASS) {
206
snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_TOO_FEW_CLASSES),
207
policy_ent.pw_min_classes);
208
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
209
(void) kadm5_free_policy_ent(lhandle, &policy_ent);
210
return(code);
211
}
212
213
if (code == KADM5_PASS_TOOSOON) {
214
time_t until;
215
char *time_string, *ptr;
216
217
until = ts_incr(princ_ent.last_pwd_change, policy_ent.pw_min_life);
218
219
time_string = ctime(&until);
220
if (time_string == NULL)
221
time_string = "(error)";
222
else if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
223
*ptr = '\0';
224
225
snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON),
226
time_string);
227
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
228
(void) kadm5_free_policy_ent(lhandle, &policy_ent);
229
return(code);
230
}
231
232
/* We should never get here, but just in case ... */
233
snprintf(msg_ret, msg_len, "%s\n%s %s\n",
234
string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
235
error_message(code),
236
string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
237
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
238
(void) kadm5_free_policy_ent(lhandle, &policy_ent);
239
return(code);
240
}
241
242