basic_ldap_auth.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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  * squid_ldap_auth: authentication via ldap for squid proxy server
11  *
12  * Authors:
13  * Henrik Nordstrom
14  * hno@squid-cache.org
15  *
16  * Glen Newton
17  * glen.newton@nrc.ca
18  * Advanced Services
19  * CISTI
20  * National Research Council
21  *
22  * with contributions from others mentioned in the Changes section below
23  *
24  * Usage: squid_ldap_auth -b basedn [-s searchscope]
25  * [-f searchfilter] [-D binddn -w bindpasswd]
26  * [-u attr] [-h host] [-p port] [-P] [-R] [ldap_server_name[:port]] ...
27  *
28  * Dependencies: You need to get the OpenLDAP libraries
29  * from http://www.openldap.org or another compatible LDAP C-API
30  * implementation.
31  *
32  * If you want to make a TLS enabled connection you will also need the
33  * OpenSSL libraries linked into openldap. See http://www.openssl.org/
34  *
35  * License: squid_ldap_auth is free software; you can redistribute it
36  * and/or modify it under the terms of the GNU General Public License
37  * as published by the Free Software Foundation; either version 2,
38  * or (at your option) any later version.
39  *
40  * Changes:
41  * 2019-01-02: Amish
42  * - Use SEND_*() macro and support for BH error
43  * 2005-01-07: Henrik Nordstrom <hno@squid-cache.org>
44  * - Added some sanity checks on login names to avoid
45  * users bypassing equality checks by exploring the
46  * overly helpful match capabilities of LDAP
47  * 2004-07-17: Henrik Nordstrom <hno@squid-cache.org>
48  * - Corrected non-persistent mode to only issue one
49  * ldap_bind per connection.
50  * - -U option to compare the users password rather
51  * than binding.
52  * 2004-03-01: Henrik Nordstrom <hno@squid-cache.org>
53  * - corrected building of search filters to escape
54  * unsafe input
55  * - -d option for "debug" like squid_ldap_group
56  * 2004-01-05: Henrik Nordstrom <hno@squid-cache.org>
57  * - Corrected TLS mode
58  * 2003-03-01: David J N Begley
59  * - Support for Netscape API method of ldap over SSL
60  * connections
61  * - Timeout option for better recovery when using
62  * multiple LDAP servers
63  * 2003-03-01: Christoph Lechleitner <lech@ibcl.at>
64  * - Added -W option to read bindpasswd from file
65  * 2003-03-01: Juerg Michel
66  * - Added support for ldap URI via the -H option
67  * (requires OpenLDAP)
68  * 2001-12-12: Michael Cunningham <m.cunningham@xpedite.com>
69  * - Added TLS support and partial ldap version 3 support.
70  * 2001-10-04: Henrik Nordstrom <hno@squid-cache.org>
71  * - Be consistent with the other helpers in how
72  * spaces are managed. If there is space characters
73  * then these are assumed to be part of the password
74  * 2001-09-05: Henrik Nordstrom <hno@squid-cache.org>
75  * - Added ability to specify another default LDAP port to
76  * connect to. Persistent connections moved to -P
77  * 2001-05-02: Henrik Nordstrom <hno@squid-cache.org>
78  * - Support newer OpenLDAP 2.x libraries using the
79  * revised Internet Draft API which unfortunately
80  * is not backwards compatible with RFC1823..
81  * 2001-04-15: Henrik Nordstrom <hno@squid-cache.org>
82  * - Added command line option for basedn
83  * - Added the ability to search for the user DN
84  * 2001-04-16: Henrik Nordstrom <hno@squid-cache.org>
85  * - Added -D binddn -w bindpasswd.
86  * 2001-04-17: Henrik Nordstrom <hno@squid-cache.org>
87  * - Added -R to disable referrals
88  * - Added -a to control alias dereferencing
89  * 2001-04-17: Henrik Nordstrom <hno@squid-cache.org>
90  * - Added -u, DN username attribute name
91  * 2001-04-18: Henrik Nordstrom <hno@squid-cache.org>
92  * - Allow full filter specifications in -f
93  */
94 
95 #include "squid.h"
97 
98 #define LDAP_DEPRECATED 1
99 
100 #include "rfc1738.h"
101 #include "util.h"
102 
103 #include <cctype>
104 #include <cstring>
105 
106 #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
107 #define snprintf _snprintf
108 #include <windows.h>
109 #include <winldap.h>
110 #ifndef LDAPAPI
111 #define LDAPAPI __cdecl
112 #endif
113 #ifdef LDAP_VERSION3
114 #ifndef LDAP_OPT_X_TLS
115 #define LDAP_OPT_X_TLS 0x6000
116 #endif
117 /* Some tricks to allow dynamic bind with ldap_start_tls_s entry point at
118  * run time.
119  */
120 #undef ldap_start_tls_s
121 #if LDAP_UNICODE
122 #define LDAP_START_TLS_S "ldap_start_tls_sW"
123 typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlW *, IN PLDAPControlW *);
124 #else
125 #define LDAP_START_TLS_S "ldap_start_tls_sA"
126 typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlA *, IN PLDAPControlA *);
127 #endif /* LDAP_UNICODE */
128 PFldap_start_tls_s Win32_ldap_start_tls_s;
129 #define ldap_start_tls_s(l,s,c) Win32_ldap_start_tls_s(l,NULL,NULL,s,c)
130 #endif /* LDAP_VERSION3 */
131 
132 #else
133 
134 #include <lber.h>
135 #include <ldap.h>
136 
137 #endif
138 
139 #define PROGRAM_NAME "basic_ldap_auth"
140 
141 /* Global options */
142 static const char *basedn;
143 static const char *searchfilter = NULL;
144 static const char *binddn = NULL;
145 static const char *bindpasswd = NULL;
146 static const char *userattr = "uid";
147 static const char *passwdattr = NULL;
148 static int searchscope = LDAP_SCOPE_SUBTREE;
149 static int persistent = 0;
150 static int bind_once = 0;
151 static int noreferrals = 0;
152 static int aliasderef = LDAP_DEREF_NEVER;
153 #if defined(NETSCAPE_SSL)
154 static const char *sslpath = NULL;
155 static int sslinit = 0;
156 #endif
157 static int connect_timeout = 0;
158 static int timelimit = LDAP_NO_LIMIT;
159 
160 /* Added for TLS support and version 3 */
161 static int use_tls = 0;
162 static int version = -1;
163 
164 static int checkLDAP(LDAP * ld, const char *userid, const char *password, const char *server, int port);
165 static int readSecret(const char *filename);
166 
167 /* Yuck.. we need to glue to different versions of the API */
168 
169 #ifndef LDAP_NO_ATTRS
170 #define LDAP_NO_ATTRS "1.1"
171 #endif
172 
173 #if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823
174 static int
175 squid_ldap_errno(LDAP * ld)
176 {
177  int err = 0;
178  ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
179  return err;
180 }
181 static void
182 squid_ldap_set_aliasderef(LDAP * ld, int deref)
183 {
184  ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
185 }
186 static void
187 squid_ldap_set_referrals(LDAP * ld, int referrals)
188 {
189  int *value = static_cast<int*>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF);
190  ldap_set_option(ld, LDAP_OPT_REFERRALS, value);
191 }
192 static void
193 squid_ldap_set_timelimit(LDAP * ld, int aTimeLimit)
194 {
195  ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &aTimeLimit);
196 }
197 static void
198 squid_ldap_set_connect_timeout(LDAP * ld, int aTimeLimit)
199 {
200 #if defined(LDAP_OPT_NETWORK_TIMEOUT)
201  struct timeval tv;
202  tv.tv_sec = aTimeLimit;
203  tv.tv_usec = 0;
204  ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
205 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
206  aTimeLimit *= 1000;
207  ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit);
208 #endif
209 }
210 static void
211 squid_ldap_memfree(char *p)
212 {
213  ldap_memfree(p);
214 }
215 
216 #else
217 static int
219 {
220  return ld->ld_errno;
221 }
222 static void
223 squid_ldap_set_aliasderef(LDAP * ld, int deref)
224 {
225  ld->ld_deref = deref;
226 }
227 static void
228 squid_ldap_set_referrals(LDAP * ld, int referrals)
229 {
230  if (referrals)
231  ld->ld_options |= ~LDAP_OPT_REFERRALS;
232  else
233  ld->ld_options &= ~LDAP_OPT_REFERRALS;
234 }
235 static void
237 {
238  ld->ld_timelimit = timelimit;
239 }
240 static void
242 {
243  fprintf(stderr, "Connect timeouts not supported in your LDAP library\n");
244 }
245 static void
247 {
248  free(p);
249 }
250 
251 #endif
252 
253 #ifdef LDAP_API_FEATURE_X_OPENLDAP
254 #if LDAP_VENDOR_VERSION > 194
255 #define HAS_URI_SUPPORT 1
256 #endif
257 #endif
258 
259 static LDAP *
261 {
262  LDAP *ld = NULL;
263 #if HAS_URI_SUPPORT
264  if (strstr(ldapServer, "://") != NULL) {
265  int rc = ldap_initialize(&ld, ldapServer);
266  if (rc != LDAP_SUCCESS) {
267  fprintf(stderr, "\nUnable to connect to LDAPURI:%s\n", ldapServer);
268  exit(EXIT_FAILURE);
269  }
270  } else
271 #endif
272 #if NETSCAPE_SSL
273  if (sslpath) {
274  if (!sslinit && (ldapssl_client_init(sslpath, NULL) != LDAP_SUCCESS)) {
275  fprintf(stderr, "\nUnable to initialise SSL with cert path %s\n",
276  sslpath);
277  exit(EXIT_FAILURE);
278  } else {
279  ++sslinit;
280  }
281  if ((ld = ldapssl_init(ldapServer, port, 1)) == NULL) {
282  fprintf(stderr, "\nUnable to connect to SSL LDAP server: %s port:%d\n",
283  ldapServer, port);
284  exit(EXIT_FAILURE);
285  }
286  } else
287 #endif
288  if ((ld = ldap_init(ldapServer, port)) == NULL) {
289  fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n",
290  ldapServer, port);
291  exit(EXIT_FAILURE);
292  }
293  if (connect_timeout)
295 
296 #ifdef LDAP_VERSION3
297  if (version == -1) {
298  version = LDAP_VERSION3;
299  }
300  if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_SUCCESS) {
301  fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
302  version);
303  exit(EXIT_FAILURE);
304  }
305  if (use_tls) {
306 #ifdef LDAP_OPT_X_TLS
307  if (version != LDAP_VERSION3) {
308  fprintf(stderr, "TLS requires LDAP version 3\n");
309  exit(EXIT_FAILURE);
310  } else if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS) {
311  fprintf(stderr, "Could not Activate TLS connection\n");
312  exit(EXIT_FAILURE);
313  }
314 #else
315  fprintf(stderr, "TLS not supported with your LDAP library\n");
316  exit(EXIT_FAILURE);
317 #endif
318  }
319 #endif
323  return ld;
324 }
325 
326 /* Make a sanity check on the username to reject oddly typed names */
327 static int
328 validUsername(const char *user)
329 {
330  const unsigned char *p = (const unsigned char *) user;
331 
332  /* Leading whitespace? */
333  if (xisspace(p[0]))
334  return 0;
335  while (p[0] && p[1]) {
336  if (xisspace(p[0])) {
337  /* More than one consequitive space? */
338  if (xisspace(p[1]))
339  return 0;
340  /* or odd space type character used? */
341  if (p[0] != ' ')
342  return 0;
343  }
344  ++p;
345  }
346  /* Trailing whitespace? */
347  if (xisspace(p[0]))
348  return 0;
349  return 1;
350 }
351 
352 int
353 main(int argc, char **argv)
354 {
355  char buf[1024];
356  char *user, *passwd;
357  char *ldapServer = NULL;
358  LDAP *ld = NULL;
359  int tryagain;
360  int port = LDAP_PORT;
361 
362  setbuf(stdout, NULL);
363 
364  while (argc > 1 && argv[1][0] == '-') {
365  const char *value = "";
366  char option = argv[1][1];
367  switch (option) {
368  case 'P':
369  case 'R':
370  case 'z':
371  case 'Z':
372  case 'd':
373  case 'O':
374  break;
375  default:
376  if (strlen(argv[1]) > 2) {
377  value = argv[1] + 2;
378  } else if (argc > 2) {
379  value = argv[2];
380  ++argv;
381  --argc;
382  } else
383  value = "";
384  break;
385  }
386  ++argv;
387  --argc;
388  switch (option) {
389  case 'H':
390 #if !HAS_URI_SUPPORT
391  fprintf(stderr, "ERROR: Your LDAP library does not have URI support\n");
392  exit(EXIT_FAILURE);
393 #endif
394  /* Fall thru to -h */
395  case 'h':
396  if (ldapServer) {
397  int len = strlen(ldapServer) + 1 + strlen(value) + 1;
398  char *newhost = static_cast<char*>(xmalloc(len));
399  snprintf(newhost, len, "%s %s", ldapServer, value);
400  free(ldapServer);
401  ldapServer = newhost;
402  } else {
403  ldapServer = xstrdup(value);
404  }
405  break;
406  case 'b':
407  basedn = value;
408  break;
409  case 'f':
410  searchfilter = value;
411  break;
412  case 'u':
413  userattr = value;
414  break;
415  case 'U':
416  passwdattr = value;
417  break;
418  case 's':
419  if (strcmp(value, "base") == 0)
420  searchscope = LDAP_SCOPE_BASE;
421  else if (strcmp(value, "one") == 0)
422  searchscope = LDAP_SCOPE_ONELEVEL;
423  else if (strcmp(value, "sub") == 0)
424  searchscope = LDAP_SCOPE_SUBTREE;
425  else {
426  fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown search scope '%s'\n", value);
427  exit(EXIT_FAILURE);
428  }
429  break;
430  case 'E':
431 #if defined(NETSCAPE_SSL)
432  sslpath = value;
433  if (port == LDAP_PORT)
434  port = LDAPS_PORT;
435 #else
436  fprintf(stderr, PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n");
437  exit(EXIT_FAILURE);
438 #endif
439  break;
440  case 'c':
441  connect_timeout = atoi(value);
442  break;
443  case 't':
444  timelimit = atoi(value);
445  break;
446  case 'a':
447  if (strcmp(value, "never") == 0)
448  aliasderef = LDAP_DEREF_NEVER;
449  else if (strcmp(value, "always") == 0)
450  aliasderef = LDAP_DEREF_ALWAYS;
451  else if (strcmp(value, "search") == 0)
452  aliasderef = LDAP_DEREF_SEARCHING;
453  else if (strcmp(value, "find") == 0)
454  aliasderef = LDAP_DEREF_FINDING;
455  else {
456  fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown alias dereference method '%s'\n", value);
457  exit(EXIT_FAILURE);
458  }
459  break;
460  case 'D':
461  binddn = value;
462  break;
463  case 'w':
464  bindpasswd = value;
465  break;
466  case 'W':
467  readSecret(value);
468  break;
469  case 'P':
471  break;
472  case 'O':
473  bind_once = !bind_once;
474  break;
475  case 'p':
476  port = atoi(value);
477  break;
478  case 'R':
480  break;
481 #ifdef LDAP_VERSION3
482  case 'v':
483  switch (atoi(value)) {
484  case 2:
485  version = LDAP_VERSION2;
486  break;
487  case 3:
488  version = LDAP_VERSION3;
489  break;
490  default:
491  fprintf(stderr, "Protocol version should be 2 or 3\n");
492  exit(EXIT_FAILURE);
493  }
494  break;
495  case 'Z':
496  if (version == LDAP_VERSION2) {
497  fprintf(stderr, "TLS (-Z) is incompatible with version %d\n",
498  version);
499  exit(EXIT_FAILURE);
500  }
501  version = LDAP_VERSION3;
502  use_tls = 1;
503  break;
504 #endif
505  case 'd':
506  debug_enabled = 1;
507  break;
508  default:
509  fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown command line option '%c'\n", option);
510  exit(EXIT_FAILURE);
511  }
512  }
513 
514  while (argc > 1) {
515  char *value = argv[1];
516  if (ldapServer) {
517  int len = strlen(ldapServer) + 1 + strlen(value) + 1;
518  char *newhost = static_cast<char*>(xmalloc(len));
519  snprintf(newhost, len, "%s %s", ldapServer, value);
520  free(ldapServer);
521  ldapServer = newhost;
522  } else {
523  ldapServer = xstrdup(value);
524  }
525  --argc;
526  ++argv;
527  }
528  if (!ldapServer)
529  ldapServer = xstrdup("localhost");
530 
531  if (!basedn) {
532  fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn [options] [ldap_server_name[:port]]...\n\n");
533  fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under which to search\n");
534  fprintf(stderr, "\t-f filter\t\tsearch filter to locate user DN\n");
535  fprintf(stderr, "\t-u userattr\t\tusername DN attribute\n");
536  fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n");
537  fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n");
538  fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n");
539  fprintf(stderr, "\t-W secretfile\t\tread password for binddn from file secretfile\n");
540 #if HAS_URI_SUPPORT
541  fprintf(stderr, "\t-H URI\t\t\tLDAPURI (defaults to ldap://localhost)\n");
542 #endif
543  fprintf(stderr, "\t-h server\t\tLDAP server (defaults to localhost)\n");
544  fprintf(stderr, "\t-p port\t\t\tLDAP server port\n");
545  fprintf(stderr, "\t-P\t\t\tpersistent LDAP connection\n");
546 #if defined(NETSCAPE_SSL)
547  fprintf(stderr, "\t-E sslcertpath\t\tenable LDAP over SSL\n");
548 #endif
549  fprintf(stderr, "\t-c timeout\t\tconnect timeout\n");
550  fprintf(stderr, "\t-t timelimit\t\tsearch time limit\n");
551  fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n");
552  fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n");
553 #ifdef LDAP_VERSION3
554  fprintf(stderr, "\t-v 2|3\t\t\tLDAP version\n");
555  fprintf(stderr, "\t-Z\t\t\tTLS encrypt the LDAP connection, requires LDAP version 3\n");
556 #endif
557  fprintf(stderr, "\t-d\t\t\tenable debug mode\n");
558  fprintf(stderr, "\n");
559  fprintf(stderr, "\tIf no search filter is specified, then the dn <userattr>=user,basedn\n\twill be used (same as specifying a search filter of '<userattr>=',\n\tbut quicker as as there is no need to search for the user DN)\n\n");
560  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");
561  exit(EXIT_FAILURE);
562  }
563  /* On Windows ldap_start_tls_s is available starting from Windows XP,
564  * so we need to bind at run-time with the function entry point
565  */
566 #if _SQUID_WINDOWS_
567  if (use_tls) {
568 
569  HMODULE WLDAP32Handle;
570 
571  WLDAP32Handle = GetModuleHandle("wldap32");
572  if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) {
573  fprintf(stderr, PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n");
574  exit(EXIT_FAILURE);
575  }
576  }
577 #endif
578 
579  while (fgets(buf, sizeof(buf), stdin) != NULL) {
580  user = strtok(buf, " \r\n");
581  passwd = strtok(NULL, "\r\n");
582 
583  if (!user) {
584  SEND_ERR(HLP_MSG("Missing username"));
585  continue;
586  }
587  if (!passwd || !passwd[0]) {
588  SEND_ERR(HLP_MSG("Missing password"));
589  continue;
590  }
591  rfc1738_unescape(user);
592  rfc1738_unescape(passwd);
593  if (!validUsername(user)) {
594  SEND_ERR(HLP_MSG("Invalid username"));
595  continue;
596  }
597  tryagain = (ld != NULL);
598 recover:
599  if (ld == NULL && persistent)
600  ld = open_ldap_connection(ldapServer, port);
601  if (checkLDAP(ld, user, passwd, ldapServer, port) != 0) {
602  const auto e = squid_ldap_errno(ld);
603  if (tryagain && e != LDAP_INVALID_CREDENTIALS) {
604  tryagain = 0;
605  ldap_unbind(ld);
606  ld = NULL;
607  goto recover;
608  }
609  if (LDAP_SECURITY_ERROR(e))
610  SEND_ERR(ldap_err2string(e));
611  else
612  SEND_BH(ldap_err2string(e));
613  } else {
614  SEND_OK("");
615  }
616  if (ld && (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) {
617  ldap_unbind(ld);
618  ld = NULL;
619  }
620  }
621  if (ld)
622  ldap_unbind(ld);
623  return EXIT_SUCCESS;
624 }
625 
626 static int
627 ldap_escape_value(char *escaped, int size, const char *src)
628 {
629  int n = 0;
630  while (size > 4 && *src) {
631  switch (*src) {
632  case '*':
633  case '(':
634  case ')':
635  case '\\':
636  n += 3;
637  size -= 3;
638  if (size > 0) {
639  *escaped = '\\';
640  ++escaped;
641  snprintf(escaped, 3, "%02x", (unsigned char) *src);
642  ++src;
643  escaped += 2;
644  }
645  break;
646  default:
647  *escaped = *src;
648  ++escaped;
649  ++src;
650  ++n;
651  --size;
652  }
653  }
654  *escaped = '\0';
655  return n;
656 }
657 
658 /* Check the userid & password.
659  * Return 0 on success, 1 on failure
660  */
661 static int
662 checkLDAP(LDAP * persistent_ld, const char *userid, const char *password, const char *ldapServer, int port)
663 {
664  char dn[1024];
665  int ret = 0;
666  LDAP *bind_ld = NULL;
667 
668  if (!*password) {
669  /* LDAP can't bind with a blank password. Seen as "anonymous"
670  * and always granted access
671  */
672  debug("Blank password given\n");
673  return 1;
674  }
675  if (searchfilter) {
676  char filter[16384];
677  char escaped_login[1024];
678  LDAPMessage *res = NULL;
679  LDAPMessage *entry;
680  char *searchattr[] = {(char *)LDAP_NO_ATTRS, NULL};
681  char *userdn;
682  int rc;
683  LDAP *search_ld = persistent_ld;
684 
685  if (!search_ld)
686  search_ld = open_ldap_connection(ldapServer, port);
687 
688  ldap_escape_value(escaped_login, sizeof(escaped_login), userid);
689  if (binddn) {
690  rc = ldap_simple_bind_s(search_ld, binddn, bindpasswd);
691  if (rc != LDAP_SUCCESS) {
692  fprintf(stderr, PROGRAM_NAME ": WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc));
693  ret = 1;
694  goto search_done;
695  }
696  }
697  snprintf(filter, sizeof(filter), searchfilter, 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);
698  debug("user filter '%s', searchbase '%s'\n", filter, basedn);
699  rc = ldap_search_s(search_ld, basedn, searchscope, filter, searchattr, 1, &res);
700  if (rc != LDAP_SUCCESS) {
701  if (noreferrals && rc == LDAP_PARTIAL_RESULTS) {
702  /* Everything is fine. This is expected when referrals
703  * are disabled.
704  */
705  debug("noreferrals && rc == LDAP_PARTIAL_RESULTS\n");
706  } else {
707  fprintf(stderr, PROGRAM_NAME ": WARNING, LDAP search error '%s'\n", ldap_err2string(rc));
708 #if defined(NETSCAPE_SSL)
709  if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
710  int sslerr = PORT_GetError();
711  fprintf(stderr, PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
712  }
713 #endif
714  ret = 1;
715  goto search_done;
716  }
717  }
718  entry = ldap_first_entry(search_ld, res);
719  if (!entry) {
720  debug("Ldap search returned nothing\n");
721  ret = 1;
722  goto search_done;
723  }
724  userdn = ldap_get_dn(search_ld, entry);
725  if (!userdn) {
726  fprintf(stderr, PROGRAM_NAME ": ERROR, could not get user DN for '%s'\n", userid);
727  ret = 1;
728  goto search_done;
729  }
730  snprintf(dn, sizeof(dn), "%s", userdn);
731  squid_ldap_memfree(userdn);
732 
733  if (ret == 0 && (!binddn || !bind_once || passwdattr)) {
734  /* Reuse the search connection for comparing the user password attribute */
735  bind_ld = search_ld;
736  search_ld = NULL;
737  }
738 search_done:
739  if (res) {
740  ldap_msgfree(res);
741  res = NULL;
742  }
743  if (search_ld && search_ld != persistent_ld) {
744  ldap_unbind(search_ld);
745  search_ld = NULL;
746  }
747  if (ret != 0)
748  return ret;
749  } else {
750  snprintf(dn, sizeof(dn), "%s=%s,%s", userattr, userid, basedn);
751  }
752 
753  debug("attempting to authenticate user '%s'\n", dn);
754  if (!bind_ld && !bind_once)
755  bind_ld = persistent_ld;
756  if (!bind_ld)
757  bind_ld = open_ldap_connection(ldapServer, port);
758  if (passwdattr) {
759  if (ldap_compare_s(bind_ld, dn, passwdattr, password) != LDAP_COMPARE_TRUE) {
760  ret = 1;
761  }
762  } else if (ldap_simple_bind_s(bind_ld, dn, password) != LDAP_SUCCESS)
763  ret = 1;
764  if (bind_ld != persistent_ld) {
765  ldap_unbind(bind_ld);
766  bind_ld = NULL;
767  }
768  return ret;
769 }
770 
771 int
772 readSecret(const char *filename)
773 {
774  char buf[BUFSIZ];
775  char *e = NULL;
776  FILE *f;
777  char *passwd = NULL;
778 
779  if (!(f = fopen(filename, "r"))) {
780  fprintf(stderr, PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename);
781  return 1;
782  }
783  if (!fgets(buf, sizeof(buf) - 1, f)) {
784  fprintf(stderr, PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename);
785  fclose(f);
786  return 1;
787  }
788  /* strip whitespaces on end */
789  if ((e = strrchr(buf, '\n')))
790  *e = 0;
791  if ((e = strrchr(buf, '\r')))
792  *e = 0;
793 
794  passwd = (char *) calloc(sizeof(char), strlen(buf) + 1);
795  if (!passwd) {
796  fprintf(stderr, PROGRAM_NAME " ERROR: can not allocate memory\n");
797  exit(EXIT_FAILURE);
798  }
799  strcpy(passwd, buf);
800  bindpasswd = passwd;
801 
802  fclose(f);
803 
804  return 0;
805 }
806 
static LDAP * open_ldap_connection(const char *ldapServer, int port)
static LDAP * ld
Definition: ldap_backend.cc:56
#define LDAP_NO_ATTRS
int debug_enabled
Definition: debug.cc:13
#define xstrdup
static int version
static int use_tls
static int timelimit
#define xisspace(x)
Definition: xis.h:17
static void squid_ldap_set_connect_timeout(LDAP *ld, int timelimit)
char * p
Definition: membanger.c:43
static int connect_timeout
static int squid_ldap_errno(LDAP *ld)
#define SEND_OK(x)
static int ldap_escape_value(char *escaped, int size, const char *src)
#define HLP_MSG(text)
static void squid_ldap_set_referrals(LDAP *ld, int referrals)
static int searchscope
static int checkLDAP(LDAP *ld, const char *userid, const char *password, const char *server, int port)
static const char * bindpasswd
static const char * userattr
int main(int argc, char **argv)
static void squid_ldap_set_timelimit(LDAP *ld, int timelimit)
static int debug
Definition: tcp-banger3.c:105
static int readSecret(const char *filename)
static int port
Definition: ldap_backend.cc:69
static const char * binddn
#define BUFSIZ
Definition: defines.h:20
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void const char * buf
Definition: stub_helper.cc:16
static void squid_ldap_set_aliasderef(LDAP *ld, int deref)
static int noreferrals
#define xmalloc
static char server[MAXLINE]
#define SEND_BH(x)
static int validUsername(const char *user)
void rfc1738_unescape(char *url)
Definition: rfc1738.c:146
static int persistent
static const char * basedn
static const char * passwdattr
static char * ldapServer
Definition: ldap_backend.cc:58
static int bind_once
unsigned int ULONG
Definition: smblib-priv.h:147
static const char * searchfilter
#define SEND_ERR(x)
#define NULL
Definition: types.h:166
int size
Definition: ModDevPoll.cc:77
#define PROGRAM_NAME
static void squid_ldap_memfree(char *p)
static int aliasderef
#define free(a)
Definition: hash.c:31

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors