]>
Commit | Line | Data |
---|---|---|
89f77e43 | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 The Squid Software Foundation and contributors |
89f77e43 | 3 | * |
ca02e0ec AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | /* | |
89f77e43 | 10 | * AUTHOR: Flavio Pescuma, MARA Systems AB <flavio@marasystems.com> |
11 | */ | |
f7f3304a | 12 | #include "squid.h" |
89f77e43 | 13 | |
14 | #define LDAP_DEPRECATED 1 | |
15 | ||
89f77e43 | 16 | #include "ldap_backend.h" |
89f77e43 | 17 | |
7aa9bb3e | 18 | #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_ |
89f77e43 | 19 | |
20 | #define snprintf _snprintf | |
21 | #include <windows.h> | |
22 | #include <winldap.h> | |
23 | #ifndef LDAPAPI | |
24 | #define LDAPAPI __cdecl | |
25 | #endif | |
26 | #ifdef LDAP_VERSION3 | |
27 | #ifndef LDAP_OPT_X_TLS | |
28 | #define LDAP_OPT_X_TLS 0x6000 | |
29 | #endif | |
30 | /* Some tricks to allow dynamic bind with ldap_start_tls_s entry point at | |
31 | * run time. | |
32 | */ | |
33 | #undef ldap_start_tls_s | |
34 | #if LDAP_UNICODE | |
35 | #define LDAP_START_TLS_S "ldap_start_tls_sW" | |
36 | typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlW *, IN PLDAPControlW *); | |
37 | #else | |
38 | #define LDAP_START_TLS_S "ldap_start_tls_sA" | |
39 | typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlA *, IN PLDAPControlA *); | |
40 | #endif /* LDAP_UNICODE */ | |
41 | PFldap_start_tls_s Win32_ldap_start_tls_s; | |
42 | #define ldap_start_tls_s(l,s,c) Win32_ldap_start_tls_s(l,NULL,NULL,s,c) | |
43 | #endif /* LDAP_VERSION3 */ | |
44 | ||
45 | #else | |
46 | ||
47 | #include <lber.h> | |
48 | #include <ldap.h> | |
49 | ||
50 | #endif | |
f971fe39 | 51 | #include "edir_ldapext.h" |
89f77e43 | 52 | #define PROGRAM_NAME "digest_pw_auth(LDAP_backend)" |
53 | ||
54 | /* Globals */ | |
55 | ||
56 | static LDAP *ld = NULL; | |
e9505fad | 57 | static const char *passattr = NULL; |
89f77e43 | 58 | static char *ldapServer = NULL; |
e9505fad | 59 | static const char *userbasedn = NULL; |
60 | static const char *userdnattr = NULL; | |
61 | static const char *usersearchfilter = NULL; | |
62 | static const char *binddn = NULL; | |
63 | static const char *bindpasswd = NULL; | |
64 | static const char *delimiter = ":"; | |
89f77e43 | 65 | static int encrpass = 0; |
66 | static int searchscope = LDAP_SCOPE_SUBTREE; | |
67 | static int persistent = 0; | |
68 | static int noreferrals = 0; | |
89f77e43 | 69 | static int port = LDAP_PORT; |
70 | static int strip_nt_domain = 0; | |
71 | static int edir_universal_passwd = 0; | |
72 | static int aliasderef = LDAP_DEREF_NEVER; | |
73 | #if defined(NETSCAPE_SSL) | |
74 | static char *sslpath = NULL; | |
75 | static int sslinit = 0; | |
76 | #endif | |
77 | static int connect_timeout = 0; | |
78 | static int timelimit = LDAP_NO_LIMIT; | |
79 | ||
80 | #ifdef LDAP_VERSION3 | |
81 | /* Added for TLS support and version 3 */ | |
82 | static int use_tls = 0; | |
83 | static int version = -1; | |
84 | #endif | |
85 | ||
86 | static void ldapconnect(void); | |
e9505fad | 87 | static int readSecret(const char *filename); |
89f77e43 | 88 | |
89 | /* Yuck.. we need to glue to different versions of the API */ | |
90 | ||
91 | #if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823 | |
92 | static void | |
93 | squid_ldap_set_aliasderef(int deref) | |
94 | { | |
95 | ldap_set_option(ld, LDAP_OPT_DEREF, &deref); | |
96 | } | |
97 | static void | |
98 | squid_ldap_set_referrals(int referrals) | |
99 | { | |
56ff4687 | 100 | int *value = static_cast<int*>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF); |
89f77e43 | 101 | ldap_set_option(ld, LDAP_OPT_REFERRALS, value); |
102 | } | |
103 | static void | |
d5f8d05f | 104 | squid_ldap_set_timelimit(int aTimeLimit) |
89f77e43 | 105 | { |
d5f8d05f | 106 | ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &aTimeLimit); |
89f77e43 | 107 | } |
108 | static void | |
d5f8d05f | 109 | squid_ldap_set_connect_timeout(int aTimeLimit) |
89f77e43 | 110 | { |
111 | #if defined(LDAP_OPT_NETWORK_TIMEOUT) | |
112 | struct timeval tv; | |
d5f8d05f | 113 | tv.tv_sec = aTimeLimit; |
89f77e43 | 114 | tv.tv_usec = 0; |
115 | ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); | |
116 | #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) | |
d5f8d05f FC |
117 | aTimeLimit *= 1000; |
118 | ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit); | |
89f77e43 | 119 | #endif |
120 | } | |
121 | ||
122 | #else | |
123 | static int | |
124 | squid_ldap_errno(LDAP * ld) | |
125 | { | |
126 | return ld->ld_errno; | |
127 | } | |
128 | static void | |
129 | squid_ldap_set_aliasderef(int deref) | |
130 | { | |
131 | ld->ld_deref = deref; | |
132 | } | |
133 | static void | |
134 | squid_ldap_set_referrals(int referrals) | |
135 | { | |
136 | if (referrals) | |
26ac0430 | 137 | ld->ld_options |= ~LDAP_OPT_REFERRALS; |
89f77e43 | 138 | else |
26ac0430 | 139 | ld->ld_options &= ~LDAP_OPT_REFERRALS; |
89f77e43 | 140 | } |
141 | static void | |
d5f8d05f | 142 | squid_ldap_set_timelimit(int aTimeLimit) |
89f77e43 | 143 | { |
d5f8d05f | 144 | ld->ld_timelimit = aTimeLimit; |
89f77e43 | 145 | } |
146 | static void | |
d5f8d05f | 147 | squid_ldap_set_connect_timeout(int aTimeLimit) |
89f77e43 | 148 | { |
56ff4687 | 149 | fprintf(stderr, "ERROR: Connect timeouts not supported in your LDAP library\n"); |
89f77e43 | 150 | } |
151 | static void | |
152 | squid_ldap_memfree(char *p) | |
153 | { | |
154 | free(p); | |
155 | } | |
156 | ||
157 | #endif | |
158 | ||
159 | #ifdef LDAP_API_FEATURE_X_OPENLDAP | |
160 | #if LDAP_VENDOR_VERSION > 194 | |
161 | #define HAS_URI_SUPPORT 1 | |
162 | #endif | |
163 | #endif | |
164 | ||
165 | static int | |
166 | ldap_escape_value(char *escaped, int size, const char *src) | |
167 | { | |
168 | int n = 0; | |
169 | while (size > 4 && *src) { | |
26ac0430 AJ |
170 | switch (*src) { |
171 | case '*': | |
172 | case '(': | |
173 | case ')': | |
174 | case '\\': | |
175 | n += 3; | |
176 | size -= 3; | |
177 | if (size > 0) { | |
f207fe64 FC |
178 | *escaped = '\\'; |
179 | ++escaped; | |
14942edd FC |
180 | snprintf(escaped, 3, "%02x", (int) *src); |
181 | ++src; | |
26ac0430 AJ |
182 | escaped += 2; |
183 | } | |
184 | break; | |
185 | default: | |
14942edd FC |
186 | *escaped = *src; |
187 | ++escaped; | |
188 | ++src; | |
755494da FC |
189 | ++n; |
190 | --size; | |
26ac0430 | 191 | } |
89f77e43 | 192 | } |
193 | *escaped = '\0'; | |
194 | return n; | |
195 | } | |
196 | ||
197 | static char * | |
198 | getpassword(char *login, char *realm) | |
199 | { | |
200 | LDAPMessage *res = NULL; | |
201 | LDAPMessage *entry; | |
202 | char **values = NULL; | |
203 | char **value = NULL; | |
204 | char *password = NULL; | |
205 | int retry = 0; | |
206 | char filter[8192]; | |
207 | char searchbase[8192]; | |
208 | char *universal_password = NULL; | |
591c3246 | 209 | size_t universal_password_len = 256; |
89f77e43 | 210 | int nmas_res = 0; |
211 | int rc = -1; | |
212 | if (ld) { | |
26ac0430 AJ |
213 | if (usersearchfilter) { |
214 | char escaped_login[1024]; | |
215 | snprintf(searchbase, sizeof(searchbase), "%s", userbasedn); | |
216 | ldap_escape_value(escaped_login, sizeof(escaped_login), login); | |
217 | snprintf(filter, sizeof(filter), usersearchfilter, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login); | |
218 | ||
219 | retrysrch: | |
56ff4687 | 220 | debug("user filter '%s', searchbase '%s'\n", filter, searchbase); |
26ac0430 AJ |
221 | |
222 | rc = ldap_search_s(ld, searchbase, searchscope, filter, NULL, 0, &res); | |
223 | if (rc != LDAP_SUCCESS) { | |
224 | if (noreferrals && rc == LDAP_PARTIAL_RESULTS) { | |
225 | /* Everything is fine. This is expected when referrals | |
226 | * are disabled. | |
227 | */ | |
228 | rc = LDAP_SUCCESS; | |
229 | } else { | |
230 | fprintf(stderr, PROGRAM_NAME " WARNING, LDAP search error '%s'\n", ldap_err2string(rc)); | |
89f77e43 | 231 | #if defined(NETSCAPE_SSL) |
26ac0430 AJ |
232 | if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) { |
233 | int sslerr = PORT_GetError(); | |
234 | fprintf(stderr, PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr)); | |
235 | } | |
89f77e43 | 236 | #endif |
26ac0430 AJ |
237 | fprintf(stderr, PROGRAM_NAME " WARNING, LDAP search error, trying to recover'%s'\n", ldap_err2string(rc)); |
238 | ldap_msgfree(res); | |
239 | /* try to connect to the LDAP server agin, maybe my persisten conexion failed. */ | |
240 | if (!retry) { | |
755494da | 241 | ++retry; |
26ac0430 AJ |
242 | ldap_unbind(ld); |
243 | ld = NULL; | |
244 | ldapconnect(); | |
245 | goto retrysrch; | |
246 | } | |
247 | return NULL; | |
248 | ||
249 | } | |
250 | } | |
251 | } else if (userdnattr) { | |
bb85e424 | 252 | snprintf(searchbase, 8192, "%s=%s, %s", userdnattr, login, userbasedn); |
26ac0430 AJ |
253 | |
254 | retrydnattr: | |
56ff4687 | 255 | debug("searchbase '%s'\n", searchbase); |
26ac0430 AJ |
256 | rc = ldap_search_s(ld, searchbase, searchscope, NULL, NULL, 0, &res); |
257 | } | |
258 | if (rc == LDAP_SUCCESS) { | |
259 | entry = ldap_first_entry(ld, res); | |
260 | if (entry) { | |
56ff4687 | 261 | debug("ldap dn: %s\n", ldap_get_dn(ld, entry)); |
26ac0430 AJ |
262 | if (edir_universal_passwd) { |
263 | ||
264 | /* allocate some memory for the universal password returned by NMAS */ | |
56ff4687 AJ |
265 | universal_password = (char*)calloc(1, universal_password_len); |
266 | values = (char**)calloc(1, sizeof(char *)); | |
26ac0430 AJ |
267 | |
268 | /* actually talk to NMAS to get a password */ | |
269 | nmas_res = nds_get_password(ld, ldap_get_dn(ld, entry), &universal_password_len, universal_password); | |
270 | if (nmas_res == LDAP_SUCCESS && universal_password) { | |
56ff4687 | 271 | debug("NMAS returned value %s\n", universal_password); |
26ac0430 AJ |
272 | values[0] = universal_password; |
273 | } else { | |
56ff4687 | 274 | debug("Error reading Universal Password: %d = %s\n", nmas_res, ldap_err2string(nmas_res)); |
26ac0430 AJ |
275 | } |
276 | } else { | |
277 | values = ldap_get_values(ld, entry, passattr); | |
278 | } | |
279 | } else { | |
280 | ldap_msgfree(res); | |
281 | return NULL; | |
282 | } | |
283 | if (!values) { | |
56ff4687 | 284 | debug("No attribute value found\n"); |
26ac0430 AJ |
285 | if (edir_universal_passwd) |
286 | free(universal_password); | |
287 | ldap_msgfree(res); | |
288 | return NULL; | |
289 | } | |
290 | value = values; | |
291 | while (*value) { | |
292 | if (encrpass) { | |
f7f2e2d6 AJ |
293 | const char *t = strtok(*value, delimiter); |
294 | if (t && strcmp(t, realm) == 0) { | |
26ac0430 AJ |
295 | password = strtok(NULL, delimiter); |
296 | break; | |
297 | } | |
298 | } else { | |
299 | password = *value; | |
300 | break; | |
301 | } | |
755494da | 302 | ++value; |
26ac0430 | 303 | } |
56ff4687 | 304 | debug("password: %s\n", password); |
26ac0430 | 305 | if (password) |
bb85e424 | 306 | password = xstrdup(password); |
26ac0430 AJ |
307 | if (edir_universal_passwd) { |
308 | free(values); | |
309 | free(universal_password); | |
310 | } else { | |
311 | ldap_value_free(values); | |
312 | } | |
313 | ldap_msgfree(res); | |
314 | return password; | |
315 | } else { | |
316 | fprintf(stderr, PROGRAM_NAME " WARNING, LDAP error '%s'\n", ldap_err2string(rc)); | |
317 | /* try to connect to the LDAP server agin, maybe my persisten conexion failed. */ | |
318 | if (!retry) { | |
755494da | 319 | ++retry; |
26ac0430 AJ |
320 | ldap_unbind(ld); |
321 | ld = NULL; | |
322 | ldapconnect(); | |
323 | goto retrydnattr; | |
324 | } | |
325 | return NULL; | |
326 | } | |
89f77e43 | 327 | } |
328 | return NULL; | |
329 | } | |
330 | ||
89f77e43 | 331 | static void |
332 | ldapconnect(void) | |
333 | { | |
334 | int rc; | |
335 | ||
26ac0430 AJ |
336 | /* On Windows ldap_start_tls_s is available starting from Windows XP, |
337 | * so we need to bind at run-time with the function entry point | |
338 | */ | |
7aa9bb3e | 339 | #if _SQUID_WINDOWS_ |
89f77e43 | 340 | if (use_tls) { |
341 | ||
26ac0430 | 342 | HMODULE WLDAP32Handle; |
89f77e43 | 343 | |
26ac0430 AJ |
344 | WLDAP32Handle = GetModuleHandle("wldap32"); |
345 | if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) { | |
346 | fprintf(stderr, PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n"); | |
347 | exit(1); | |
348 | } | |
89f77e43 | 349 | } |
350 | #endif | |
351 | ||
352 | if (ld == NULL) { | |
353 | #if HAS_URI_SUPPORT | |
26ac0430 AJ |
354 | if (strstr(ldapServer, "://") != NULL) { |
355 | rc = ldap_initialize(&ld, ldapServer); | |
356 | if (rc != LDAP_SUCCESS) { | |
357 | fprintf(stderr, "\nUnable to connect to LDAPURI:%s\n", ldapServer); | |
358 | } | |
359 | } else | |
89f77e43 | 360 | #endif |
361 | #if NETSCAPE_SSL | |
26ac0430 AJ |
362 | if (sslpath) { |
363 | if (!sslinit && (ldapssl_client_init(sslpath, NULL) != LDAP_SUCCESS)) { | |
364 | fprintf(stderr, "\nUnable to initialise SSL with cert path %s\n", | |
365 | sslpath); | |
366 | exit(1); | |
367 | } else { | |
755494da | 368 | ++sslinit; |
26ac0430 AJ |
369 | } |
370 | if ((ld = ldapssl_init(ldapServer, port, 1)) == NULL) { | |
371 | fprintf(stderr, "\nUnable to connect to SSL LDAP server: %s port:%d\n", | |
372 | ldapServer, port); | |
373 | exit(1); | |
374 | } | |
375 | } else | |
89f77e43 | 376 | #endif |
26ac0430 AJ |
377 | if ((ld = ldap_init(ldapServer, port)) == NULL) { |
378 | fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n", ldapServer, port); | |
379 | } | |
380 | if (connect_timeout) | |
381 | squid_ldap_set_connect_timeout(connect_timeout); | |
89f77e43 | 382 | |
383 | #ifdef LDAP_VERSION3 | |
26ac0430 AJ |
384 | if (version == -1) { |
385 | version = LDAP_VERSION2; | |
386 | } | |
387 | if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) | |
388 | != LDAP_SUCCESS) { | |
389 | fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", | |
390 | version); | |
391 | ldap_unbind(ld); | |
392 | ld = NULL; | |
393 | } | |
394 | if (use_tls) { | |
89f77e43 | 395 | #ifdef LDAP_OPT_X_TLS |
26ac0430 AJ |
396 | if ((version == LDAP_VERSION3) && (ldap_start_tls_s(ld, NULL, NULL) == LDAP_SUCCESS)) { |
397 | fprintf(stderr, "Could not Activate TLS connection\n"); | |
398 | ldap_unbind(ld); | |
399 | ld = NULL; | |
400 | } | |
89f77e43 | 401 | #else |
26ac0430 AJ |
402 | fprintf(stderr, "TLS not supported with your LDAP library\n"); |
403 | ldap_unbind(ld); | |
404 | ld = NULL; | |
89f77e43 | 405 | #endif |
26ac0430 | 406 | } |
89f77e43 | 407 | #endif |
26ac0430 AJ |
408 | squid_ldap_set_timelimit(timelimit); |
409 | squid_ldap_set_referrals(!noreferrals); | |
410 | squid_ldap_set_aliasderef(aliasderef); | |
411 | if (binddn && bindpasswd && *binddn && *bindpasswd) { | |
412 | rc = ldap_simple_bind_s(ld, binddn, bindpasswd); | |
413 | if (rc != LDAP_SUCCESS) { | |
414 | fprintf(stderr, PROGRAM_NAME " WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc)); | |
415 | ldap_unbind(ld); | |
416 | ld = NULL; | |
417 | } | |
418 | } | |
56ff4687 | 419 | debug("Connected OK\n"); |
89f77e43 | 420 | } |
421 | } | |
422 | int | |
423 | LDAPArguments(int argc, char **argv) | |
424 | { | |
425 | setbuf(stdout, NULL); | |
426 | ||
427 | while (argc > 1 && argv[1][0] == '-') { | |
26ac0430 AJ |
428 | const char *value = ""; |
429 | char option = argv[1][1]; | |
430 | switch (option) { | |
431 | case 'P': | |
432 | case 'R': | |
433 | case 'z': | |
434 | case 'Z': | |
435 | case 'g': | |
436 | case 'e': | |
437 | case 'S': | |
438 | case 'n': | |
439 | case 'd': | |
440 | break; | |
441 | default: | |
442 | if (strlen(argv[1]) > 2) { | |
443 | value = argv[1] + 2; | |
444 | } else if (argc > 2) { | |
445 | value = argv[2]; | |
755494da FC |
446 | ++argv; |
447 | --argc; | |
26ac0430 AJ |
448 | } else |
449 | value = ""; | |
450 | break; | |
451 | } | |
755494da FC |
452 | ++argv; |
453 | --argc; | |
26ac0430 AJ |
454 | switch (option) { |
455 | case 'H': | |
89f77e43 | 456 | #if !HAS_URI_SUPPORT |
26ac0430 AJ |
457 | fprintf(stderr, "ERROR: Your LDAP library does not have URI support\n"); |
458 | return 1; | |
89f77e43 | 459 | #endif |
f53969cc | 460 | /* Fall thru to -h */ |
26ac0430 AJ |
461 | case 'h': |
462 | if (ldapServer) { | |
463 | int len = strlen(ldapServer) + 1 + strlen(value) + 1; | |
c14fb378 | 464 | char *newhost = static_cast<char*>(xmalloc(len)); |
26ac0430 AJ |
465 | snprintf(newhost, len, "%s %s", ldapServer, value); |
466 | free(ldapServer); | |
467 | ldapServer = newhost; | |
468 | } else { | |
bb85e424 | 469 | ldapServer = xstrdup(value); |
26ac0430 AJ |
470 | } |
471 | break; | |
472 | case 'A': | |
473 | passattr = value; | |
474 | break; | |
475 | case 'e': | |
476 | encrpass = 1; | |
477 | break; | |
478 | case 'l': | |
479 | delimiter = value; | |
480 | break; | |
481 | case 'b': | |
482 | userbasedn = value; | |
483 | break; | |
484 | case 'F': | |
485 | usersearchfilter = value; | |
486 | break; | |
487 | case 'u': | |
488 | userdnattr = value; | |
489 | break; | |
490 | case 's': | |
491 | if (strcmp(value, "base") == 0) | |
492 | searchscope = LDAP_SCOPE_BASE; | |
493 | else if (strcmp(value, "one") == 0) | |
494 | searchscope = LDAP_SCOPE_ONELEVEL; | |
495 | else if (strcmp(value, "sub") == 0) | |
496 | searchscope = LDAP_SCOPE_SUBTREE; | |
497 | else { | |
498 | fprintf(stderr, PROGRAM_NAME " ERROR: Unknown search scope '%s'\n", value); | |
499 | return 1; | |
500 | } | |
501 | break; | |
502 | case 'S': | |
89f77e43 | 503 | #if defined(NETSCAPE_SSL) |
26ac0430 AJ |
504 | sslpath = value; |
505 | if (port == LDAP_PORT) | |
506 | port = LDAPS_PORT; | |
89f77e43 | 507 | #else |
26ac0430 AJ |
508 | fprintf(stderr, PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n"); |
509 | return 1; | |
89f77e43 | 510 | #endif |
26ac0430 AJ |
511 | break; |
512 | case 'c': | |
513 | connect_timeout = atoi(value); | |
514 | break; | |
515 | case 't': | |
516 | timelimit = atoi(value); | |
517 | break; | |
518 | case 'a': | |
519 | if (strcmp(value, "never") == 0) | |
520 | aliasderef = LDAP_DEREF_NEVER; | |
521 | else if (strcmp(value, "always") == 0) | |
522 | aliasderef = LDAP_DEREF_ALWAYS; | |
523 | else if (strcmp(value, "search") == 0) | |
524 | aliasderef = LDAP_DEREF_SEARCHING; | |
525 | else if (strcmp(value, "find") == 0) | |
526 | aliasderef = LDAP_DEREF_FINDING; | |
527 | else { | |
528 | fprintf(stderr, PROGRAM_NAME " ERROR: Unknown alias dereference method '%s'\n", value); | |
529 | return 1; | |
530 | } | |
531 | break; | |
532 | case 'D': | |
533 | binddn = value; | |
534 | break; | |
535 | case 'w': | |
536 | bindpasswd = value; | |
537 | break; | |
538 | case 'W': | |
539 | readSecret(value); | |
540 | break; | |
541 | case 'P': | |
542 | persistent = !persistent; | |
543 | break; | |
544 | case 'p': | |
545 | port = atoi(value); | |
546 | break; | |
547 | case 'R': | |
548 | noreferrals = !noreferrals; | |
549 | break; | |
89f77e43 | 550 | #ifdef LDAP_VERSION3 |
26ac0430 AJ |
551 | case 'v': |
552 | switch (atoi(value)) { | |
553 | case 2: | |
554 | version = LDAP_VERSION2; | |
555 | break; | |
556 | case 3: | |
557 | version = LDAP_VERSION3; | |
558 | break; | |
559 | default: | |
560 | fprintf(stderr, "Protocol version should be 2 or 3\n"); | |
561 | return 1; | |
562 | } | |
563 | break; | |
564 | case 'Z': | |
565 | if (version == LDAP_VERSION2) { | |
566 | fprintf(stderr, "TLS (-Z) is incompatible with version %d\n", | |
567 | version); | |
568 | return 1; | |
569 | } | |
570 | version = LDAP_VERSION3; | |
571 | use_tls = 1; | |
572 | break; | |
89f77e43 | 573 | #endif |
26ac0430 | 574 | case 'd': |
56ff4687 | 575 | debug_enabled = 1; |
26ac0430 AJ |
576 | break; |
577 | case 'E': | |
578 | strip_nt_domain = 1; | |
579 | break; | |
580 | case 'n': | |
581 | edir_universal_passwd = 1; | |
582 | break; | |
583 | default: | |
584 | fprintf(stderr, PROGRAM_NAME " ERROR: Unknown command line option '%c'\n", option); | |
585 | return 1; | |
586 | } | |
89f77e43 | 587 | } |
588 | ||
589 | while (argc > 1) { | |
26ac0430 AJ |
590 | char *value = argv[1]; |
591 | if (ldapServer) { | |
592 | int len = strlen(ldapServer) + 1 + strlen(value) + 1; | |
c14fb378 | 593 | char *newhost = static_cast<char*>(xmalloc(len)); |
26ac0430 AJ |
594 | snprintf(newhost, len, "%s %s", ldapServer, value); |
595 | free(ldapServer); | |
596 | ldapServer = newhost; | |
597 | } else { | |
bb85e424 | 598 | ldapServer = xstrdup(value); |
26ac0430 | 599 | } |
755494da FC |
600 | --argc; |
601 | ++argv; | |
89f77e43 | 602 | } |
603 | ||
604 | if (!ldapServer) | |
26ac0430 | 605 | ldapServer = (char *) "localhost"; |
89f77e43 | 606 | |
607 | if (!userbasedn || !((passattr != NULL) || (edir_universal_passwd && usersearchfilter && version == LDAP_VERSION3 && use_tls))) { | |
26ac0430 AJ |
608 | fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn -f filter [options] ldap_server_name\n\n"); |
609 | fprintf(stderr, "\t-A password attribute(REQUIRED)\t\tUser attribute that contains the password\n"); | |
610 | fprintf(stderr, "\t-l password realm delimiter(REQUIRED)\tCharater(s) that devides the password attribute\n\t\t\t\t\t\tin realm and password tokens, default ':' realm:password\n"); | |
611 | fprintf(stderr, "\t-b basedn (REQUIRED)\t\t\tbase dn under where to search for users\n"); | |
612 | fprintf(stderr, "\t-e Encrypted passwords(REQUIRED)\tPassword are stored encrypted using HHA1\n"); | |
613 | fprintf(stderr, "\t-F filter\t\t\t\tuser search filter pattern. %%s = login\n"); | |
614 | fprintf(stderr, "\t-u attribute\t\t\t\tattribute to use in combination with the basedn to create the user DN\n"); | |
615 | fprintf(stderr, "\t-s base|one|sub\t\t\t\tsearch scope\n"); | |
616 | fprintf(stderr, "\t-D binddn\t\t\t\tDN to bind as to perform searches\n"); | |
617 | fprintf(stderr, "\t-w bindpasswd\t\t\t\tpassword for binddn\n"); | |
618 | fprintf(stderr, "\t-W secretfile\t\t\t\tread password for binddn from file secretfile\n"); | |
89f77e43 | 619 | #if HAS_URI_SUPPORT |
26ac0430 | 620 | fprintf(stderr, "\t-H URI\t\t\t\t\tLDAPURI (defaults to ldap://localhost)\n"); |
89f77e43 | 621 | #endif |
26ac0430 AJ |
622 | fprintf(stderr, "\t-h server\t\t\t\tLDAP server (defaults to localhost)\n"); |
623 | fprintf(stderr, "\t-p port\t\t\t\t\tLDAP server port (defaults to %d)\n", LDAP_PORT); | |
624 | fprintf(stderr, "\t-P\t\t\t\t\tpersistent LDAP connection\n"); | |
89f77e43 | 625 | #if defined(NETSCAPE_SSL) |
26ac0430 | 626 | fprintf(stderr, "\t-E sslcertpath\t\t\t\tenable LDAP over SSL\n"); |
89f77e43 | 627 | #endif |
26ac0430 AJ |
628 | fprintf(stderr, "\t-c timeout\t\t\t\tconnect timeout\n"); |
629 | fprintf(stderr, "\t-t timelimit\t\t\t\tsearch time limit\n"); | |
630 | fprintf(stderr, "\t-R\t\t\t\t\tdo not follow referrals\n"); | |
631 | fprintf(stderr, "\t-a never|always|search|find\t\twhen to dereference aliases\n"); | |
89f77e43 | 632 | #ifdef LDAP_VERSION3 |
26ac0430 AJ |
633 | fprintf(stderr, "\t-v 2|3\t\t\t\t\tLDAP version\n"); |
634 | fprintf(stderr, "\t-Z\t\t\t\t\tTLS encrypt the LDAP connection, requires\n\t\t\t\tLDAP version 3\n"); | |
89f77e43 | 635 | #endif |
26ac0430 AJ |
636 | fprintf(stderr, "\t-S\t\t\t\t\tStrip NT domain from usernames\n"); |
637 | fprintf(stderr, "\t-n\t\t\t\t\tGet an eDirectory Universal Password from Novell NMAS\n\t\t\t\t\t\t(requires bind credentials, version 3, TLS, and a search filter)\n"); | |
638 | fprintf(stderr, "\n"); | |
639 | fprintf(stderr, "\tIf you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd or -D binddn -W secretfile options\n\n"); | |
640 | return -1; | |
89f77e43 | 641 | } |
642 | return 0; | |
643 | } | |
644 | static int | |
e9505fad | 645 | readSecret(const char *filename) |
89f77e43 | 646 | { |
647 | char buf[BUFSIZ]; | |
648 | char *e = 0; | |
649 | FILE *f; | |
650 | ||
651 | if (!(f = fopen(filename, "r"))) { | |
26ac0430 AJ |
652 | fprintf(stderr, PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename); |
653 | return 1; | |
89f77e43 | 654 | } |
655 | if (!fgets(buf, sizeof(buf) - 1, f)) { | |
26ac0430 AJ |
656 | fprintf(stderr, PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename); |
657 | fclose(f); | |
658 | return 1; | |
89f77e43 | 659 | } |
660 | /* strip whitespaces on end */ | |
661 | if ((e = strrchr(buf, '\n'))) | |
26ac0430 | 662 | *e = 0; |
89f77e43 | 663 | if ((e = strrchr(buf, '\r'))) |
26ac0430 | 664 | *e = 0; |
89f77e43 | 665 | |
bb85e424 | 666 | bindpasswd = xstrdup(buf); |
e9505fad | 667 | if (!bindpasswd) { |
26ac0430 | 668 | fprintf(stderr, PROGRAM_NAME " ERROR: can not allocate memory\n"); |
89f77e43 | 669 | } |
89f77e43 | 670 | fclose(f); |
671 | ||
672 | return 0; | |
673 | } | |
674 | ||
675 | void | |
676 | LDAPHHA1(RequestData * requestData) | |
677 | { | |
e9505fad | 678 | char *password; |
89f77e43 | 679 | ldapconnect(); |
680 | password = getpassword(requestData->user, requestData->realm); | |
681 | if (password != NULL) { | |
26ac0430 AJ |
682 | if (encrpass) |
683 | xstrncpy(requestData->HHA1, password, sizeof(requestData->HHA1)); | |
684 | else { | |
685 | HASH HA1; | |
686 | DigestCalcHA1("md5", requestData->user, requestData->realm, password, NULL, NULL, HA1, requestData->HHA1); | |
687 | } | |
688 | free(password); | |
89f77e43 | 689 | } else { |
26ac0430 | 690 | requestData->error = -1; |
89f77e43 | 691 | } |
692 | ||
693 | } | |
f53969cc | 694 |