ext_ldap_group_acl.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 * ext_ldap_group_acl: lookup group membership in LDAP
11 *
12 * Version 2.17
13 *
14 * (C)2002,2003 MARA Systems AB
15 *
16 * License: squid_ldap_group is free software; you can redistribute it
17 * and/or modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2,
19 * or (at your option) any later version.
20 *
21 * Authors:
22 * Flavio Pescuma <flavio@marasystems.com>
23 * Henrik Nordstrom <hno@marasystems.com>
24 * MARA Systems AB, Sweden <http://www.marasystems.com>
25 *
26 * With contributions from others mentioned in the ChangeLog file
27 *
28 * In part based on squid_ldap_auth by Glen Newton and Henrik Nordstrom.
29 *
30 * Latest version of this program can always be found from MARA Systems
31 * at http://marasystems.com/download/LDAP_Group/
32 *
33 * Dependencies: You need to get the OpenLDAP libraries
34 * from http://www.openldap.org or use another compatible
35 * LDAP C-API library.
36 *
37 * If you want to make a TLS enabled connection you will also need the
38 * OpenSSL libraries linked into openldap. See http://www.openssl.org/
39 */
40#include "squid.h"
42#include "rfc1738.h"
43#include "util.h"
44
45#define LDAP_DEPRECATED 1
46
47#include <algorithm>
48#include <cctype>
49#include <cstring>
50#include <iomanip>
51#include <iostream>
52#include <memory>
53#include <sstream>
54
55#if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
56
57#define snprintf _snprintf
58#include <windows.h>
59#include <winldap.h>
60#ifndef LDAPAPI
61#define LDAPAPI __cdecl
62#endif
63#ifdef LDAP_VERSION3
64#ifndef LDAP_OPT_X_TLS
65#define LDAP_OPT_X_TLS 0x6000
66#endif
67/* Some tricks to allow dynamic bind with ldap_start_tls_s entry point at
68 * run time.
69 */
70#undef ldap_start_tls_s
71#if LDAP_UNICODE
72#define LDAP_START_TLS_S "ldap_start_tls_sW"
73typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlW *, IN PLDAPControlW *);
74#else
75#define LDAP_START_TLS_S "ldap_start_tls_sA"
76typedef WINLDAPAPI ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlA *, IN PLDAPControlA *);
77#endif /* LDAP_UNICODE */
78PFldap_start_tls_s Win32_ldap_start_tls_s;
79#define ldap_start_tls_s(l,s,c) Win32_ldap_start_tls_s(l, nullptr, nullptr,s,c)
80#endif /* LDAP_VERSION3 */
81
82#else
83
84#if HAVE_LBER_H
85#include <lber.h>
86#endif
87#if HAVE_LDAP_H
88#include <ldap.h>
89#endif
90
91#endif
92
93#define PROGRAM_NAME "ext_ldap_group_acl"
94#define PROGRAM_VERSION "2.18"
95
96/* Globals */
97
98static const char *basedn = nullptr;
99static const char *searchfilter = nullptr;
100static const char *userbasedn = nullptr;
101static const char *userdnattr = nullptr;
102static const char *usersearchfilter = nullptr;
103static const char *binddn = nullptr;
104static const char *bindpasswd = nullptr;
105static int searchscope = LDAP_SCOPE_SUBTREE;
106static int persistent = 0;
107static int noreferrals = 0;
108static int aliasderef = LDAP_DEREF_NEVER;
109#if defined(NETSCAPE_SSL)
110static char *sslpath = nullptr;
111static int sslinit = 0;
112#endif
113static int connect_timeout = 0;
114static int timelimit = LDAP_NO_LIMIT;
115
116#ifdef LDAP_VERSION3
117/* Added for TLS support and version 3 */
118static int use_tls = 0;
119static int version = -1;
120#endif
121
122static int searchLDAP(LDAP * ld, char *group, char *user, char *extension_dn);
123
124static int readSecret(const char *filename);
125
126/* Yuck.. we need to glue to different versions of the API */
127
128#ifndef LDAP_NO_ATTRS
129#define LDAP_NO_ATTRS "1.1"
130#endif
131
132#if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823
133static int
134squid_ldap_errno(LDAP * ld)
135{
136 int err = 0;
137 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
138 return err;
139}
140static void
141squid_ldap_set_aliasderef(LDAP * ld, int deref)
142{
143 ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
144}
145static void
146squid_ldap_set_referrals(LDAP * ld, int referrals)
147{
148 int *value = static_cast<int*>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF);
149 ldap_set_option(ld, LDAP_OPT_REFERRALS, value);
150}
151static void
152squid_ldap_set_timelimit(LDAP * ld, int aTimeLimit)
153{
154 ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &aTimeLimit);
155}
156static void
157squid_ldap_set_connect_timeout(LDAP * ld, int aTimeLimit)
158{
159#if defined(LDAP_OPT_NETWORK_TIMEOUT)
160 struct timeval tv;
161 tv.tv_sec = aTimeLimit;
162 tv.tv_usec = 0;
163 ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
164#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
165 aTimeLimit *= 1000;
166 ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit);
167#endif
168}
169static void
170squid_ldap_memfree(char *p)
171{
172 ldap_memfree(p);
173}
174
175#else
176static int
178{
179 return ld->ld_errno;
180}
181static void
183{
184 ld->ld_deref = deref;
185}
186static void
187squid_ldap_set_referrals(LDAP * ld, int referrals)
188{
189 if (referrals)
190 ld->ld_options |= ~LDAP_OPT_REFERRALS;
191 else
192 ld->ld_options &= ~LDAP_OPT_REFERRALS;
193}
194static void
196{
197 ld->ld_timelimit = timelimit;
198}
199static void
201{
202 fprintf(stderr, "WARNING: Connect timeouts not supported in your LDAP library\n");
203}
204static void
206{
207 free(p);
208}
209
210#endif
211
212#ifdef LDAP_API_FEATURE_X_OPENLDAP
213#if LDAP_VENDOR_VERSION > 194
214#define HAS_URI_SUPPORT 1
215#endif
216#endif
217
218int
219main(int argc, char **argv)
220{
221 char buf[HELPER_INPUT_BUFFER];
222 char *user, *group, *extension_dn = nullptr;
223 char *ldapServer = nullptr;
224 LDAP *ld = nullptr;
225 int tryagain = 0, rc;
226 int port = LDAP_PORT;
227 int use_extension_dn = 0;
228 int strip_nt_domain = 0;
229 int strip_kerberos_realm = 0;
230
231 setbuf(stdout, nullptr);
232
233 while (argc > 1 && argv[1][0] == '-') {
234 const char *value = "";
235 char option = argv[1][1];
236 switch (option) {
237 case 'P':
238 case 'R':
239 case 'z':
240 case 'Z':
241 case 'd':
242 case 'g':
243 case 'S':
244 case 'K':
245 break;
246 default:
247 if (strlen(argv[1]) > 2) {
248 value = argv[1] + 2;
249 } else if (argc > 2) {
250 value = argv[2];
251 ++argv;
252 --argc;
253 } else
254 value = "";
255 break;
256 }
257 ++argv;
258 --argc;
259 switch (option) {
260 case 'H':
261#if !HAS_URI_SUPPORT
262 fprintf(stderr, "FATAL: Your LDAP library does not have URI support\n");
263 exit(EXIT_FAILURE);
264#endif
265 /* Fall thru to -h */
266 case 'h':
267 if (ldapServer) {
268 int len = strlen(ldapServer) + 1 + strlen(value) + 1;
269 char *newhost = static_cast<char*>(xmalloc(len));
270 snprintf(newhost, len, "%s %s", ldapServer, value);
271 free(ldapServer);
272 ldapServer = newhost;
273 } else {
274 ldapServer = xstrdup(value);
275 }
276 break;
277 case 'b':
278 basedn = value;
279 break;
280 case 'f':
281 searchfilter = value;
282 break;
283 case 'B':
284 userbasedn = value;
285 break;
286 case 'F':
287 usersearchfilter = value;
288 break;
289 case 'u':
290 userdnattr = value;
291 break;
292 case 's':
293 if (strcmp(value, "base") == 0)
294 searchscope = LDAP_SCOPE_BASE;
295 else if (strcmp(value, "one") == 0)
296 searchscope = LDAP_SCOPE_ONELEVEL;
297 else if (strcmp(value, "sub") == 0)
298 searchscope = LDAP_SCOPE_SUBTREE;
299 else {
300 fprintf(stderr, PROGRAM_NAME ": FATAL: Unknown search scope '%s'\n", value);
301 exit(EXIT_FAILURE);
302 }
303 break;
304 case 'E':
305#if defined(NETSCAPE_SSL)
306 sslpath = value;
307 if (port == LDAP_PORT)
308 port = LDAPS_PORT;
309#else
310 fprintf(stderr, PROGRAM_NAME ": FATAL: -E unsupported with this LDAP library\n");
311 exit(EXIT_FAILURE);
312#endif
313 break;
314 case 'c':
315 connect_timeout = atoi(value);
316 break;
317 case 't':
318 timelimit = atoi(value);
319 break;
320 case 'a':
321 if (strcmp(value, "never") == 0)
322 aliasderef = LDAP_DEREF_NEVER;
323 else if (strcmp(value, "always") == 0)
324 aliasderef = LDAP_DEREF_ALWAYS;
325 else if (strcmp(value, "search") == 0)
326 aliasderef = LDAP_DEREF_SEARCHING;
327 else if (strcmp(value, "find") == 0)
328 aliasderef = LDAP_DEREF_FINDING;
329 else {
330 fprintf(stderr, PROGRAM_NAME ": FATAL: Unknown alias dereference method '%s'\n", value);
331 exit(EXIT_FAILURE);
332 }
333 break;
334 case 'D':
335 binddn = value;
336 break;
337 case 'w':
338 bindpasswd = value;
339 break;
340 case 'W':
341 readSecret(value);
342 break;
343 case 'P':
345 break;
346 case 'p':
347 port = atoi(value);
348 break;
349 case 'R':
351 break;
352#ifdef LDAP_VERSION3
353 case 'v':
354 switch (atoi(value)) {
355 case 2:
356 version = LDAP_VERSION2;
357 break;
358 case 3:
359 version = LDAP_VERSION3;
360 break;
361 default:
362 fprintf(stderr, "FATAL: Protocol version should be 2 or 3\n");
363 exit(EXIT_FAILURE);
364 }
365 break;
366 case 'Z':
367 if (version == LDAP_VERSION2) {
368 fprintf(stderr, "FATAL: TLS (-Z) is incompatible with version %d\n",
369 version);
370 exit(EXIT_FAILURE);
371 }
372 version = LDAP_VERSION3;
373 use_tls = 1;
374 break;
375#endif
376 case 'd':
377 debug_enabled = 1;
378 break;
379 case 'g':
380 use_extension_dn = 1;
381 break;
382 case 'S':
383 strip_nt_domain = 1;
384 break;
385 case 'K':
386 strip_kerberos_realm = 1;
387 break;
388 default:
389 fprintf(stderr, PROGRAM_NAME ": FATAL: Unknown command line option '%c'\n", option);
390 exit(EXIT_FAILURE);
391 }
392 }
393
394 while (argc > 1) {
395 char *value = argv[1];
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 --argc;
406 ++argv;
407 }
408
409 if (!ldapServer)
410 ldapServer = (char *) "localhost";
411
412 if (!basedn || !searchfilter) {
413 fprintf(stderr, "\n" PROGRAM_NAME " version " PROGRAM_VERSION "\n\n");
414 fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn -f filter [options] ldap_server_name\n\n");
415 fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under where to search for groups\n");
416 fprintf(stderr, "\t-f filter (REQUIRED)\tgroup search filter pattern. %%u = user,\n\t\t\t\t%%v = group\n");
417 fprintf(stderr, "\t-B basedn (REQUIRED)\tbase dn under where to search for users\n");
418 fprintf(stderr, "\t-F filter (REQUIRED)\tuser search filter pattern. %%s = login\n");
419 fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n");
420 fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n");
421 fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n");
422 fprintf(stderr, "\t-W secretfile\t\tread password for binddn from file secretfile\n");
423#if HAS_URI_SUPPORT
424 fprintf(stderr, "\t-H URI\t\t\tLDAPURI (defaults to ldap://localhost)\n");
425#endif
426 fprintf(stderr, "\t-h server\t\tLDAP server (defaults to localhost)\n");
427 fprintf(stderr, "\t-p port\t\t\tLDAP server port (defaults to %d)\n", LDAP_PORT);
428 fprintf(stderr, "\t-P\t\t\tpersistent LDAP connection\n");
429#if defined(NETSCAPE_SSL)
430 fprintf(stderr, "\t-E sslcertpath\t\tenable LDAP over SSL\n");
431#endif
432 fprintf(stderr, "\t-c timeout\t\tconnect timeout\n");
433 fprintf(stderr, "\t-t timelimit\t\tsearch time limit\n");
434 fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n");
435 fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n");
436#ifdef LDAP_VERSION3
437 fprintf(stderr, "\t-v 2|3\t\t\tLDAP version\n");
438 fprintf(stderr, "\t-Z\t\t\tTLS encrypt the LDAP connection, requires\n\t\t\t\tLDAP version 3\n");
439#endif
440 fprintf(stderr, "\t-g\t\t\tfirst query parameter is base DN extension\n\t\t\t\tfor this query\n");
441 fprintf(stderr, "\t-S\t\t\tStrip NT domain from usernames\n");
442 fprintf(stderr, "\t-K\t\t\tStrip Kerberos realm from usernames\n");
443 fprintf(stderr, "\t-d\t\t\tenable debug mode\n");
444 fprintf(stderr, "\n");
445 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");
446 exit(EXIT_FAILURE);
447 }
448 /* On Windows ldap_start_tls_s is available starting from Windows XP,
449 * so we need to bind at run-time with the function entry point
450 */
451#if _SQUID_WINDOWS_
452 if (use_tls) {
453
454 HMODULE WLDAP32Handle;
455
456 WLDAP32Handle = GetModuleHandle("wldap32");
457 if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) {
458 fprintf(stderr, PROGRAM_NAME ": FATAL: TLS (-Z) not supported on this platform.\n");
459 exit(EXIT_FAILURE);
460 }
461 }
462#endif
463
464 while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != nullptr) {
465 int found = 0;
466 if (!strchr(buf, '\n')) {
467 /* too large message received.. skip and deny */
468 fprintf(stderr, "%s: ERROR: Input Too large: %s\n", argv[0], buf);
469 while (fgets(buf, sizeof(buf), stdin)) {
470 fprintf(stderr, "%s: ERROR: Input Too large..: %s\n", argv[0], buf);
471 if (strchr(buf, '\n') != nullptr)
472 break;
473 }
474 SEND_BH(HLP_MSG("Input too large"));
475 continue;
476 }
477 user = strtok(buf, " \n");
478 if (!user) {
479 debug("%s: Invalid request: No Username given\n", argv[0]);
480 SEND_BH(HLP_MSG("Invalid request. No Username"));
481 continue;
482 }
483 rfc1738_unescape(user);
484 if (strip_nt_domain) {
485 char *u = strrchr(user, '\\');
486 if (!u)
487 u = strrchr(user, '/');
488 if (!u)
489 u = strrchr(user, '+');
490 if (u && u[1])
491 user = u + 1;
492 }
493 if (strip_kerberos_realm) {
494 char *u = strchr(user, '@');
495 if (u != nullptr) {
496 *u = '\0';
497 }
498 }
499 if (use_extension_dn) {
500 extension_dn = strtok(nullptr, " \n");
501 if (!extension_dn) {
502 debug("%s: Invalid request: Extension DN configured, but none sent.\n", argv[0]);
503 SEND_BH(HLP_MSG("Invalid Request. Extension DN required"));
504 continue;
505 }
506 rfc1738_unescape(extension_dn);
507 }
508 const char *broken = nullptr;
509 while (!found && user && (group = strtok(nullptr, " \n")) != nullptr) {
510 rfc1738_unescape(group);
511
512recover:
513 if (ld == nullptr) {
514#if HAS_URI_SUPPORT
515 if (strstr(ldapServer, "://") != nullptr) {
516 rc = ldap_initialize(&ld, ldapServer);
517 if (rc != LDAP_SUCCESS) {
518 broken = HLP_MSG("Unable to connect to LDAP server");
519 fprintf(stderr, "%s: ERROR: Unable to connect to LDAPURI:%s\n", argv[0], ldapServer);
520 break;
521 }
522 } else
523#endif
524#if NETSCAPE_SSL
525 if (sslpath) {
526 if (!sslinit && (ldapssl_client_init(sslpath, nullptr) != LDAP_SUCCESS)) {
527 fprintf(stderr, "FATAL: Unable to initialise SSL with cert path %s\n", sslpath);
528 exit(EXIT_FAILURE);
529 } else {
530 ++sslinit;
531 }
532 if ((ld = ldapssl_init(ldapServer, port, 1)) == NULL) {
533 fprintf(stderr, "FATAL: Unable to connect to SSL LDAP server: %s port:%d\n",
535 exit(EXIT_FAILURE);
536 }
537 } else
538#endif
539 if ((ld = ldap_init(ldapServer, port)) == nullptr) {
540 broken = HLP_MSG("Unable to connect to LDAP server");
541 fprintf(stderr, "ERROR: %s:%s port:%d\n", broken, ldapServer, port);
542 break;
543 }
544 if (connect_timeout)
546
547#ifdef LDAP_VERSION3
548 if (version == -1) {
549 version = LDAP_VERSION3;
550 }
551 if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_SUCCESS) {
552 broken = HLP_MSG("Could not set LDAP_OPT_PROTOCOL_VERSION");
553 fprintf(stderr, "ERROR: %s %d\n", broken, version);
554 ldap_unbind(ld);
555 ld = nullptr;
556 break;
557 }
558 if (use_tls) {
559#ifdef LDAP_OPT_X_TLS
560 if (version != LDAP_VERSION3) {
561 fprintf(stderr, "FATAL: TLS requires LDAP version 3\n");
562 exit(EXIT_FAILURE);
563 } else if (ldap_start_tls_s(ld, nullptr, nullptr) != LDAP_SUCCESS) {
564 broken = HLP_MSG("Could not Activate TLS connection");
565 fprintf(stderr, "ERROR: %s\n", broken);
566 ldap_unbind(ld);
567 ld = nullptr;
568 break;
569 }
570#else
571 fprintf(stderr, "FATAL: TLS not supported with your LDAP library\n");
572 exit(EXIT_FAILURE);
573#endif
574 }
575#endif
579 if (binddn && bindpasswd && *binddn && *bindpasswd) {
580 rc = ldap_simple_bind_s(ld, binddn, bindpasswd);
581 if (rc != LDAP_SUCCESS) {
582 broken = HLP_MSG("could not bind");
583 fprintf(stderr, PROGRAM_NAME ": WARNING: %s to binddn '%s'\n", broken, ldap_err2string(rc));
584 ldap_unbind(ld);
585 ld = nullptr;
586 break;
587 }
588 }
589 debug("Connected OK\n");
590 }
591 int searchResult = searchLDAP(ld, group, user, extension_dn);
592 if (searchResult == 0) {
593 found = 1;
594 break;
595 } else if (searchResult < 0) {
596 if (tryagain) {
597 tryagain = 0;
598 ldap_unbind(ld);
599 ld = nullptr;
600 goto recover;
601 }
602 broken = HLP_MSG("LDAP search error");
603 }
604 }
605 if (found)
606 SEND_OK("");
607 else if (broken)
608 SEND_BH(broken);
609 else {
610 SEND_ERR("");
611 }
612
613 if (ld != nullptr) {
614 if (!persistent || (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) {
615 ldap_unbind(ld);
616 ld = nullptr;
617 } else {
618 tryagain = 1;
619 }
620 }
621 }
622 if (ld)
623 ldap_unbind(ld);
624 return EXIT_SUCCESS;
625}
626
627static std::string
628ldap_escape_value(const std::string &src)
629{
630 std::stringstream str;
631 for (const auto &c : src) {
632 switch (c) {
633 case '*':
634 case '(':
635 case ')':
636 case '\\':
637 str << '\\' << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(c);
638 break;
639 default:
640 str << c;
641 }
642 }
643 return str.str();
644}
645
646static bool
647build_filter(std::string &filter, const char *templ, const char *user, const char *group)
648{
649 std::stringstream str;
650 while (*templ) {
651 switch (*templ) {
652 case '%':
653 ++templ;
654 switch (*templ) {
655 case 'u':
656 case 'v':
657 ++templ;
658 str << ldap_escape_value(user);
659 break;
660 case 'g':
661 case 'a':
662 ++templ;
663 str << ldap_escape_value(group);
664 break;
665 default:
666 fprintf(stderr, "ERROR: Unknown filter template string %%%c\n", *templ);
667 filter = str.str();
668 return false;
669 }
670 break;
671 case '\\':
672 ++templ;
673 if (*templ) {
674 str << *templ;
675 ++templ;
676 }
677 break;
678 default:
679 str << *templ;
680 ++templ;
681 break;
682 }
683 }
684 filter = str.str();
685 return true;
686}
687
688static std::string
689build_searchbase(const char *extension_dn, const char *base_dn)
690{
691 std::stringstream searchBaseStream;
692 if (extension_dn && *extension_dn)
693 searchBaseStream << extension_dn << ",";
694 searchBaseStream << base_dn;
695 return searchBaseStream.str();
696}
697
698static bool ldap_search_ok(const int result)
699{
700 if (result == LDAP_SUCCESS)
701 return true;
702 if (noreferrals && result == LDAP_PARTIAL_RESULTS) {
703 /* Everything is fine. This is expected when referrals
704 * are disabled.
705 */
706 return true;
707 }
708 std::cerr << PROGRAM_NAME << ": WARNING: LDAP search error '" <<
709 ldap_err2string(result) << "'" << std::endl;
710#if defined(NETSCAPE_SSL)
711 if (sslpath && ((result == LDAP_SERVER_DOWN) || (result == LDAP_CONNECT_ERROR))) {
712 int sslerr = PORT_GetError();
713 std::cerr << PROGRAM_NAME << ": WARNING: SSL error " << sslerr << " (" <<
714 ldapssl_err2string(sslerr) << ")" << std::endl;
715 }
716#endif
717 return false;
718}
719
720typedef const std::unique_ptr<LDAPMessage, decltype(&ldap_msgfree)> LdapResult;
721
722static int
723searchLDAPGroup(LDAP * ld, const char *group, const char *member, const char *extension_dn)
724{
725 std::string filter;
726 LDAPMessage *res = nullptr;
727 int rc;
728 char *searchattr[] = {(char *) LDAP_NO_ATTRS, nullptr};
729
730 const std::string searchbase = build_searchbase(extension_dn, basedn);
731 if (!build_filter(filter, searchfilter, member, group)) {
732 std::cerr << PROGRAM_NAME << ": ERROR: Failed to construct LDAP search filter. filter=\"" <<
733 filter.c_str() << "\", user=\"" << member << "\", group=\"" << group << "\"" << std::endl;
734 return -1;
735 }
736 debug("group filter '%s', searchbase '%s'\n", filter.c_str(), searchbase.c_str());
737
738 rc = ldap_search_s(ld, searchbase.c_str(), searchscope, filter.c_str(), searchattr, 1, &res);
739 LdapResult ldapRes(res, ldap_msgfree);
740 if (!ldap_search_ok(rc))
741 return -1;
742
743 return ldap_first_entry(ld, ldapRes.get()) ? 0 : 1;
744}
745
746static void
747formatWithString(std::string &formatted, const std::string &value)
748{
749 size_t start_pos = 0;
750 while ((start_pos = formatted.find("%s", start_pos)) != std::string::npos) {
751 formatted.replace(start_pos, 2, value);
752 start_pos += 2;
753 }
754}
755
756static int
757searchLDAP(LDAP * ld, char *group, char *login, char *extension_dn)
758{
759
760 const char *current_userdn = userbasedn ? userbasedn : basedn;
761 if (usersearchfilter) {
762 LDAPMessage *res = nullptr;
763 LDAPMessage *entry;
764 int rc;
765 char *userdn;
766 char *searchattr[] = {(char *) LDAP_NO_ATTRS, nullptr};
767 const std::string searchbase = build_searchbase(extension_dn, current_userdn);
768 std::string filter(usersearchfilter);
769 const std::string escaped_login = ldap_escape_value(login);
770 formatWithString(filter, escaped_login);
771
772 debug("user filter '%s', searchbase '%s'\n", filter.c_str(), searchbase.c_str());
773 rc = ldap_search_s(ld, searchbase.c_str(), searchscope, filter.c_str(), searchattr, 1, &res);
774 LdapResult ldapRes(res, ldap_msgfree);
775 if (!ldap_search_ok(rc))
776 return -1;
777 entry = ldap_first_entry(ld, ldapRes.get());
778 if (!entry) {
779 std::cerr << PROGRAM_NAME << ": WARNING: User '" << login <<
780 " not found in '" << searchbase.c_str() << "'" << std::endl;
781 return 1;
782 }
783 userdn = ldap_get_dn(ld, entry);
784 rc = searchLDAPGroup(ld, group, userdn, extension_dn);
785 squid_ldap_memfree(userdn);
786 return rc;
787 } else if (userdnattr) {
788 std::stringstream str;
789 str << userdnattr << "=" << login << ", ";
790 if (extension_dn && *extension_dn)
791 str << extension_dn << ", ";
792 str << current_userdn;
793 return searchLDAPGroup(ld, group, str.str().c_str(), extension_dn);
794 } else {
795 return searchLDAPGroup(ld, group, login, extension_dn);
796 }
797}
798
799int
800readSecret(const char *filename)
801{
802 char buf[BUFSIZ];
803 char *e = nullptr;
804 FILE *f;
805
806 if (!(f = fopen(filename, "r"))) {
807 fprintf(stderr, PROGRAM_NAME ": ERROR: Can not read secret file %s\n", filename);
808 return 1;
809 }
810 if (!fgets(buf, sizeof(buf) - 1, f)) {
811 fprintf(stderr, PROGRAM_NAME ": ERROR: Secret file %s is empty\n", filename);
812 fclose(f);
813 return 1;
814 }
815 /* strip whitespaces on end */
816 if ((e = strrchr(buf, '\n')))
817 *e = 0;
818 if ((e = strrchr(buf, '\r')))
819 *e = 0;
820
821 bindpasswd = xstrdup(buf);
822 if (!bindpasswd) {
823 fprintf(stderr, PROGRAM_NAME ": ERROR: can not allocate memory\n");
824 }
825 fclose(f);
826
827 return 0;
828}
829
#define HELPER_INPUT_BUFFER
Definition: UserRequest.cc:24
static int use_tls
static int version
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
static int strip_nt_domain
Definition: ldap_backend.cc:71
#define LDAP_NO_ATTRS
static std::string ldap_escape_value(const std::string &src)
static int searchLDAP(LDAP *ld, char *group, char *user, char *extension_dn)
static int persistent
static int noreferrals
static int readSecret(const char *filename)
#define PROGRAM_VERSION
#define PROGRAM_NAME
int main(int argc, char **argv)
static const char * bindpasswd
static const char * userbasedn
static bool ldap_search_ok(const int result)
static void formatWithString(std::string &formatted, const std::string &value)
static bool build_filter(std::string &filter, const char *templ, const char *user, const char *group)
static const char * usersearchfilter
static void squid_ldap_set_connect_timeout(LDAP *ld, int timelimit)
static const char * binddn
static int searchscope
static void squid_ldap_set_referrals(LDAP *ld, int referrals)
static std::string build_searchbase(const char *extension_dn, const char *base_dn)
const std::unique_ptr< LDAPMessage, decltype(&ldap_msgfree)> LdapResult
static int connect_timeout
static void squid_ldap_set_aliasderef(LDAP *ld, int deref)
static int timelimit
static const char * userdnattr
static const char * searchfilter
static void squid_ldap_memfree(char *p)
static int searchLDAPGroup(LDAP *ld, const char *group, const char *member, const char *extension_dn)
static void squid_ldap_set_timelimit(LDAP *ld, int timelimit)
static const char * basedn
static int squid_ldap_errno(LDAP *ld)
static int aliasderef
#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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors