]> andersk Git - moira.git/blame - incremental/winad/setpw.c
Convert full name to a reasonable format.
[moira.git] / incremental / winad / setpw.c
CommitLineData
cd9e6b16 1/*--
2
3THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
4ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
6PARTICULAR PURPOSE.
7
8Copyright (C) 1999 Microsoft Corporation. All rights reserved.
9
10Module Name:
11
12 ksetpw.c
13
14Abstract:
15
16 Set a user's password using the
17 Kerberos Change Password Protocol (I-D) variant for Windows 2000
18
19--*/
20/*
21 * lib/krb5/os/changepw.c
22 *
23 * Copyright 1990 by the Massachusetts Institute of Technology.
24 * All Rights Reserved.
25 *
26 * Export of this software from the United States of America may
27 * require a specific license from the United States Government.
28 * It is the responsibility of any person or organization contemplating
29 * export to obtain such a license before exporting.
30 *
31 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
32 * distribute this software and its documentation for any purpose and
33 * without fee is hereby granted, provided that the above copyright
34 * notice appear in all copies and that both that copyright notice and
35 * this permission notice appear in supporting documentation, and that
36 * the name of M.I.T. not be used in advertising or publicity pertaining
37 * to distribution of the software without specific, written prior
38 * permission. M.I.T. makes no representations about the suitability of
39 * this software for any purpose. It is provided "as is" without express
40 * or implied warranty.
41 *
42 */
43
44#define NEED_SOCKETS
45#include <krb5.h>
46#include <krb.h>
47#ifdef _WIN32
48#include "k5-int.h"
49#include "adm_err.h"
50#include "krb5_err.h"
51#endif
52#include <auth_con.h>
53#include "kpasswd.h"
54
55#ifndef _WIN32
56#include <sys/socket.h>
57#include <netdb.h>
58#include <sys/select.h>
59#endif
60
61#include <stdio.h>
62#include <stdlib.h>
63#include <time.h>
64#include <sys/timeb.h>
65#include <errno.h>
66
67
68#define PW_LENGTH 25
69
70#ifndef krb5_is_krb_error
71#define krb5_is_krb_error(dat)\
72 ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
73 (dat)->data[0] == 0x5e))
74#endif
75
76/* Win32 defines. */
77#if defined(_WIN32) && !defined(__CYGWIN32__)
78#ifndef ECONNABORTED
79#define ECONNABORTED WSAECONNABORTED
80#endif
81#ifndef ECONNREFUSED
82#define ECONNREFUSED WSAECONNREFUSED
83#endif
84#ifndef EHOSTUNREACH
85#define EHOSTUNREACH WSAEHOSTUNREACH
86#endif
87#endif /* _WIN32 && !__CYGWIN32__ */
88
89static const char rcsid[] = "$Id$";
90
91static int frequency[26][26] =
92{ {4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, 167, 2, 14, 0, 83, 76,
93127, 7, 25, 8, 1, 9, 1}, /* aa - az */
94 {13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0, 11, 0, 0, 15, 4, 2, 13, 0,
950, 0, 15, 0}, /* ba - bz */
96 {32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, 0, 50, 3, 0, 10, 0, 28, 11,
970, 0, 0, 3, 0}, /* ca - cz */
98 {40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, 6, 16, 4, 0, 21, 18, 53,
9919, 5, 15, 0, 3, 0}, /* da - dz */
100 {84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, 55, 54, 146, 35, 37, 6, 191,
101149, 65, 9, 26, 21, 12, 5, 0}, /* ea - ez */
102 {19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, 0, 51, 0, 0, 26, 8, 47, 6,
1033, 3, 0, 2, 0}, /* fa - fz */
104 {20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, 4, 21, 1, 1, 20, 9, 21, 9,
1050, 5, 0, 1, 0}, /* ga - gz */
106 {101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, 2, 44, 1, 0, 3, 10, 18, 6,
1070, 5, 0, 3, 0}, /* ha - hz */
108 {40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, 25, 202, 56, 12, 1, 46, 79,
109117, 1, 22, 0, 4, 0, 3}, /* ia - iz */
110 {3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0,
1110, 0}, /* ja - jz */
112 {1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2, 0, 0, 0, 0, 6, 2, 1, 0, 2,
1130, 1, 0}, /* ka - kz */
114 {44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, 2, 25, 1, 1, 2, 16, 23, 9,
1150, 1, 0, 33, 0}, /* la - lz */
116 {52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, 1, 17, 18, 1, 2, 12, 3, 8,
1170, 1, 0, 2, 0}, /* ma - mz */
118 {42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, 6, 9, 7, 54, 7, 1, 7, 44,
119124, 6, 1, 15, 0, 12, 0}, /* na - nz */
120 {7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, 41, 134, 13, 23, 0, 91, 23,
12142, 55, 16, 28, 0, 4, 1}, /* oa - oz */
122 {19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0, 27, 9, 0, 33, 14, 7, 6, 0,
1230, 0, 0, 0}, /* pa - pz */
124 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0,
1250, 0, 0}, /* qa - qz */
126 {83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, 16, 60, 4, 0, 24, 37,
12755, 6, 11, 4, 0, 28, 0}, /* ra - rz */
128 {65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, 11, 12, 56, 17, 6, 9, 48,
129116, 35, 1, 28, 0, 4, 0}, /* sa - sz */
130 {57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, 10, 6, 79, 7, 0, 49, 50,
13156, 21, 2, 27, 0, 24, 0}, /* ta - tz */
132 {11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31, 1, 15, 0, 47, 39, 31, 0,
1333, 0, 0, 0, 0}, /* ua - uz */
134 {7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
1350, 3, 0}, /* va - vz */
136 {36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, 8, 15, 0, 0, 0, 4, 2, 0, 0,
1371, 0, 0, 0}, /* wa - wz */
138 {1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 3, 0, 0, 1, 0,
1390, 0}, /* xa - xz */
140 {14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, 5, 17, 3, 0, 4, 16, 30, 0,
1410, 5, 0, 0, 0}, /* ya - yz */
142 {1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1430, 0}}; /* za - zz */
144
145/*
146 * This MUST be equal to the sum of the equivalent rows above.
147 */
148
149static int row_sums[26] =
150{796, 160, 284, 401, 1276, 262, 199, 539, 777,
151 16, 39, 351, 243, 751, 662, 181, 17, 683,
152 662, 968, 248, 115, 180, 17, 162, 5};
153
154/*
155 * Frequencies of starting characters
156 */
157
158static int start_freq [26] =
159{1299, 425, 725, 271, 375, 470, 93, 223, 1009,
160 24, 20, 355, 379, 319, 823, 618, 21, 317,
161 962, 1991, 271, 104, 516, 6, 16, 14};
162
163/*
164 * This MUST be equal to the sum of all elements in the above array.
165 */
166static int total_sum = 11646;
167
168long myrandom();
169void generate_password(char *password);
170int set_password(char *user, char *domain);
171krb5_error_code encode_krb5_setpw
172 PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
173krb5_error_code
174krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
175 struct sockaddr **addr_pp, int *naddrs);
176
177krb5_error_code krb5_mk_setpw_req(krb5_context context, krb5_auth_context auth_context,
178 krb5_data *ap_req, krb5_principal targprinc,
179 char *passwd, krb5_data *packet)
180{
181 krb5_error_code ret;
182 krb5_setpw setpw;
183 krb5_data cipherpw;
184 krb5_data *encoded_setpw;
185 krb5_replay_data replay;
186 char *ptr;
187 register int count = 2;
188
189 memset (&setpw, 0, sizeof(krb5_setpw));
190 if (ret = krb5_auth_con_setflags(context, auth_context,
191 KRB5_AUTH_CONTEXT_DO_SEQUENCE))
192 return(ret);
193 setpw.targprinc = targprinc;
194 setpw.newpasswd.length = strlen(passwd);
195 setpw.newpasswd.data = passwd;
196 if ((ret = encode_krb5_setpw(&setpw, &encoded_setpw)))
197 return( ret );
198 if (ret = krb5_mk_priv(context, auth_context,
199 encoded_setpw, &cipherpw, &replay))
200 return(ret);
201 packet->length = 6 + ap_req->length + cipherpw.length;
202 packet->data = (char *) malloc(packet->length);
203 ptr = packet->data;
204 /* Length */
205 *ptr++ = (packet->length>>8) & 0xff;
206 *ptr++ = packet->length & 0xff;
207 /* version */
208 *ptr++ = (char)0xff;
209 *ptr++ = (char)0x80;
210 /* ap_req length, big-endian */
211 *ptr++ = (ap_req->length>>8) & 0xff;
212 *ptr++ = ap_req->length & 0xff;
213 /* ap-req data */
214 memcpy(ptr, ap_req->data, ap_req->length);
215 ptr += ap_req->length;
216 /* krb-priv of password */
217 memcpy(ptr, cipherpw.data, cipherpw.length);
218 return(0);
219}
220
221krb5_error_code krb5_rd_setpw_rep(krb5_context context, krb5_auth_context auth_context,
222 krb5_data *packet, int *result_code,
223 krb5_data *result_data)
224{
225 char *ptr;
226 int plen;
227 int vno;
228 krb5_data ap_rep;
229 krb5_error_code ret;
230 krb5_data cipherresult;
231 krb5_data clearresult;
232 krb5_error *krberror;
233 krb5_replay_data replay;
234 krb5_keyblock *tmp;
235 krb5_ap_rep_enc_part *ap_rep_enc;
236
237 if (packet->length < 4)
238 return(KRB5KRB_AP_ERR_MODIFIED);
239 ptr = packet->data;
240 if (krb5_is_krb_error(packet))
241 {
242 ret = decode_krb5_error(packet, &krberror);
243 if (ret)
244 return(ret);
245 ret = krberror->error;
246 krb5_free_error(context, krberror);
247 return(ret);
248 }
249 /* verify length */
250 plen = (*ptr++ & 0xff);
251 plen = (plen<<8) | (*ptr++ & 0xff);
252 if (plen != packet->length)
253 return(KRB5KRB_AP_ERR_MODIFIED);
254 vno = (*ptr++ & 0xff);
255 vno = (vno<<8) | (*ptr++ & 0xff);
256 if (vno != KRB5_KPASSWD_VERS_SETPW && vno != KRB5_KPASSWD_VERS_CHANGEPW)
257 return(KRB5KDC_ERR_BAD_PVNO);
258 /* read, check ap-rep length */
259 ap_rep.length = (*ptr++ & 0xff);
260 ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
261 if (ptr + ap_rep.length >= packet->data + packet->length)
262 return(KRB5KRB_AP_ERR_MODIFIED);
263 if (ap_rep.length)
264 {
265 /* verify ap_rep */
266 ap_rep.data = ptr;
267 ptr += ap_rep.length;
268 if (ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc))
269 return(ret);
270 krb5_free_ap_rep_enc_part(context, ap_rep_enc);
271 /* extract and decrypt the result */
272 cipherresult.data = ptr;
273 cipherresult.length = (packet->data + packet->length) - ptr;
274 /* XXX there's no api to do this right. The problem is that
275 if there's a remote subkey, it will be used. This is
276 not what the spec requires */
277 tmp = auth_context->remote_subkey;
278 auth_context->remote_subkey = NULL;
279 ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
280 &replay);
281 auth_context->remote_subkey = tmp;
282 if (ret)
283 return(ret);
284 }
285 else
286 {
287 cipherresult.data = ptr;
288 cipherresult.length = (packet->data + packet->length) - ptr;
289
290 if (ret = krb5_rd_error(context, &cipherresult, &krberror))
291 return(ret);
292
293 clearresult = krberror->e_data;
294 }
295 if (clearresult.length < 2)
296 {
297 ret = KRB5KRB_AP_ERR_MODIFIED;
298 goto cleanup;
299 }
300 ptr = clearresult.data;
301 *result_code = (*ptr++ & 0xff);
302 *result_code = (*result_code<<8) | (*ptr++ & 0xff);
303 if ((*result_code < KRB5_KPASSWD_SUCCESS) ||
304 (*result_code > KRB5_KPASSWD_ACCESSDENIED))
305 {
306 ret = KRB5KRB_AP_ERR_MODIFIED;
307 goto cleanup;
308 }
309 /* all success replies should be authenticated/encrypted */
310 if ((ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS))
311 {
312 ret = KRB5KRB_AP_ERR_MODIFIED;
313 goto cleanup;
314 }
315 result_data->length = (clearresult.data + clearresult.length) - ptr;
316 if (result_data->length)
317 {
318 result_data->data = (char *) malloc(result_data->length);
319 memcpy(result_data->data, ptr, result_data->length);
320 }
321 else
322 result_data->data = NULL;
323 ret = 0;
324cleanup:
325 if (ap_rep.length)
326 free(clearresult.data);
327 else
328 krb5_free_error(context, krberror);
329 return(ret);
330}
331
332krb5_error_code krb5_set_password(krb5_context context, krb5_ccache ccache,
333 char *newpw, char *user, char *domain,
334 int *result_code)
335{
336 krb5_auth_context auth_context;
337 krb5_data ap_req;
338 krb5_data chpw_req;
339 krb5_data chpw_rep;
340 krb5_data result_string;
341 krb5_address local_kaddr;
342 krb5_address remote_kaddr;
343 char userrealm[256];
344 char temp[256];
345 krb5_error_code code;
346 krb5_creds creds;
347 krb5_creds *credsp;
348 struct sockaddr *addr_p;
349 struct sockaddr local_addr;
350 struct sockaddr remote_addr;
351 struct sockaddr tmp_addr;
352 SOCKET s1;
353 SOCKET s2;
354 int i;
355 int out;
356 int addrlen;
357 int cc;
358 int local_result_code;
359 int tmp_len;
360 int error_count;
361 krb5_principal targprinc;
362 struct timeval TimeVal;
363 fd_set readfds;
364
365 auth_context = NULL;
366 addr_p = NULL;
367 credsp = NULL;
368 memset(&local_addr, 0, sizeof(local_addr));
369 memset(&local_kaddr, 0, sizeof(local_kaddr));
370 memset(&result_string, 0, sizeof(result_string));
371 memset(&remote_kaddr, 0, sizeof(remote_kaddr));
372 memset(&chpw_req, 0, sizeof(krb5_data));
373 memset(&chpw_rep, 0, sizeof(krb5_data));
374 memset(&ap_req, 0, sizeof(krb5_data));
375 auth_context = NULL;
376 memset(&creds, 0, sizeof(creds));
377 memset(userrealm, '\0', sizeof(userrealm));
378 targprinc = NULL;
379 for (i = 0; i < (int)strlen(domain); i++)
380 userrealm[i] = toupper(domain[i]);
381
382 sprintf(temp, "%s@%s", user, userrealm);
383 krb5_parse_name(context, temp, &targprinc);
384
385 sprintf(temp, "%s@%s", "kadmin/changepw", userrealm);
386 if (code = krb5_parse_name(context, temp, &creds.server))
387 goto cleanup;
388
389 if (code = krb5_cc_get_principal(context, ccache, &creds.client))
390 goto cleanup;
391 if (code = krb5_get_credentials(context, 0, ccache, &creds, &credsp))
392 goto cleanup;
393 if (code = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
394 NULL, credsp, &ap_req))
395 goto cleanup;
396 if (code = krb5_locate_kpasswd(context, &targprinc->realm, &addr_p, &out))
397 goto cleanup;
398 if (out == 0)
399 { /* Couldn't resolve any KPASSWD names */
400 code = 1;
401 goto cleanup;
402 }
403
404 /* this is really obscure. s1 is used for all communications. it
405 is left unconnected in case the server is multihomed and routes
406 are asymmetric. s2 is connected to resolve routes and get
407 addresses. this is the *only* way to get proper addresses for
408 multihomed hosts if routing is asymmetric.
409
410 A related problem in the server, but not the client, is that
411 many os's have no way to disconnect a connected udp socket, so
412 the s2 socket needs to be closed and recreated for each
413 request. The s1 socket must not be closed, or else queued
414 requests will be lost.
415
416 A "naive" client implementation (one socket, no connect,
417 hostname resolution to get the local ip addr) will work and
418 interoperate if the client is single-homed. */
419
420 if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
421 {
422 free(addr_p);
423 return(errno);
424 }
425 if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
426 {
427 closesocket(s1);
428 free(addr_p);
429 return(errno);
430 }
431 error_count = 0;
432 for (i=0; i<out; i++)
433 {
434 if (connect(s2, &addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR)
435 continue;
436
437 addrlen = sizeof(local_addr);
438 if (getsockname(s2, &local_addr, &addrlen) < 0)
439 continue;
440 if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0)
441 {
442 local_kaddr.addrtype = ADDRTYPE_INET;
443 local_kaddr.length =
444 sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
445 local_kaddr.contents =
446 (char *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
447 }
448 else
449 {
450 krb5_address **addrs;
451 krb5_os_localaddr(context, &addrs);
452 local_kaddr.magic = addrs[0]->magic;
453 local_kaddr.addrtype = addrs[0]->addrtype;
454 local_kaddr.length = addrs[0]->length;
455 local_kaddr.contents = calloc(1, addrs[0]->length);
456 memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
457 krb5_free_addresses(context, addrs);
458 }
459
460 addrlen = sizeof(remote_addr);
461 if (getpeername(s2, &remote_addr, &addrlen) < 0)
462 continue;
463 remote_kaddr.addrtype = ADDRTYPE_INET;
464 remote_kaddr.length =
465 sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
466 remote_kaddr.contents =
467 (char *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
468 /* mk_priv requires that the local address be set.
469 getsockname is used for this. rd_priv requires that the
470 remote address be set. recvfrom is used for this. If
471 rd_priv is given a local address, and the message has the
472 recipient addr in it, this will be checked. However, there
473 is simply no way to know ahead of time what address the
474 message will be delivered *to*. Therefore, it is important
475 that either no recipient address is in the messages when
476 mk_priv is called, or that no local address is passed to
477 rd_priv. Both is a better idea, and I have done that. In
478 summary, when mk_priv is called, *only* a local address is
479 specified. when rd_priv is called, *only* a remote address
480 is specified. Are we having fun yet? */
481 if (code = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL))
482 goto cleanup;
483 if (code = krb5_mk_setpw_req(context, auth_context, &ap_req,
484 targprinc, newpw, &chpw_req))
485 goto cleanup;
486 if ((cc = sendto(s1, chpw_req.data, chpw_req.length, 0,
487 (struct sockaddr *) &addr_p[i],
488 sizeof(addr_p[i]))) != chpw_req.length)
489 continue; /* try the next addr */
490#ifdef _WIN32
491 krb5_free_data_contents(context, &chpw_req);
492#else
493 free(chpw_req.data);
494#endif
495 chpw_rep.length = 1500;
496 chpw_rep.data = (char *) calloc(1, chpw_rep.length);
497 /* XXX need a timeout/retry loop here */
498 /* "recv" would be good enough here... except that Windows/NT
499 commits the atrocity of returning -1 to indicate failure,
500 but leaving errno set to 0.
501
502 "recvfrom(...,NULL,NULL)" would seem to be a good enough
503 alternative, and it works on NT, but it doesn't work on
504 SunOS 4.1.4 or Irix 5.3. Thus we must actually accept the
505 value and discard it. */
506 tmp_len = sizeof(tmp_addr);
507 TimeVal.tv_sec = 10;
508 TimeVal.tv_usec = 0;
509
510 FD_ZERO(&readfds);
511 FD_SET(s1, &readfds);
512 code = select(1, &readfds, NULL, NULL, &TimeVal);
513
514 if ((code == 0) || (code == SOCKET_ERROR))
515 {
516 if (error_count < 2)
517 {
518 closesocket(s1);
519 closesocket(s2);
520 if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
521 goto cleanup;
522 if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
523 goto cleanup;
524 ++error_count;
525 --i;
526 continue;
527 }
528 code = errno;
529 goto cleanup;
530 }
531 if ((cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, 0, &tmp_addr, &tmp_len)) < 0)
532 {
533 code = errno;
534 goto cleanup;
535 }
536 chpw_rep.length = cc;
537 if (code = krb5_auth_con_setaddrs(context, auth_context, NULL,
538 &remote_kaddr))
539 {
540 goto cleanup;
541 }
542 local_result_code = 0;
543 code = krb5_rd_setpw_rep(context, auth_context, &chpw_rep,
544 &local_result_code, &result_string);
545
546 if (result_code)
547 *result_code = local_result_code;
548#ifdef _WIN32
549 krb5_free_data_contents(context, &chpw_req);
550#else
551 free(chpw_req.data);
552#endif
553 break;
554
555 }
556cleanup:
557 closesocket(s1);
558 closesocket(s2);
559 if (addr_p != NULL)
560 free(addr_p);
561 if (auth_context != NULL)
562 krb5_auth_con_free(context, auth_context);
563 if (ap_req.data != NULL)
564#ifdef _WIN32
565 krb5_free_data_contents(context, &ap_req);
566#else
567 free(ap_req.data);
568#endif
569 krb5_free_cred_contents(context, &creds);
570 if (credsp != NULL)
571 krb5_free_creds(context, credsp);
572 if (targprinc != NULL)
573 krb5_free_principal(context, targprinc);
574 return(code);
575}
576
577int set_password(char *user, char *domain)
578{
579 krb5_context context;
580 krb5_ccache ccache;
581 int res_code;
582 krb5_error_code retval;
583 char pw[PW_LENGTH+1];
584
585 if (retval = krb5_init_context(&context))
586 return retval;
587 if (retval = krb5_cc_default(context, &ccache))
588 return(retval);
589
590 memset(pw, '\0', sizeof(pw));
591 generate_password(pw);
592 retval = krb5_set_password(context, ccache, pw, user, domain, &res_code);
593
594 krb5_cc_close(context, ccache);
595 krb5_free_context(context);
596 return(retval);
597}
598
599void generate_password(char *password)
600{
601 int i;
602 int j;
603 int row_position;
604 int nchars;
605 int position;
606 int word;
607 int line;
608 char *pwp;
609
610 for (line = 22; line; --line)
611 {
612 for (word = 7; word; --word)
613 {
614 position = myrandom()%total_sum;
615 for(row_position = 0, j = 0; position >= row_position; row_position += start_freq[j], j++)
616 continue;
617 *(pwp = password) = j + 'a' - 1;
618 for (nchars = PW_LENGTH-1; nchars; --nchars)
619 {
620 i = *pwp - 'a';
621 pwp++;
622 position = myrandom()%row_sums[i];
623 for (row_position = 0, j = 0; position >= row_position; row_position += frequency[i][j], j++)
624 continue;
625 *pwp = j + 'a' - 1;
626 }
627 *(++pwp)='\0';
628 return;
629 }
630 putchar('\n');
631 }
632}
633
634long myrandom()
635{
636 static int init = 0;
637 int pid;
638#ifdef _WIN32
639 struct _timeb timebuffer;
640#else
641 struct timeval tv;
642#endif
643
644 if (!init)
645 {
646 init = 1;
647 pid = getpid();
648#ifdef _WIN32
649 _ftime(&timebuffer);
650 srand(timebuffer.time ^ timebuffer.millitm ^ pid);
651#else
652 gettimeofday(&tv, (struct timezone *) NULL);
653 srandom(tv.tv_sec ^ tv.tv_usec ^ pid);
654#endif
655 }
656 return (rand());
657}
This page took 0.127815 seconds and 5 git commands to generate.