11
11
#define GETSOCKNAME_ARG3_TYPE int
14
#define RFC3244_VERSION 0xff80
15
process_chpw_request(context, server_handle, realm, s, keytab, sockin,
17
process_chpw_request(context, server_handle, realm, keytab,
18
local_faddr, remote_faddr, req, rep)
17
19
krb5_context context;
18
20
void *server_handle;
21
22
krb5_keytab keytab;
22
struct sockaddr_in *sockin;
23
krb5_fulladdr *local_faddr;
24
krb5_fulladdr *remote_faddr;
26
28
krb5_error_code ret;
29
krb5_address local_kaddr, remote_kaddr;
30
int allocated_mem = 0;
31
31
krb5_data ap_req, ap_rep;
32
32
krb5_auth_context auth_context;
33
33
krb5_principal changepw;
34
krb5_principal client, target = NULL;
34
35
krb5_ticket *ticket;
35
36
krb5_data cipher, clear;
36
struct sockaddr local_addr, remote_addr;
37
GETSOCKNAME_ARG3_TYPE addrlen;
38
37
krb5_replay_data replay;
39
38
krb5_error krberror;
41
40
char strresult[1024];
41
char *clientstr = NULL, *targetstr = NULL;
42
const char *errmsg = NULL;
45
struct sockaddr_storage ss;
48
krb5_address *addr = remote_faddr->address;
132
140
numresult = KRB5_KPASSWD_AUTHERROR;
133
strcpy(strresult, "Failed reading application request");
137
/* set up address info */
139
addrlen = sizeof(local_addr);
141
if (getsockname(s, &local_addr, &addrlen) < 0) {
143
numresult = KRB5_KPASSWD_HARDERROR;
144
strcpy(strresult, "Failed getting server internet address");
148
/* some brain-dead OS's don't return useful information from
149
* the getsockname call. Namely, windows and solaris. */
151
if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0) {
152
local_kaddr.addrtype = ADDRTYPE_INET;
154
sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
155
local_kaddr.contents =
156
(krb5_octet *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
158
krb5_address **addrs;
160
krb5_os_localaddr(context, &addrs);
161
local_kaddr.magic = addrs[0]->magic;
162
local_kaddr.addrtype = addrs[0]->addrtype;
163
local_kaddr.length = addrs[0]->length;
164
local_kaddr.contents = malloc(addrs[0]->length);
165
memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
168
krb5_free_addresses(context, addrs);
171
addrlen = sizeof(remote_addr);
173
if (getpeername(s, &remote_addr, &addrlen) < 0) {
175
numresult = KRB5_KPASSWD_HARDERROR;
176
strcpy(strresult, "Failed getting client internet address");
180
remote_kaddr.addrtype = ADDRTYPE_INET;
181
remote_kaddr.length =
182
sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
183
remote_kaddr.contents =
184
(krb5_octet *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
186
remote_kaddr.addrtype = ADDRTYPE_INET;
187
remote_kaddr.length = sizeof(sockin->sin_addr);
188
remote_kaddr.contents = (krb5_octet *) &sockin->sin_addr;
141
strlcpy(strresult, "Failed reading application request",
190
146
/* mk_priv requires that the local address be set.
191
147
getsockname is used for this. rd_priv requires that the
192
148
remote address be set. recvfrom is used for this. If
234
184
ret = krb5_rd_priv(context, auth_context, &cipher, &clear, &replay);
236
186
numresult = KRB5_KPASSWD_HARDERROR;
237
strcpy(strresult, "Failed decrypting request");
187
strlcpy(strresult, "Failed decrypting request", sizeof(strresult));
241
ret = krb5_unparse_name(context, ticket->enc_part2->client, &clientstr);
191
client = ticket->enc_part2->client;
193
/* decode ChangePasswdData for setpw requests */
194
if (vno == RFC3244_VERSION) {
195
krb5_data *clear_data;
197
ret = decode_krb5_setpw_req(&clear, &clear_data, &target);
199
numresult = KRB5_KPASSWD_MALFORMED;
200
strlcpy(strresult, "Failed decoding ChangePasswdData",
205
memset(clear.data, 0, clear.length);
211
if (target != NULL) {
212
ret = krb5_unparse_name(context, target, &targetstr);
214
numresult = KRB5_KPASSWD_HARDERROR;
215
strlcpy(strresult, "Failed unparsing target name for log",
222
ret = krb5_unparse_name(context, client, &clientstr);
243
224
numresult = KRB5_KPASSWD_HARDERROR;
244
strcpy(strresult, "Failed unparsing client name for log");
225
strlcpy(strresult, "Failed unparsing client name for log",
230
/* for cpw, verify that this is an AS_REQ ticket */
232
(ticket->enc_part2->flags & TKT_FLG_INITIAL) == 0) {
233
numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
234
strlcpy(strresult, "Ticket must be derived from a password",
247
239
/* change the password */
249
241
ptr = (char *) malloc(clear.length+1);
250
242
memcpy(ptr, clear.data, clear.length);
251
243
ptr[clear.length] = '\0';
253
ret = schpw_util_wrapper(server_handle, ticket->enc_part2->client,
245
ret = schpw_util_wrapper(server_handle, client, target,
246
(ticket->enc_part2->flags & TKT_FLG_INITIAL) != 0,
254
247
ptr, NULL, strresult, sizeof(strresult));
249
errmsg = krb5_get_error_message(context, ret);
256
251
/* zap the password */
257
252
memset(clear.data, 0, clear.length);
258
253
memset(ptr, 0, clear.length);
259
krb5_xfree(clear.data);
261
256
clear.length = 0;
263
258
clen = strlen(clientstr);
264
259
trunc_name(&clen, &cdots);
265
krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %.*s%s: %s",
266
inet_ntoa(((struct sockaddr_in *)&remote_addr)->sin_addr),
267
clen, clientstr, cdots,
268
ret ? krb5_get_error_message (context, ret) : "success");
269
krb5_free_unparsed_name(context, clientstr);
272
if ((ret != KADM5_PASS_Q_TOOSHORT) &&
273
(ret != KADM5_PASS_REUSE) && (ret != KADM5_PASS_Q_CLASS) &&
274
(ret != KADM5_PASS_Q_DICT) && (ret != KADM5_PASS_TOOSOON))
275
numresult = KRB5_KPASSWD_HARDERROR;
277
numresult = KRB5_KPASSWD_SOFTERROR;
278
/* strresult set by kadb5_chpass_principal_util() */
284
numresult = KRB5_KPASSWD_SUCCESS;
285
strcpy(strresult, "");
261
switch (addr->addrtype) {
262
case ADDRTYPE_INET: {
263
struct sockaddr_in *sin = ss2sin(&ss);
265
sin->sin_family = AF_INET;
266
memcpy(&sin->sin_addr, addr->contents, addr->length);
267
sin->sin_port = htons(remote_faddr->port);
268
salen = sizeof(*sin);
271
case ADDRTYPE_INET6: {
272
struct sockaddr_in6 *sin6 = ss2sin6(&ss);
274
sin6->sin6_family = AF_INET6;
275
memcpy(&sin6->sin6_addr, addr->contents, addr->length);
276
sin6->sin6_port = htons(remote_faddr->port);
277
salen = sizeof(*sin6);
281
struct sockaddr *sa = ss2sa(&ss);
283
sa->sa_family = AF_UNSPEC;
289
if (getnameinfo(ss2sa(&ss), salen,
290
addrbuf, sizeof(addrbuf), NULL, 0,
291
NI_NUMERICHOST | NI_NUMERICSERV) != 0)
292
strlcpy(addrbuf, "<unprintable>", sizeof(addrbuf));
294
if (vno == RFC3244_VERSION) {
299
if (target == NULL) {
304
tlen = strlen(targetstr);
305
trunc_name(&tlen, &tdots);
309
krb5_klog_syslog(LOG_NOTICE, "setpw request from %s by %.*s%s for %.*s%s: %s",
311
(int) clen, clientstr, cdots,
312
(int) tlen, targetp, tdots,
313
errmsg ? errmsg : "success");
315
krb5_klog_syslog(LOG_NOTICE, "chpw request from %s for %.*s%s: %s",
317
(int) clen, clientstr, cdots,
318
errmsg ? errmsg : "success");
321
case KADM5_AUTH_CHANGEPW:
322
numresult = KRB5_KPASSWD_ACCESSDENIED;
324
case KADM5_PASS_Q_TOOSHORT:
325
case KADM5_PASS_REUSE:
326
case KADM5_PASS_Q_CLASS:
327
case KADM5_PASS_Q_DICT:
328
case KADM5_PASS_TOOSOON:
329
numresult = KRB5_KPASSWD_HARDERROR;
332
numresult = KRB5_KPASSWD_SUCCESS;
333
strlcpy(strresult, "", sizeof(strresult));
336
numresult = KRB5_KPASSWD_SOFTERROR;