1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
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 /*
10  * AUTHOR: Flavio Pescuma, MARA Systems AB <flavio@marasystems.com>
11  */
12 #include "squid.h"
13 
14 #define LDAP_DEPRECATED 1
15 
16 #include "auth/digest/eDirectory/ldap_backend.h"
17 
18 #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
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
51 #include "auth/digest/eDirectory/edir_ldapext.h"
52 #define PROGRAM_NAME "digest_pw_auth(LDAP_backend)"
53 
54 /* Globals */
55 
56 static LDAP *ld = NULL;
57 static const char *passattr = NULL;
58 static char *ldapServer = NULL;
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 = ":";
65 static int encrpass = 0;
66 static int searchscope = LDAP_SCOPE_SUBTREE;
67 static int persistent = 0;
68 static int noreferrals = 0;
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);
87 static int readSecret(const char *filename);
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
squid_ldap_set_aliasderef(int deref)93 squid_ldap_set_aliasderef(int deref)
94 {
95     ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
96 }
97 static void
squid_ldap_set_referrals(int referrals)98 squid_ldap_set_referrals(int referrals)
99 {
100     int *value = static_cast<int*>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF);
101     ldap_set_option(ld, LDAP_OPT_REFERRALS, value);
102 }
103 static void
squid_ldap_set_timelimit(int aTimeLimit)104 squid_ldap_set_timelimit(int aTimeLimit)
105 {
106     ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &aTimeLimit);
107 }
108 static void
squid_ldap_set_connect_timeout(int aTimeLimit)109 squid_ldap_set_connect_timeout(int aTimeLimit)
110 {
111 #if defined(LDAP_OPT_NETWORK_TIMEOUT)
112     struct timeval tv;
113     tv.tv_sec = aTimeLimit;
114     tv.tv_usec = 0;
115     ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
116 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
117     aTimeLimit *= 1000;
118     ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit);
119 #endif
120 }
121 
122 #else
123 static int
squid_ldap_errno(LDAP * ld)124 squid_ldap_errno(LDAP * ld)
125 {
126     return ld->ld_errno;
127 }
128 static void
squid_ldap_set_aliasderef(int deref)129 squid_ldap_set_aliasderef(int deref)
130 {
131     ld->ld_deref = deref;
132 }
133 static void
squid_ldap_set_referrals(int referrals)134 squid_ldap_set_referrals(int referrals)
135 {
136     if (referrals)
137         ld->ld_options |= ~LDAP_OPT_REFERRALS;
138     else
139         ld->ld_options &= ~LDAP_OPT_REFERRALS;
140 }
141 static void
squid_ldap_set_timelimit(int aTimeLimit)142 squid_ldap_set_timelimit(int aTimeLimit)
143 {
144     ld->ld_timelimit = aTimeLimit;
145 }
146 static void
squid_ldap_set_connect_timeout(int aTimeLimit)147 squid_ldap_set_connect_timeout(int aTimeLimit)
148 {
149     fprintf(stderr, "ERROR: Connect timeouts not supported in your LDAP library\n");
150 }
151 static void
squid_ldap_memfree(char * p)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
ldap_escape_value(char * escaped,int size,const char * src)166 ldap_escape_value(char *escaped, int size, const char *src)
167 {
168     int n = 0;
169     while (size > 4 && *src) {
170         switch (*src) {
171         case '*':
172         case '(':
173         case ')':
174         case '\\':
175             n += 3;
176             size -= 3;
177             if (size > 0) {
178                 *escaped = '\\';
179                 ++escaped;
180                 snprintf(escaped, 3, "%02x", (int) *src);
181                 ++src;
182                 escaped += 2;
183             }
184             break;
185         default:
186             *escaped = *src;
187             ++escaped;
188             ++src;
189             ++n;
190             --size;
191         }
192     }
193     *escaped = '\0';
194     return n;
195 }
196 
197 static char *
getpassword(char * login,char * realm)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;
209     size_t universal_password_len = 256;
210     int nmas_res = 0;
211     int rc = -1;
212     if (ld) {
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:
220             debug("user filter '%s', searchbase '%s'\n", filter, searchbase);
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));
231 #if defined(NETSCAPE_SSL)
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                     }
236 #endif
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) {
241                         ++retry;
242                         ldap_unbind(ld);
243                         ld = NULL;
244                         ldapconnect();
245                         goto retrysrch;
246                     }
247                     return NULL;
248 
249                 }
250             }
251         } else if (userdnattr) {
252             snprintf(searchbase, 8192, "%s=%s, %s", userdnattr, login, userbasedn);
253 
254 retrydnattr:
255             debug("searchbase '%s'\n", searchbase);
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) {
261                 debug("ldap dn: %s\n", ldap_get_dn(ld, entry));
262                 if (edir_universal_passwd) {
263 
264                     /* allocate some memory for the universal password returned by NMAS */
265                     universal_password = (char*)calloc(1, universal_password_len);
266                     values = (char**)calloc(1, sizeof(char *));
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) {
271                         debug("NMAS returned value %s\n", universal_password);
272                         values[0] = universal_password;
273                     } else {
274                         debug("Error reading Universal Password: %d = %s\n", nmas_res, ldap_err2string(nmas_res));
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) {
284                 debug("No attribute value found\n");
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) {
293                     const char *t = strtok(*value, delimiter);
294                     if (t && strcmp(t, realm) == 0) {
295                         password = strtok(NULL, delimiter);
296                         break;
297                     }
298                 } else {
299                     password = *value;
300                     break;
301                 }
302                 ++value;
303             }
304             debug("password: %s\n", password);
305             if (password)
306                 password = xstrdup(password);
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) {
319                 ++retry;
320                 ldap_unbind(ld);
321                 ld = NULL;
322                 ldapconnect();
323                 goto retrydnattr;
324             }
325             return NULL;
326         }
327     }
328     return NULL;
329 }
330 
331 static void
ldapconnect(void)332 ldapconnect(void)
333 {
334     int rc;
335 
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      */
339 #if _SQUID_WINDOWS_
340     if (use_tls) {
341 
342         HMODULE WLDAP32Handle;
343 
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         }
349     }
350 #endif
351 
352     if (ld == NULL) {
353 #if HAS_URI_SUPPORT
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
360 #endif
361 #if NETSCAPE_SSL
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 {
368                     ++sslinit;
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
376 #endif
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);
382 
383 #ifdef LDAP_VERSION3
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) {
395 #ifdef LDAP_OPT_X_TLS
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             }
401 #else
402             fprintf(stderr, "TLS not supported with your LDAP library\n");
403             ldap_unbind(ld);
404             ld = NULL;
405 #endif
406         }
407 #endif
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         }
419         debug("Connected OK\n");
420     }
421 }
422 int
LDAPArguments(int argc,char ** argv)423 LDAPArguments(int argc, char **argv)
424 {
425     setbuf(stdout, NULL);
426 
427     while (argc > 1 && argv[1][0] == '-') {
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];
446                 ++argv;
447                 --argc;
448             } else
449                 value = "";
450             break;
451         }
452         ++argv;
453         --argc;
454         switch (option) {
455         case 'H':
456 #if !HAS_URI_SUPPORT
457             fprintf(stderr, "ERROR: Your LDAP library does not have URI support\n");
458             return 1;
459 #endif
460         /* Fall thru to -h */
461         case 'h':
462             if (ldapServer) {
463                 int len = strlen(ldapServer) + 1 + strlen(value) + 1;
464                 char *newhost = static_cast<char*>(xmalloc(len));
465                 snprintf(newhost, len, "%s %s", ldapServer, value);
466                 free(ldapServer);
467                 ldapServer = newhost;
468             } else {
469                 ldapServer = xstrdup(value);
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':
503 #if defined(NETSCAPE_SSL)
504             sslpath = value;
505             if (port == LDAP_PORT)
506                 port = LDAPS_PORT;
507 #else
508             fprintf(stderr, PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n");
509             return 1;
510 #endif
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;
550 #ifdef LDAP_VERSION3
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;
573 #endif
574         case 'd':
575             debug_enabled = 1;
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         }
587     }
588 
589     while (argc > 1) {
590         char *value = argv[1];
591         if (ldapServer) {
592             int len = strlen(ldapServer) + 1 + strlen(value) + 1;
593             char *newhost = static_cast<char*>(xmalloc(len));
594             snprintf(newhost, len, "%s %s", ldapServer, value);
595             free(ldapServer);
596             ldapServer = newhost;
597         } else {
598             ldapServer = xstrdup(value);
599         }
600         --argc;
601         ++argv;
602     }
603 
604     if (!ldapServer)
605         ldapServer = (char *) "localhost";
606 
607     if (!userbasedn || !((passattr != NULL) || (edir_universal_passwd && usersearchfilter && version == LDAP_VERSION3 && use_tls))) {
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");
619 #if HAS_URI_SUPPORT
620         fprintf(stderr, "\t-H URI\t\t\t\t\tLDAPURI (defaults to ldap://localhost)\n");
621 #endif
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");
625 #if defined(NETSCAPE_SSL)
626         fprintf(stderr, "\t-E sslcertpath\t\t\t\tenable LDAP over SSL\n");
627 #endif
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");
632 #ifdef LDAP_VERSION3
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");
635 #endif
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;
641     }
642     return 0;
643 }
644 static int
readSecret(const char * filename)645 readSecret(const char *filename)
646 {
647     char buf[BUFSIZ];
648     char *e = 0;
649     FILE *f;
650 
651     if (!(f = fopen(filename, "r"))) {
652         fprintf(stderr, PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename);
653         return 1;
654     }
655     if (!fgets(buf, sizeof(buf) - 1, f)) {
656         fprintf(stderr, PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename);
657         fclose(f);
658         return 1;
659     }
660     /* strip whitespaces on end */
661     if ((e = strrchr(buf, '\n')))
662         *e = 0;
663     if ((e = strrchr(buf, '\r')))
664         *e = 0;
665 
666     bindpasswd = xstrdup(buf);
667     if (!bindpasswd) {
668         fprintf(stderr, PROGRAM_NAME " ERROR: can not allocate memory\n");
669     }
670     fclose(f);
671 
672     return 0;
673 }
674 
675 void
LDAPHHA1(RequestData * requestData)676 LDAPHHA1(RequestData * requestData)
677 {
678     char *password;
679     ldapconnect();
680     password = getpassword(requestData->user, requestData->realm);
681     if (password != NULL) {
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);
689     } else {
690         requestData->error = -1;
691     }
692 
693 }
694 
695