]> andersk Git - moira.git/blob - incremental/winad/setpw.c
From dtanner: updates to Active Directory incremental update program.
[moira.git] / incremental / winad / setpw.c
1 /*--
2
3 THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
4 ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
5 TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
6 PARTICULAR PURPOSE.
7
8 Copyright (C) 1999  Microsoft Corporation.  All rights reserved.
9
10 Module Name:
11
12     ksetpw.c
13
14 Abstract:
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
89 static const char rcsid[] = "$Id$";
90
91 static int frequency[26][26] =
92 { {4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, 167, 2, 14, 0, 83, 76, 
93 127, 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, 
95 0, 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, 
97 0, 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, 
99 19, 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, 
101 149, 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, 
103 3, 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, 
105 0, 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, 
107 0, 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, 
109 117, 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, 
111 0, 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, 
113 0, 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, 
115 0, 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, 
117 0, 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, 
119 124, 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, 
121 42, 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, 
123 0, 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, 
125 0, 0, 0}, /* qa - qz */
126    {83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, 16, 60, 4, 0, 24, 37, 
127 55, 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, 
129 116, 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, 
131 56, 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, 
133 3, 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, 
135 0, 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, 
137 1, 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, 
139 0, 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, 
141 0, 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, 
143 0, 0}}; /* za - zz */
144
145 /*
146  * This MUST be equal to the sum of the equivalent rows above.
147  */
148
149 static 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
158 static 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  */
166 static int total_sum = 11646;
167
168 long myrandom();
169 void generate_password(char *password);
170 int set_password(char *user, char *domain);
171 krb5_error_code encode_krb5_setpw
172         PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
173 krb5_error_code 
174 krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
175                     struct sockaddr **addr_pp, int *naddrs);
176
177 krb5_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
221 krb5_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;
324 cleanup:
325   if (ap_rep.length)
326           free(clearresult.data);
327   else
328           krb5_free_error(context, krberror);
329   return(ret);
330 }
331
332 krb5_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     }
556 cleanup:
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
577 int 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
599 void 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
634 long 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.088047 seconds and 5 git commands to generate.