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