source: trunk/third/moira/incremental/winad/setpw.c @ 24319

Revision 24319, 11.1 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1#define LDAP_AUTH_OTHERKIND             0x86L
2#define LDAP_AUTH_NEGOTIATE             (LDAP_AUTH_OTHERKIND | 0x0400)
3/*--
4
5THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
6ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
7TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
8PARTICULAR PURPOSE.
9
10Copyright (C) 1999  Microsoft Corporation.  All rights reserved.
11
12Module Name:
13
14    setpw.c
15
16Abstract:
17
18    Set a user's password using the
19    Kerberos Change Password Protocol (I-D) variant for Windows 2000
20
21--*/
22/*
23 * lib/krb5/os/changepw.c
24 *
25 * Copyright 1990 by the Massachusetts Institute of Technology.
26 * All Rights Reserved.
27 *
28 * Export of this software from the United States of America may
29 *   require a specific license from the United States Government.
30 *   It is the responsibility of any person or organization contemplating
31 *   export to obtain such a license before exporting.
32 *
33 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
34 * distribute this software and its documentation for any purpose and
35 * without fee is hereby granted, provided that the above copyright
36 * notice appear in all copies and that both that copyright notice and
37 * this permission notice appear in supporting documentation, and that
38 * the name of M.I.T. not be used in advertising or publicity pertaining
39 * to distribution of the software without specific, written prior
40 * permission.  M.I.T. makes no representations about the suitability of
41 * this software for any purpose.  It is provided "as is" without express
42 * or implied warranty.
43 *
44 */
45
46
47#define NEED_SOCKETS
48#include <krb5.h>
49#include <krb.h>
50#include <stdio.h>
51#include <sys/timeb.h>
52#include <string.h>
53#include <stdlib.h>
54#include <ldap.h>
55
56#ifdef _WIN32
57#include <wshelper.h>
58#include "k5-int.h"
59#else
60#include <sys/socket.h>
61#include <netdb.h>
62#include <sys/select.h>
63#endif
64
65krb5_context        context;
66krb5_ccache         ccache;
67char                *admin_server;
68
69#define SOCKET          int
70#define INVALID_SOCKET  ((SOCKET)~0)
71#define SOCKET_ERROR    (-1)
72
73#define PW_LENGTH 255
74#define KDC_PORT  464
75#define ULONG     unsigned long
76
77#ifndef krb5_is_krb_error
78#define krb5_is_krb_error(dat)\
79            ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
80            (dat)->data[0] == 0x5e))
81#endif
82
83#ifdef _WIN32
84extern krb5_error_code decode_krb5_error
85        (const krb5_data *output, krb5_error **rep);
86#define sleep(Seconds) Sleep(Seconds * 1000)
87#define gethostbyname(Server) rgethostbyname(Server)
88#endif
89
90/* Win32 defines. */
91#if defined(_WIN32) && !defined(__CYGWIN32__)
92#ifndef ECONNABORTED
93#define ECONNABORTED WSAECONNABORTED
94#endif
95#ifndef ECONNREFUSED
96#define ECONNREFUSED WSAECONNREFUSED
97#endif
98#ifndef EHOSTUNREACH
99#define EHOSTUNREACH WSAEHOSTUNREACH
100#endif
101#endif /* _WIN32 && !__CYGWIN32__ */
102
103static const char rcsid[] = "$Id: setpw.c 3956 2010-01-05 20:56:56Z zacheiss $";
104
105static int frequency[26][26] =
106{ {4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, 167, 2, 14, 0, 83, 76,
107127, 7, 25, 8, 1, 9, 1}, /* aa - az */
108   {13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0, 11, 0, 0, 15, 4, 2, 13, 0,
1090, 0, 15, 0}, /* ba - bz */
110   {32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, 0, 50, 3, 0, 10, 0, 28, 11,
1110, 0, 0, 3, 0}, /* ca - cz */
112   {40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, 6, 16, 4, 0, 21, 18, 53,
11319, 5, 15, 0, 3, 0}, /* da - dz */
114   {84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, 55, 54, 146, 35, 37, 6, 191,
115149, 65, 9, 26, 21, 12, 5, 0}, /* ea - ez */
116   {19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, 0, 51, 0, 0, 26, 8, 47, 6,
1173, 3, 0, 2, 0}, /* fa - fz */
118   {20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, 4, 21, 1, 1, 20, 9, 21, 9,
1190, 5, 0, 1, 0}, /* ga - gz */
120   {101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, 2, 44, 1, 0, 3, 10, 18, 6,
1210, 5, 0, 3, 0}, /* ha - hz */
122   {40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, 25, 202, 56, 12, 1, 46, 79,
123117, 1, 22, 0, 4, 0, 3}, /* ia - iz */
124   {3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0,
1250, 0}, /* ja - jz */
126   {1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2, 0, 0, 0, 0, 6, 2, 1, 0, 2,
1270, 1, 0}, /* ka - kz */
128   {44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, 2, 25, 1, 1, 2, 16, 23, 9,
1290, 1, 0, 33, 0}, /* la - lz */
130   {52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, 1, 17, 18, 1, 2, 12, 3, 8,
1310, 1, 0, 2, 0}, /* ma - mz */
132   {42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, 6, 9, 7, 54, 7, 1, 7, 44,
133124, 6, 1, 15, 0, 12, 0}, /* na - nz */
134   {7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, 41, 134, 13, 23, 0, 91, 23,
13542, 55, 16, 28, 0, 4, 1}, /* oa - oz */
136   {19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0, 27, 9, 0, 33, 14, 7, 6, 0,
1370, 0, 0, 0}, /* pa - pz */
138   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0,
1390, 0, 0}, /* qa - qz */
140   {83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, 16, 60, 4, 0, 24, 37,
14155, 6, 11, 4, 0, 28, 0}, /* ra - rz */
142   {65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, 11, 12, 56, 17, 6, 9, 48,
143116, 35, 1, 28, 0, 4, 0}, /* sa - sz */
144   {57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, 10, 6, 79, 7, 0, 49, 50,
14556, 21, 2, 27, 0, 24, 0}, /* ta - tz */
146   {11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31, 1, 15, 0, 47, 39, 31, 0,
1473, 0, 0, 0, 0}, /* ua - uz */
148   {7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
1490, 3, 0}, /* va - vz */
150   {36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, 8, 15, 0, 0, 0, 4, 2, 0, 0,
1511, 0, 0, 0}, /* wa - wz */
152   {1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 3, 0, 0, 1, 0,
1530, 0}, /* xa - xz */
154   {14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, 5, 17, 3, 0, 4, 16, 30, 0,
1550, 5, 0, 0, 0}, /* ya - yz */
156   {1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1570, 0}}; /* za - zz */
158
159/*
160 * This MUST be equal to the sum of the equivalent rows above.
161 */
162
163static int row_sums[26] =
164{796,160,284,401,1276,262,199,539,777, 
165  16,39,351,243,751,662,181,17,683,     
166  662,968,248,115,180,17,162,5};
167
168/*
169 * Frequencies of starting characters
170 */
171
172static int start_freq [26] =
173{1299,425,725,271,375,470,93,223,1009,
174 24,20,355,379,319,823,618,21,317,
175 962,1991,271,104,516,6,16,14};
176
177/*
178 * This MUST be equal to the sum of all elements in the above array.
179 */
180
181static int total_sum = 11646;
182
183int compare_elements(const void *arg1, const void *arg2);
184int set_password(char *user, char *password, char *domain, char *msg);
185
186int locate_ldap_server(char *domain, char **server_name);
187
188long myrandom();
189void generate_password(char *password);
190extern LDAP* ldap_handle;
191char DomainOu[256];
192
193#ifdef WIN32
194krb5_error_code encode_krb5_setpw
195        PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
196#endif
197
198krb5_error_code kdc_set_password(krb5_context context, krb5_ccache ccache,
199                                 char *newpw, char *user, char *domain,
200                                 int *result_code, char *admin_server)
201{
202  krb5_data         chpw_snd;
203  krb5_data         chpw_rcv;
204  krb5_data         result_string;
205  krb5_data         result_code_string;
206  krb5_address      local_kaddr;
207  krb5_address      remote_kaddr;
208  char              userrealm[256];
209  char              temp[256];
210  krb5_error_code   code;
211  struct sockaddr   local_addr;
212  struct sockaddr   remote_addr;
213  int               i;
214  int               addrlen;
215  int               cc;
216  int               local_result_code;
217  int               nfds;
218  krb5_principal    targprinc;
219  struct timeval    TimeVal;
220  fd_set            readfds;
221  krb5_creds        *credsp = NULL;
222  struct hostent    *hp;
223  SOCKET            kdc_socket;
224  struct sockaddr_in  kdc_server;
225  krb5_auth_context   auth_context = NULL;
226  krb5_creds          creds;
227  krb5_data           ap_req;
228  char                *code_string;
229
230  memset(&local_addr, 0, sizeof(local_addr));
231  memset(&local_kaddr, 0, sizeof(local_kaddr));
232  memset(&result_string, 0, sizeof(result_string));
233  memset(&remote_kaddr, 0, sizeof(remote_kaddr));
234  memset(&chpw_snd, 0, sizeof(krb5_data));
235  memset(&chpw_rcv, 0, sizeof(krb5_data));
236  memset(userrealm, '\0', sizeof(userrealm));
237  targprinc = NULL;
238
239  chpw_rcv.length = 1500;
240  chpw_rcv.data = (char *) malloc(chpw_rcv.length);
241
242  for (i = 0; i < (int)strlen(domain); i++)
243    userrealm[i] = toupper(domain[i]);
244
245  sprintf(temp, "%s@%s", user, userrealm);
246  krb5_parse_name(context, temp, &targprinc);
247 
248  if (credsp == NULL)
249    {
250      memset(&creds, 0, sizeof(creds));
251      memset(&ap_req, 0, sizeof(krb5_data));
252      memset(&result_string, 0, sizeof(krb5_data));
253      memset(&result_code_string, 0, sizeof(krb5_data));
254      sprintf(temp, "%s@%s", "kadmin/changepw", userrealm);
255
256      if(code = krb5_init_context(&context))
257        goto cleanup;
258     
259      if(code = krb5_cc_default(context, &ccache))
260        goto cleanup;
261
262      if (krb5_parse_name(context, temp, &creds.server))
263        goto cleanup;
264
265      if (krb5_cc_get_principal(context, ccache, &creds.client))
266        goto cleanup;
267
268      if (krb5_get_credentials(context, 0, ccache, &creds, &credsp))
269        goto cleanup;
270    }
271
272  if ((code = krb5_change_set_password(context, credsp, newpw,
273                                       targprinc, &result_code,
274                                       &result_code_string,
275                                       &result_string))) {
276
277    goto cleanup;
278  }
279
280
281cleanup:
282  if (targprinc != NULL)
283    krb5_free_principal(context, targprinc);
284  return(code);
285}
286
287int set_password(char *user, char *password, char *domain, char *msg)
288{
289  int             res_code;
290  krb5_error_code retval;
291  char            pw[PW_LENGTH+1];
292  int newpasswd = 0;
293
294  memset(pw, '\0', sizeof(pw));
295  if (strlen(password) != 0)
296    {
297      strcpy(pw, password);
298      newpasswd = 1;
299    }
300  else
301    {
302      generate_password(pw);
303      newpasswd = 0;
304    }
305  res_code = 0;
306
307  retval = kdc_set_password(context, ccache, pw, user, domain, &res_code,
308                            admin_server);
309
310  if (res_code)
311    return(res_code);
312
313  return(retval);
314}
315
316void generate_password(char *password)
317{
318  int   i;
319  int   j;
320  int   row_position;
321  int   nchars;
322  int   position;
323  int   word;
324  int   line;
325  char  *pwp;
326
327  for (line = 22; line; --line)
328    {
329      for (word = 7; word; --word)
330        {
331          position = myrandom()%total_sum;
332          for(row_position = 0, j = 0; position >= row_position; row_position += start_freq[j], j++)
333            continue;
334          *(pwp = password) = j + 'a' - 1;
335          for (nchars = PW_LENGTH-1; nchars; --nchars)
336            {
337              i = *pwp - 'a';
338              pwp++;
339              position = myrandom()%row_sums[i];
340              for (row_position = 0, j = 0; position >= row_position; row_position += frequency[i][j], j++)
341                continue;
342              *pwp = j + 'a' - 1;
343            }
344          *(++pwp)='\0';
345          return;
346        }
347      putchar('\n');
348    }
349}
350
351long myrandom()
352{
353  static int init = 0;
354  int pid;
355#ifdef _WIN32
356  struct _timeb timebuffer;
357#else
358  struct timeval tv;
359#endif
360
361  if (!init)
362    {
363      init = 1;
364      pid = getpid();
365#ifdef _WIN32
366      _ftime(&timebuffer);
367      srand(timebuffer.time ^ timebuffer.millitm ^ pid);
368#else
369      gettimeofday(&tv, (struct timezone *) NULL);
370      srandom(tv.tv_sec ^ tv.tv_usec ^ pid);
371#endif
372    }
373  return (rand());
374}
375
376int compare_elements(const void *arg1, const void *arg2)
377{
378  int rc;
379
380  rc = strcmp((char*)arg1, (char*)arg2);
381  if (rc < 0)
382    return(1);
383  if (rc > 0)
384    return(-1);
385  return(rc);
386}
Note: See TracBrowser for help on using the repository browser.