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

Revision 25817, 11.0 KB checked in by jdreed, 11 years ago (diff)
In moira: * Re-snapshot moira at r4097 to pick up Status 10 (Suspended) (Trac: #1295) * Remove our addusr.1 and namespace.1 in favor of upstreams (Trac: #918) * Build-dep on OpenSSL and pass new configure flag per moira r4091
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 <stdio.h>
50#include <sys/timeb.h>
51#include <string.h>
52#include <stdlib.h>
53#include <ldap.h>
54
55#ifdef _WIN32
56#include <wshelper.h>
57#include "k5-int.h"
58#else
59#include <sys/socket.h>
60#include <netdb.h>
61#include <sys/select.h>
62#endif
63
64krb5_context        context;
65krb5_ccache         ccache;
66char                *admin_server;
67
68#define SOCKET          int
69#define INVALID_SOCKET  ((SOCKET)~0)
70#define SOCKET_ERROR    (-1)
71
72#define PW_LENGTH 255
73#define KDC_PORT  464
74#define ULONG     unsigned long
75
76#ifndef krb5_is_krb_error
77#define krb5_is_krb_error(dat)\
78            ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
79            (dat)->data[0] == 0x5e))
80#endif
81
82#ifdef _WIN32
83extern krb5_error_code decode_krb5_error
84        (const krb5_data *output, krb5_error **rep);
85#define sleep(Seconds) Sleep(Seconds * 1000)
86#define gethostbyname(Server) rgethostbyname(Server)
87#endif
88
89/* Win32 defines. */
90#if defined(_WIN32) && !defined(__CYGWIN32__)
91#ifndef ECONNABORTED
92#define ECONNABORTED WSAECONNABORTED
93#endif
94#ifndef ECONNREFUSED
95#define ECONNREFUSED WSAECONNREFUSED
96#endif
97#ifndef EHOSTUNREACH
98#define EHOSTUNREACH WSAEHOSTUNREACH
99#endif
100#endif /* _WIN32 && !__CYGWIN32__ */
101
102static const char rcsid[] = "$Id: setpw.c 4092 2013-01-18 15:36:33Z zacheiss $";
103
104static int frequency[26][26] =
105{ {4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, 167, 2, 14, 0, 83, 76,
106127, 7, 25, 8, 1, 9, 1}, /* aa - az */
107   {13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0, 11, 0, 0, 15, 4, 2, 13, 0,
1080, 0, 15, 0}, /* ba - bz */
109   {32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, 0, 50, 3, 0, 10, 0, 28, 11,
1100, 0, 0, 3, 0}, /* ca - cz */
111   {40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, 6, 16, 4, 0, 21, 18, 53,
11219, 5, 15, 0, 3, 0}, /* da - dz */
113   {84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, 55, 54, 146, 35, 37, 6, 191,
114149, 65, 9, 26, 21, 12, 5, 0}, /* ea - ez */
115   {19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, 0, 51, 0, 0, 26, 8, 47, 6,
1163, 3, 0, 2, 0}, /* fa - fz */
117   {20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, 4, 21, 1, 1, 20, 9, 21, 9,
1180, 5, 0, 1, 0}, /* ga - gz */
119   {101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, 2, 44, 1, 0, 3, 10, 18, 6,
1200, 5, 0, 3, 0}, /* ha - hz */
121   {40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, 25, 202, 56, 12, 1, 46, 79,
122117, 1, 22, 0, 4, 0, 3}, /* ia - iz */
123   {3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0,
1240, 0}, /* ja - jz */
125   {1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2, 0, 0, 0, 0, 6, 2, 1, 0, 2,
1260, 1, 0}, /* ka - kz */
127   {44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, 2, 25, 1, 1, 2, 16, 23, 9,
1280, 1, 0, 33, 0}, /* la - lz */
129   {52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, 1, 17, 18, 1, 2, 12, 3, 8,
1300, 1, 0, 2, 0}, /* ma - mz */
131   {42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, 6, 9, 7, 54, 7, 1, 7, 44,
132124, 6, 1, 15, 0, 12, 0}, /* na - nz */
133   {7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, 41, 134, 13, 23, 0, 91, 23,
13442, 55, 16, 28, 0, 4, 1}, /* oa - oz */
135   {19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0, 27, 9, 0, 33, 14, 7, 6, 0,
1360, 0, 0, 0}, /* pa - pz */
137   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0,
1380, 0, 0}, /* qa - qz */
139   {83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, 16, 60, 4, 0, 24, 37,
14055, 6, 11, 4, 0, 28, 0}, /* ra - rz */
141   {65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, 11, 12, 56, 17, 6, 9, 48,
142116, 35, 1, 28, 0, 4, 0}, /* sa - sz */
143   {57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, 10, 6, 79, 7, 0, 49, 50,
14456, 21, 2, 27, 0, 24, 0}, /* ta - tz */
145   {11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31, 1, 15, 0, 47, 39, 31, 0,
1463, 0, 0, 0, 0}, /* ua - uz */
147   {7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
1480, 3, 0}, /* va - vz */
149   {36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, 8, 15, 0, 0, 0, 4, 2, 0, 0,
1501, 0, 0, 0}, /* wa - wz */
151   {1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 3, 0, 0, 1, 0,
1520, 0}, /* xa - xz */
153   {14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, 5, 17, 3, 0, 4, 16, 30, 0,
1540, 5, 0, 0, 0}, /* ya - yz */
155   {1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1560, 0}}; /* za - zz */
157
158/*
159 * This MUST be equal to the sum of the equivalent rows above.
160 */
161
162static int row_sums[26] =
163{796,160,284,401,1276,262,199,539,777, 
164  16,39,351,243,751,662,181,17,683,     
165  662,968,248,115,180,17,162,5};
166
167/*
168 * Frequencies of starting characters
169 */
170
171static int start_freq [26] =
172{1299,425,725,271,375,470,93,223,1009,
173 24,20,355,379,319,823,618,21,317,
174 962,1991,271,104,516,6,16,14};
175
176/*
177 * This MUST be equal to the sum of all elements in the above array.
178 */
179
180static int total_sum = 11646;
181
182int compare_elements(const void *arg1, const void *arg2);
183int set_password(char *user, char *password, char *domain, char *msg);
184
185int locate_ldap_server(char *domain, char **server_name);
186
187long myrandom();
188void generate_password(char *password);
189extern LDAP* ldap_handle;
190char DomainOu[256];
191
192#ifdef WIN32
193krb5_error_code encode_krb5_setpw
194        PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
195#endif
196
197krb5_error_code kdc_set_password(krb5_context context, krb5_ccache ccache,
198                                 char *newpw, char *user, char *domain,
199                                 int *result_code, char *admin_server)
200{
201  krb5_data         chpw_snd;
202  krb5_data         chpw_rcv;
203  krb5_data         result_string;
204  krb5_data         result_code_string;
205  krb5_address      local_kaddr;
206  krb5_address      remote_kaddr;
207  char              userrealm[256];
208  char              temp[256];
209  krb5_error_code   code;
210  struct sockaddr   local_addr;
211  struct sockaddr   remote_addr;
212  int               i;
213  int               addrlen;
214  int               cc;
215  int               local_result_code;
216  int               nfds;
217  krb5_principal    targprinc;
218  struct timeval    TimeVal;
219  fd_set            readfds;
220  krb5_creds        *credsp = NULL;
221  struct hostent    *hp;
222  SOCKET            kdc_socket;
223  struct sockaddr_in  kdc_server;
224  krb5_auth_context   auth_context = NULL;
225  krb5_creds          creds;
226  krb5_data           ap_req;
227  char                *code_string;
228
229  memset(&local_addr, 0, sizeof(local_addr));
230  memset(&local_kaddr, 0, sizeof(local_kaddr));
231  memset(&result_string, 0, sizeof(result_string));
232  memset(&remote_kaddr, 0, sizeof(remote_kaddr));
233  memset(&chpw_snd, 0, sizeof(krb5_data));
234  memset(&chpw_rcv, 0, sizeof(krb5_data));
235  memset(userrealm, '\0', sizeof(userrealm));
236  targprinc = NULL;
237
238  chpw_rcv.length = 1500;
239  chpw_rcv.data = (char *) malloc(chpw_rcv.length);
240
241  for (i = 0; i < (int)strlen(domain); i++)
242    userrealm[i] = toupper(domain[i]);
243
244  sprintf(temp, "%s@%s", user, userrealm);
245  krb5_parse_name(context, temp, &targprinc);
246 
247  if (credsp == NULL)
248    {
249      memset(&creds, 0, sizeof(creds));
250      memset(&ap_req, 0, sizeof(krb5_data));
251      memset(&result_string, 0, sizeof(krb5_data));
252      memset(&result_code_string, 0, sizeof(krb5_data));
253      sprintf(temp, "%s@%s", "kadmin/changepw", userrealm);
254
255      if(code = krb5_init_context(&context))
256        goto cleanup;
257     
258      if(code = krb5_cc_default(context, &ccache))
259        goto cleanup;
260
261      if (krb5_parse_name(context, temp, &creds.server))
262        goto cleanup;
263
264      if (krb5_cc_get_principal(context, ccache, &creds.client))
265        goto cleanup;
266
267      if (krb5_get_credentials(context, 0, ccache, &creds, &credsp))
268        goto cleanup;
269    }
270
271  if ((code = krb5_change_set_password(context, credsp, newpw,
272                                       targprinc, &result_code,
273                                       &result_code_string,
274                                       &result_string))) {
275
276    goto cleanup;
277  }
278
279
280cleanup:
281  if (targprinc != NULL)
282    krb5_free_principal(context, targprinc);
283  return(code);
284}
285
286int set_password(char *user, char *password, char *domain, char *msg)
287{
288  int             res_code;
289  krb5_error_code retval;
290  char            pw[PW_LENGTH+1];
291  int newpasswd = 0;
292
293  memset(pw, '\0', sizeof(pw));
294  if (strlen(password) != 0)
295    {
296      strcpy(pw, password);
297      newpasswd = 1;
298    }
299  else
300    {
301      generate_password(pw);
302      newpasswd = 0;
303    }
304  res_code = 0;
305
306  retval = kdc_set_password(context, ccache, pw, user, domain, &res_code,
307                            admin_server);
308
309  if (res_code)
310    return(res_code);
311
312  return(retval);
313}
314
315void generate_password(char *password)
316{
317  int   i;
318  int   j;
319  int   row_position;
320  int   nchars;
321  int   position;
322  int   word;
323  int   line;
324  char  *pwp;
325
326  for (line = 22; line; --line)
327    {
328      for (word = 7; word; --word)
329        {
330          position = myrandom()%total_sum;
331          for(row_position = 0, j = 0; position >= row_position; row_position += start_freq[j], j++)
332            continue;
333          *(pwp = password) = j + 'a' - 1;
334          for (nchars = PW_LENGTH-1; nchars; --nchars)
335            {
336              i = *pwp - 'a';
337              pwp++;
338              position = myrandom()%row_sums[i];
339              for (row_position = 0, j = 0; position >= row_position; row_position += frequency[i][j], j++)
340                continue;
341              *pwp = j + 'a' - 1;
342            }
343          *(++pwp)='\0';
344          return;
345        }
346      putchar('\n');
347    }
348}
349
350long myrandom()
351{
352  static int init = 0;
353  int pid;
354#ifdef _WIN32
355  struct _timeb timebuffer;
356#else
357  struct timeval tv;
358#endif
359
360  if (!init)
361    {
362      init = 1;
363      pid = getpid();
364#ifdef _WIN32
365      _ftime(&timebuffer);
366      srand(timebuffer.time ^ timebuffer.millitm ^ pid);
367#else
368      gettimeofday(&tv, (struct timezone *) NULL);
369      srandom(tv.tv_sec ^ tv.tv_usec ^ pid);
370#endif
371    }
372  return (rand());
373}
374
375int compare_elements(const void *arg1, const void *arg2)
376{
377  int rc;
378
379  rc = strcmp((char*)arg1, (char*)arg2);
380  if (rc < 0)
381    return(1);
382  if (rc > 0)
383    return(-1);
384  return(rc);
385}
Note: See TracBrowser for help on using the repository browser.