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

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