1 | #define LDAP_AUTH_OTHERKIND 0x86L |
---|
2 | #define LDAP_AUTH_NEGOTIATE (LDAP_AUTH_OTHERKIND | 0x0400) |
---|
3 | /*-- |
---|
4 | |
---|
5 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF |
---|
6 | ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED |
---|
7 | TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A |
---|
8 | PARTICULAR PURPOSE. |
---|
9 | |
---|
10 | Copyright (C) 1999 Microsoft Corporation. All rights reserved. |
---|
11 | |
---|
12 | Module Name: |
---|
13 | |
---|
14 | setpw.c |
---|
15 | |
---|
16 | Abstract: |
---|
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 | |
---|
66 | krb5_context context; |
---|
67 | krb5_ccache ccache; |
---|
68 | char *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 |
---|
85 | extern 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 | |
---|
104 | static const char rcsid[] = "$Id: setpw.c 3956 2010-01-05 20:56:56Z zacheiss $"; |
---|
105 | |
---|
106 | static int frequency[26][26] = |
---|
107 | { {4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, 23, 167, 2, 14, 0, 83, 76, |
---|
108 | 127, 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, |
---|
110 | 0, 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, |
---|
112 | 0, 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, |
---|
114 | 19, 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, |
---|
116 | 149, 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, |
---|
118 | 3, 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, |
---|
120 | 0, 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, |
---|
122 | 0, 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, |
---|
124 | 117, 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, |
---|
126 | 0, 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, |
---|
128 | 0, 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, |
---|
130 | 0, 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, |
---|
132 | 0, 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, |
---|
134 | 124, 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, |
---|
136 | 42, 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, |
---|
138 | 0, 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, |
---|
140 | 0, 0, 0}, /* qa - qz */ |
---|
141 | {83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, 26, 16, 60, 4, 0, 24, 37, |
---|
142 | 55, 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, |
---|
144 | 116, 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, |
---|
146 | 56, 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, |
---|
148 | 3, 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, |
---|
150 | 0, 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, |
---|
152 | 1, 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, |
---|
154 | 0, 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, |
---|
156 | 0, 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, |
---|
158 | 0, 0}}; /* za - zz */ |
---|
159 | |
---|
160 | /* |
---|
161 | * This MUST be equal to the sum of the equivalent rows above. |
---|
162 | */ |
---|
163 | |
---|
164 | static 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 | |
---|
173 | static 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 | |
---|
182 | static int total_sum = 11646; |
---|
183 | |
---|
184 | int compare_elements(const void *arg1, const void *arg2); |
---|
185 | int set_password(char *user, char *password, char *domain, char *msg); |
---|
186 | |
---|
187 | int locate_ldap_server(char *domain, char **server_name); |
---|
188 | |
---|
189 | long myrandom(); |
---|
190 | void generate_password(char *password); |
---|
191 | extern LDAP* ldap_handle; |
---|
192 | char DomainOu[256]; |
---|
193 | |
---|
194 | #ifdef WIN32 |
---|
195 | krb5_error_code encode_krb5_setpw |
---|
196 | PROTOTYPE((const krb5_setpw *rep, krb5_data ** code)); |
---|
197 | #endif |
---|
198 | |
---|
199 | krb5_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 | |
---|
282 | cleanup: |
---|
283 | if (targprinc != NULL) |
---|
284 | krb5_free_principal(context, targprinc); |
---|
285 | return(code); |
---|
286 | } |
---|
287 | |
---|
288 | int 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 | |
---|
317 | int ad_server_connect(char *connectedServer, char *domain) |
---|
318 | { |
---|
319 | admin_server = strdup(connectedServer); |
---|
320 | return(1); |
---|
321 | } |
---|
322 | |
---|
323 | void 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 | |
---|
358 | long 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 | |
---|
383 | int 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 | } |
---|