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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors