]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/external_acl/kerberos_ldap_group/support_ldap.cc
Use IPv6 localhost nameserver on DNS configuration errors
[thirdparty/squid.git] / helpers / external_acl / kerberos_ldap_group / support_ldap.cc
CommitLineData
b1218840
AJ
1/*
2 * -----------------------------------------------------------------------------
3 *
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
5 *
6 * Copyright (C) 2007 Markus Moeller. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * -----------------------------------------------------------------------------
23 */
24
f7f3304a 25#include "squid.h"
b1218840
AJ
26#include "util.h"
27
28#ifdef HAVE_LDAP
29
30#include "support.h"
31#ifdef HAVE_ERRNO_H
32#include <errno.h>
33#endif
34
35char *convert_domain_to_bind_path(char *domain);
36char *escape_filter(char *filter);
37int check_AD(struct main_args *margs, LDAP * ld);
38int ldap_set_defaults(struct main_args *margs, LDAP * ld);
39int ldap_set_ssl_defaults(struct main_args *margs);
40LDAP *tool_ldap_open(struct main_args *margs, char *host, int port, char *ssl);
41
42#define CONNECT_TIMEOUT 2
43#define SEARCH_TIMEOUT 30
44
45#define FILTER "(memberuid=%s)"
46#define ATTRIBUTE "cn"
47#define FILTER_UID "(uid=%s)"
48#define FILTER_GID "(&(gidNumber=%s)(objectclass=posixgroup))"
49#define ATTRIBUTE_GID "gidNumber"
50
51#define FILTER_AD "(samaccountname=%s)"
52#define ATTRIBUTE_AD "memberof"
53
54int get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute /* IN */ , char ***out_val /* OUT (caller frees) */ );
55int search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth);
56
57#if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
58#ifdef HAVE_LDAP_REBINDPROC_CALLBACK
59
60#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
61static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
62
63static int LDAP_CALL LDAP_CALLBACK
64ldap_sasl_rebind(
65 LDAP * ld,
66 char **whop,
67 char **credp,
68 int *methodp,
69 int freeit,
70 void *params)
71{
72 struct ldap_creds *cp = (struct ldap_creds *) params;
73 whop = whop;
74 credp = credp;
75 methodp = methodp;
76 freeit = freeit;
77 return tool_sasl_bind(ld, cp->dn, cp->pw);
78}
79#endif
80
81static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
82
83static int LDAP_CALL LDAP_CALLBACK
84ldap_simple_rebind(
85 LDAP * ld,
86 char **whop,
87 char **credp,
88 int *methodp,
89 int freeit,
90 void *params)
91{
92 struct ldap_creds *cp = (struct ldap_creds *) params;
93 whop = whop;
94 credp = credp;
95 methodp = methodp;
96 freeit = freeit;
97 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
98}
99#elif defined(HAVE_LDAP_REBIND_PROC)
100#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
101static LDAP_REBIND_PROC ldap_sasl_rebind;
102
103static int
104ldap_sasl_rebind(
105 LDAP * ld,
106 LDAP_CONST char *url,
107 ber_tag_t request,
108 ber_int_t msgid,
109 void *params)
110{
111 struct ldap_creds *cp = (struct ldap_creds *) params;
b1218840
AJ
112 return tool_sasl_bind(ld, cp->dn, cp->pw);
113}
114#endif
115
116static LDAP_REBIND_PROC ldap_simple_rebind;
117
118static int
119ldap_simple_rebind(
120 LDAP * ld,
121 LDAP_CONST char *url,
122 ber_tag_t request,
123 ber_int_t msgid,
124 void *params)
125{
126 struct ldap_creds *cp = (struct ldap_creds *) params;
b1218840
AJ
127 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
128}
129
130#elif defined(HAVE_LDAP_REBIND_FUNCTION)
131#ifndef LDAP_REFERRALS
132#define LDAP_REFERRALS
133#endif
134#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
135static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
136
137static int
138ldap_sasl_rebind(
139 LDAP * ld,
140 char **whop,
141 char **credp,
142 int *methodp,
143 int freeit,
144 void *params)
145{
146 struct ldap_creds *cp = (struct ldap_creds *) params;
147 whop = whop;
148 credp = credp;
149 methodp = methodp;
150 freeit = freeit;
151 return tool_sasl_bind(ld, cp->dn, cp->pw);
152}
153#endif
154
155static LDAP_REBIND_FUNCTION ldap_simple_rebind;
156
157static int
158ldap_simple_rebind(
159 LDAP * ld,
160 char **whop,
161 char **credp,
162 int *methodp,
163 int freeit,
164 void *params)
165{
166 struct ldap_creds *cp = (struct ldap_creds *) params;
167 whop = whop;
168 credp = credp;
169 methodp = methodp;
170 freeit = freeit;
171 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
172}
173#else
174#error "No rebind functione defined"
175#endif
176#else /* HAVE_SUN_LDAP_SDK */
177#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
178static LDAP_REBIND_PROC ldap_sasl_rebind;
179
180static int
181ldap_sasl_rebind(
182 LDAP * ld,
183 LDAP_CONST char *url,
184 ber_tag_t request,
185 ber_int_t msgid,
186 void *params)
187{
188 struct ldap_creds *cp = (struct ldap_creds *) params;
b1218840
AJ
189 return tool_sasl_bind(ld, cp->dn, cp->pw);
190}
191#endif
192
193static LDAP_REBIND_PROC ldap_simple_rebind;
194
195static int
196ldap_simple_rebind(
197 LDAP * ld,
198 LDAP_CONST char *url,
199 ber_tag_t request,
200 ber_int_t msgid,
201 void *params)
202{
203
204 struct ldap_creds *cp = (struct ldap_creds *) params;
b1218840
AJ
205 return ldap_bind_s(ld, cp->dn, cp->pw, LDAP_AUTH_SIMPLE);
206}
207
208#endif
209char *
210convert_domain_to_bind_path(char *domain)
211{
212 char *dp, *bindp = NULL, *bp = NULL;
213 int i = 0;
214
215 if (!domain)
2e881a6f 216 return NULL;
b1218840 217
a2f5277a 218 for (dp = domain; *dp; ++dp) {
2e881a6f 219 if (*dp == '.')
755494da 220 ++i;
b1218840 221 }
2e881a6f
A
222 /*
223 * add dc= and
224 * replace . with ,dc= => new length = old length + #dots * 3 + 3
b1218840
AJ
225 */
226 bindp = (char *) xmalloc(strlen(domain) + 3 + i * 3 + 1);
227 bp = bindp;
228 strcpy(bp, "dc=");
229 bp += 3;
a2f5277a 230 for (dp = domain; *dp; ++dp) {
2e881a6f
A
231 if (*dp == '.') {
232 strcpy(bp, ",dc=");
233 bp += 4;
f207fe64
FC
234 } else {
235 *bp = *dp;
236 ++bp;
237 }
b1218840
AJ
238 }
239 *bp = '\0';
240 return bindp;
241}
242
243char *
244escape_filter(char *filter)
245{
246 int i;
247 char *ldap_filter_esc, *ldf;
248
249 i = 0;
a2f5277a 250 for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
2e881a6f
A
251 if ((*ldap_filter_esc == '*') ||
252 (*ldap_filter_esc == '(') ||
253 (*ldap_filter_esc == ')') ||
254 (*ldap_filter_esc == '\\'))
255 i = i + 3;
b1218840
AJ
256 }
257
258 ldap_filter_esc = (char *) xcalloc(strlen(filter) + i + 1, sizeof(char));
259 ldf = ldap_filter_esc;
a2f5277a 260 for (; *filter; ++filter) {
2e881a6f
A
261 if (*filter == '*') {
262 strcpy(ldf, "\\2a");
263 ldf = ldf + 3;
264 } else if (*filter == '(') {
265 strcpy(ldf, "\\28");
266 ldf = ldf + 3;
267 } else if (*filter == ')') {
268 strcpy(ldf, "\\29");
269 ldf = ldf + 3;
270 } else if (*filter == '\\') {
271 strcpy(ldf, "\\5c");
272 ldf = ldf + 3;
273 } else {
274 *ldf = *filter;
755494da 275 ++ldf;
2e881a6f 276 }
b1218840
AJ
277 }
278 *ldf = '\0';
279
280 return ldap_filter_esc;
281};
282
283int
284check_AD(struct main_args *margs, LDAP * ld)
285{
286 LDAPMessage *res;
287 char **attr_value = NULL;
288 struct timeval searchtime;
289 int max_attr = 0;
290 int j, rc = 0;
291
292#define FILTER_SCHEMA "(objectclass=*)"
293#define ATTRIBUTE_SCHEMA "schemaNamingContext"
294#define FILTER_SAM "(ldapdisplayname=samaccountname)"
295
296 searchtime.tv_sec = SEARCH_TIMEOUT;
297 searchtime.tv_usec = 0;
298
299 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n", LogTime(), PROGRAM, FILTER_SCHEMA);
300 rc = ldap_search_ext_s(ld, (char *) "", LDAP_SCOPE_BASE, (char *) FILTER_SCHEMA, NULL, 0,
2e881a6f 301 NULL, NULL, &searchtime, 0, &res);
b1218840
AJ
302
303 if (rc == LDAP_SUCCESS)
2e881a6f 304 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_SCHEMA, &attr_value);
b1218840
AJ
305
306 if (max_attr == 1) {
2e881a6f
A
307 ldap_msgfree(res);
308 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, attr_value[0], FILTER_SAM);
309 rc = ldap_search_ext_s(ld, attr_value[0], LDAP_SCOPE_SUBTREE, (char *) FILTER_SAM, NULL, 0,
310 NULL, NULL, &searchtime, 0, &res);
311 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
312 if (ldap_count_entries(ld, res) > 0)
313 margs->AD = 1;
b1218840 314 } else
2e881a6f 315 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n", LogTime(), PROGRAM);
b1218840
AJ
316 debug((char *) "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n", LogTime(), PROGRAM, margs->AD ? "" : "not ");
317 /*
318 * Cleanup
319 */
320 if (attr_value) {
a2f5277a 321 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
322 xfree(attr_value[j]);
323 }
324 xfree(attr_value);
325 attr_value = NULL;
b1218840
AJ
326 }
327 ldap_msgfree(res);
328 return rc;
329}
330int
331search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_group, char *group, int depth)
332{
333 LDAPMessage *res = NULL;
334 char **attr_value = NULL;
335 int max_attr = 0;
336 char *filter = NULL;
337 char *search_exp = NULL;
338 int j, rc = 0, retval = 0;
339 char *av = NULL, *avp = NULL;
340 int ldepth;
341 char *ldap_filter_esc = NULL;
342 struct timeval searchtime;
343
344#define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
345#define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
346
347 searchtime.tv_sec = SEARCH_TIMEOUT;
348 searchtime.tv_usec = 0;
349
350 if (margs->AD)
2e881a6f 351 filter = (char *) FILTER_GROUP_AD;
b1218840 352 else
2e881a6f 353 filter = (char *) FILTER_GROUP;
b1218840
AJ
354
355 ldap_filter_esc = escape_filter(ldap_group);
356
357 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
358 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
359
4ad7aabf 360 xfree(ldap_filter_esc);
b1218840
AJ
361
362 if (depth > margs->mdepth) {
2e881a6f 363 debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
4ad7aabf 364 xfree(search_exp);
2e881a6f 365 return 0;
b1218840
AJ
366 }
367 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
368 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
2e881a6f
A
369 search_exp, NULL, 0,
370 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 371 xfree(search_exp);
b1218840
AJ
372
373 if (rc != LDAP_SUCCESS) {
2e881a6f
A
374 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
375 ldap_unbind_s(ld);
376 return 0;
b1218840
AJ
377 }
378 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
379
380 if (margs->AD)
2e881a6f 381 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
b1218840 382 else
2e881a6f 383 max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
b1218840
AJ
384
385 /*
386 * Compare group names
387 */
388 retval = 0;
389 ldepth = depth + 1;
a2f5277a 390 for (j = 0; j < max_attr; ++j) {
b1218840 391
2e881a6f
A
392 /* Compare first CN= value assuming it is the same as the group name itself */
393 av = attr_value[j];
394 if (!strncasecmp("CN=", av, 3)) {
395 av += 3;
396 if ((avp = strchr(av, ','))) {
397 *avp = '\0';
398 }
399 }
400 if (debug_enabled) {
401 int n;
402 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
a2f5277a 403 for (n = 0; av[n] != '\0'; ++n)
2e881a6f
A
404 fprintf(stderr, "%02x", (unsigned char) av[n]);
405 fprintf(stderr, "\n");
406 }
407 if (!strcasecmp(group, av)) {
408 retval = 1;
409 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
410 break;
411 } else
412 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
413 /*
414 * Do recursive group search
415 */
416 debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM, av);
417 av = attr_value[j];
418 if (search_group_tree(margs, ld, bindp, av, group, ldepth)) {
419 retval = 1;
420 if (!strncasecmp("CN=", av, 3)) {
421 av += 3;
422 if ((avp = strchr(av, ','))) {
423 *avp = '\0';
424 }
425 }
426 if (debug_enabled)
427 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
428 else
429 break;
430
431 }
b1218840
AJ
432 }
433
434 /*
435 * Cleanup
436 */
437 if (attr_value) {
a2f5277a 438 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
439 xfree(attr_value[j]);
440 }
441 xfree(attr_value);
442 attr_value = NULL;
b1218840
AJ
443 }
444 ldap_msgfree(res);
445
446 return retval;
447}
448
449int
450ldap_set_defaults(struct main_args *margs, LDAP * ld)
451{
452 int val, rc = 0;
453#ifdef LDAP_OPT_NETWORK_TIMEOUT
454 struct timeval tv;
455#endif
456 val = LDAP_VERSION3;
457 rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &val);
458 if (rc != LDAP_SUCCESS) {
2e881a6f
A
459 debug((char *) "%s| %s: DEBUG: Error while setting protocol version: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
460 return rc;
b1218840
AJ
461 }
462 rc = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
463 if (rc != LDAP_SUCCESS) {
2e881a6f
A
464 debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
465 return rc;
b1218840
AJ
466 }
467#ifdef LDAP_OPT_NETWORK_TIMEOUT
468 tv.tv_sec = CONNECT_TIMEOUT;
469 tv.tv_usec = 0;
470 rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
471 if (rc != LDAP_SUCCESS) {
2e881a6f
A
472 debug((char *) "%s| %s: DEBUG: Error while setting network timeout: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
473 return rc;
b1218840
AJ
474 }
475#endif /* LDAP_OPT_NETWORK_TIMEOUT */
476 return LDAP_SUCCESS;
477}
478
479int
480ldap_set_ssl_defaults(struct main_args *margs)
481{
482#if defined(HAVE_OPENLDAP) || defined(HAVE_LDAPSSL_CLIENT_INIT)
483 int rc = 0;
484#endif
485#ifdef HAVE_OPENLDAP
486 int val;
487 char *ssl_cacertfile = NULL;
488 int free_path;
489#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
490 char *ssl_certdbpath = NULL;
491#endif
492
493#ifdef HAVE_OPENLDAP
494 if (!margs->rc_allow) {
2e881a6f
A
495 debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM);
496 val = LDAP_OPT_X_TLS_DEMAND;
497 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
498 if (rc != LDAP_SUCCESS) {
499 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
500 return rc;
501 }
502 ssl_cacertfile = getenv("TLS_CACERTFILE");
503 free_path = 0;
504 if (!ssl_cacertfile) {
505 ssl_cacertfile = xstrdup("/etc/ssl/certs/cert.pem");
506 free_path = 1;
507 }
508 debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM, ssl_cacertfile);
509 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ssl_cacertfile);
510 if (ssl_cacertfile && free_path) {
511 xfree(ssl_cacertfile);
512 ssl_cacertfile = NULL;
513 }
514 if (rc != LDAP_OPT_SUCCESS) {
515 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
516 return rc;
517 }
b1218840 518 } else {
2e881a6f
A
519 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
520 val = LDAP_OPT_X_TLS_ALLOW;
521 rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
522 if (rc != LDAP_SUCCESS) {
523 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
524 return rc;
525 }
b1218840
AJ
526 }
527#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
2e881a6f 528 /*
b1218840
AJ
529 * Solaris SSL ldap calls require path to certificate database
530 */
2e881a6f
A
531 /*
532 * rc = ldapssl_client_init( ssl_certdbpath, NULL );
533 * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
534 */
b1218840
AJ
535 ssl_certdbpath = getenv("SSL_CERTDBPATH");
536 if (!ssl_certdbpath) {
2e881a6f 537 ssl_certdbpath = xstrdup("/etc/certs");
b1218840
AJ
538 }
539 debug((char *) "%s| %s: DEBUG: Set certificate database path for ldap server to %s.(Changeable through setting environment variable SSL_CERTDBPATH)\n", LogTime(), PROGRAM, ssl_certdbpath);
540 if (!margs->rc_allow) {
2e881a6f 541 rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 2);
b1218840 542 } else {
2e881a6f
A
543 rc = ldapssl_advclientauth_init(ssl_certdbpath, NULL, 0, NULL, NULL, 0, NULL, 0);
544 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM);
b1218840
AJ
545 }
546 if (ssl_certdbpath) {
2e881a6f
A
547 xfree(ssl_certdbpath);
548 ssl_certdbpath = NULL;
b1218840
AJ
549 }
550 if (rc != LDAP_SUCCESS) {
2e881a6f
A
551 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
552 return rc;
b1218840
AJ
553 }
554#else
555 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
556#endif
557 return LDAP_SUCCESS;
558}
559
560int
561get_attributes(struct main_args *margs, LDAP * ld, LDAPMessage * res, const char *attribute, char ***ret_value)
562{
563
564 LDAPMessage *msg;
565 char **attr_value = NULL;
566 int max_attr = 0;
567
568 attr_value = *ret_value;
569 /*
570 * loop over attributes
571 */
572 debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM, attribute);
573 for (msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) {
574
2e881a6f
A
575 BerElement *b;
576 char *attr;
577
578 switch (ldap_msgtype(msg)) {
579
580 case LDAP_RES_SEARCH_ENTRY:
581
582 for (attr = ldap_first_attribute(ld, msg, &b); attr;
583 attr = ldap_next_attribute(ld, msg, b)) {
584 if (strcasecmp(attr, attribute) == 0) {
585 struct berval **values;
586 int il;
587
588 if ((values = ldap_get_values_len(ld, msg, attr)) != NULL) {
a2f5277a 589 for (il = 0; values[il] != NULL; ++il) {
2e881a6f
A
590
591 attr_value = (char **) xrealloc(attr_value, (il + 1) * sizeof(char *));
592 if (!attr_value)
593 break;
594
595 attr_value[il] = (char *) xmalloc(values[il]->bv_len + 1);
596 memcpy(attr_value[il], values[il]->bv_val, values[il]->bv_len);
597 attr_value[il][values[il]->bv_len] = 0;
598 }
599 max_attr = il;
600 }
601 ber_bvecfree(values);
602 }
603 ldap_memfree(attr);
604 }
605 ber_free(b, 0);
606 break;
607 case LDAP_RES_SEARCH_REFERENCE:
608 debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM);
609 break;
610 case LDAP_RES_SEARCH_RESULT:
611 debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM);
612 break;
613 default:
614 break;
615 }
b1218840
AJ
616 }
617
618 debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM, max_attr, max_attr > 1 || max_attr == 0 ? "ies" : "y", attribute);
619
620 *ret_value = attr_value;
621 return max_attr;
622}
623
624/*
625 * call to open ldap server with or without SSL
626 */
627LDAP *
628tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
629{
630 LDAP *ld;
631#ifdef HAVE_OPENLDAP
632 LDAPURLDesc *url = NULL;
633 char *ldapuri = NULL;
634#endif
635 int rc = 0;
636
2e881a6f
A
637 /*
638 * Use ldap open here to check if TCP connection is possible. If possible use it.
b1218840
AJ
639 * (Not sure if this is the best way)
640 */
641#ifdef HAVE_OPENLDAP
642 url = (LDAPURLDesc *) xmalloc(sizeof(*url));
643 memset(url, 0, sizeof(*url));
644#ifdef HAVE_LDAP_URL_LUD_SCHEME
645 if (ssl)
2e881a6f 646 url->lud_scheme = (char *) "ldaps";
b1218840 647 else
2e881a6f 648 url->lud_scheme = (char *) "ldap";
b1218840
AJ
649#endif
650 url->lud_host = host;
651 url->lud_port = port;
652#ifdef HAVE_LDAP_SCOPE_DEFAULT
653 url->lud_scope = LDAP_SCOPE_DEFAULT;
654#else
655 url->lud_scope = LDAP_SCOPE_SUBTREE;
656#endif
657#ifdef HAVE_LDAP_URL_DESC2STR
658 ldapuri = ldap_url_desc2str(url);
659#elif defined(HAVE_LDAP_URL_PARSE)
660 rc = ldap_url_parse(ldapuri, &url);
661 if (rc != LDAP_SUCCESS) {
2e881a6f 662 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
b656d212
AJ
663 xfree(ldapuri);
664 xfree(url);
2e881a6f 665 return NULL;
b1218840
AJ
666 }
667#else
668#error "No URL parsing function"
669#endif
b656d212 670 safe_free(url);
b1218840 671 rc = ldap_initialize(&ld, ldapuri);
b656d212 672 xfree(ldapuri);
b1218840 673 if (rc != LDAP_SUCCESS) {
2e881a6f
A
674 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
675 ldap_unbind(ld);
676 ld = NULL;
677 return NULL;
b1218840
AJ
678 }
679#else
680 ld = ldap_init(host, port);
681#endif
682 rc = ldap_set_defaults(margs, ld);
683 if (rc != LDAP_SUCCESS) {
2e881a6f
A
684 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
685 ldap_unbind(ld);
686 ld = NULL;
687 return NULL;
b1218840
AJ
688 }
689 if (ssl) {
2e881a6f
A
690 /*
691 * Try Start TLS first
692 */
693 debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM);
694 rc = ldap_set_ssl_defaults(margs);
695 if (rc != LDAP_SUCCESS) {
696 error((char *) "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
697 ldap_unbind(ld);
698 ld = NULL;
699 return NULL;
700 }
b1218840 701#ifdef HAVE_OPENLDAP
2e881a6f
A
702 /*
703 * Use tls if possible
704 */
705 rc = ldap_start_tls_s(ld, NULL, NULL);
706 if (rc != LDAP_SUCCESS) {
707 error((char *) "%s| %s: ERROR: Error while setting start_tls for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
708 ldap_unbind(ld);
709 ld = NULL;
710 url = (LDAPURLDesc *) xmalloc(sizeof(*url));
711 memset(url, 0, sizeof(*url));
b1218840 712#ifdef HAVE_LDAP_URL_LUD_SCHEME
2e881a6f 713 url->lud_scheme = (char *) "ldaps";
b1218840 714#endif
2e881a6f
A
715 url->lud_host = host;
716 url->lud_port = port;
b1218840 717#ifdef HAVE_LDAP_SCOPE_DEFAULT
2e881a6f 718 url->lud_scope = LDAP_SCOPE_DEFAULT;
b1218840 719#else
2e881a6f 720 url->lud_scope = LDAP_SCOPE_SUBTREE;
b1218840
AJ
721#endif
722#ifdef HAVE_LDAP_URL_DESC2STR
2e881a6f 723 ldapuri = ldap_url_desc2str(url);
b1218840 724#elif defined(HAVE_LDAP_URL_PARSE)
2e881a6f
A
725 rc = ldap_url_parse(ldapuri, &url);
726 if (rc != LDAP_SUCCESS) {
727 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
4ad7aabf
AJ
728 xfree(ldapuri);
729 xfree(url);
2e881a6f
A
730 return NULL;
731 }
b1218840
AJ
732#else
733#error "No URL parsing function"
734#endif
4ad7aabf 735 safe_free(url);
2e881a6f 736 rc = ldap_initialize(&ld, ldapuri);
4ad7aabf 737 xfree(ldapuri);
2e881a6f
A
738 if (rc != LDAP_SUCCESS) {
739 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
740 ldap_unbind(ld);
741 ld = NULL;
742 return NULL;
743 }
744 rc = ldap_set_defaults(margs, ld);
745 if (rc != LDAP_SUCCESS) {
746 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
747 ldap_unbind(ld);
748 ld = NULL;
749 return NULL;
750 }
751 }
b1218840 752#elif defined(HAVE_LDAPSSL_CLIENT_INIT)
2e881a6f
A
753 ld = ldapssl_init(host, port, 1);
754 if (!ld) {
755 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM, ldapssl_err2string(rc));
756 ldap_unbind(ld);
757 ld = NULL;
758 return NULL;
759 }
760 rc = ldap_set_defaults(margs, ld);
761 if (rc != LDAP_SUCCESS) {
762 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
763 ldap_unbind(ld);
764 ld = NULL;
765 return NULL;
766 }
b1218840 767#else
2e881a6f 768 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM);
b1218840
AJ
769#endif
770 }
771 return ld;
772}
773
774/*
775 * ldap calls to get attribute from Ldap Directory Server
776 */
777int
778get_memberof(struct main_args *margs, char *user, char *domain, char *group)
779{
780 LDAP *ld = NULL;
781 LDAPMessage *res;
782#ifndef HAVE_SUN_LDAP_SDK
783 int ldap_debug = 0;
784#endif
785 struct ldap_creds *lcreds = NULL;
786 char *bindp = NULL;
787 char *filter = NULL;
788 char *search_exp;
789 struct timeval searchtime;
790 int i, j, rc = 0, kc = 1;
791 int retval;
792 char **attr_value = NULL;
793 char *av = NULL, *avp = NULL;
794 int max_attr = 0;
795 struct hstruct *hlist = NULL;
796 int nhosts = 0;
797 char *hostname;
798 char *host;
799 int port;
800 char *ssl = NULL;
801 char *p;
802 char *ldap_filter_esc = NULL;
803
b1218840
AJ
804 searchtime.tv_sec = SEARCH_TIMEOUT;
805 searchtime.tv_usec = 0;
806 /*
807 * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
808 */
809 if (domain) {
2e881a6f 810 debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM);
b1218840 811
bec91ba0 812#ifdef HAVE_KRB5
2e881a6f
A
813 kc = krb5_create_cache(margs, domain);
814 if (kc) {
815 error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM);
816 }
bec91ba0
MM
817#else
818 kc = 1;
819 debug((char *) "%s| %s: DEBUG: Kerberos is not supported. Use username/passwaord with ldap url instead\n", LogTime(), PROGRAM);
820#endif
b1218840 821 }
bec91ba0 822
b1218840 823 if (kc && (!margs->lurl || !margs->luser | !margs->lpass)) {
2e881a6f
A
824 /*
825 * If Kerberos fails and no url given exit here
826 */
827 retval = 0;
828 goto cleanup;
b1218840
AJ
829 }
830#ifndef HAVE_SUN_LDAP_SDK
831 /*
832 * Initialise ldap
833 */
834 ldap_debug = 127 /* LDAP_DEBUG_TRACE */ ;
835 ldap_debug = -1 /* LDAP_DEBUG_ANY */ ;
836 ldap_debug = 0;
837 (void) ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
838#endif
839 debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM);
840
841 if (domain && !kc) {
2e881a6f
A
842 if (margs->ssl) {
843 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
844 }
845 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM, domain);
846 /*
847 * Loop over list of ldap servers of users domain
848 */
849 nhosts = get_ldap_hostname_list(margs, &hlist, 0, domain);
a2f5277a 850 for (i = 0; i < nhosts; ++i) {
2e881a6f
A
851 port = 389;
852 if (hlist[i].port != -1)
853 port = hlist[i].port;
854 debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM, hlist[i].host, port);
855
856 ld = tool_ldap_open(margs, hlist[i].host, port, margs->ssl);
857 if (!ld)
858 continue;
859
860 /*
861 * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
862 */
b1218840
AJ
863
864#if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
2e881a6f
A
865 debug((char *) "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n", LogTime(), PROGRAM);
866
867 rc = tool_sasl_bind(ld, bindp, margs->ssl);
868 if (rc != LDAP_SUCCESS) {
869 error((char *) "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
870 ldap_unbind(ld);
871 ld = NULL;
872 continue;
873 }
874 lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
4ad7aabf 875 lcreds->dn = NULL;
2e881a6f
A
876 lcreds->pw = margs->ssl ? xstrdup(margs->ssl) : NULL;
877 ldap_set_rebind_proc(ld, ldap_sasl_rebind, (char *) lcreds);
878 if (ld != NULL) {
879 debug((char *) "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", margs->ssl ? "SSL protected " : "", hlist[i].host, port);
880 break;
881 }
b1218840 882#else
2e881a6f
A
883 ldap_unbind(ld);
884 ld = NULL;
885 error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM);
886 continue;
b1218840 887#endif
2e881a6f
A
888 }
889 nhosts = free_hostname_list(&hlist, nhosts);
890 if (ld == NULL) {
891 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
892 }
893 bindp = convert_domain_to_bind_path(domain);
b1218840
AJ
894 }
895 if ((!domain || !ld) && margs->lurl && strstr(margs->lurl, "://")) {
2e881a6f
A
896 /*
897 * If username does not contain a domain and a url was given then try it
898 */
899 hostname = strstr(margs->lurl, "://") + 3;
900 ssl = strstr(margs->lurl, "ldaps://");
901 if (ssl) {
902 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM);
903 }
904 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM, hostname);
905 /*
906 * Loop over list of ldap servers
907 */
908 host = xstrdup(hostname);
909 port = 389;
910 if ((p = strchr(host, ':'))) {
911 *p = '\0';
755494da 912 ++p;
2e881a6f
A
913 port = atoi(p);
914 }
915 nhosts = get_hostname_list(margs, &hlist, 0, host);
4ad7aabf 916 safe_free(host);
a2f5277a 917 for (i = 0; i < nhosts; ++i) {
2e881a6f
A
918
919 ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
920 if (!ld)
921 continue;
922 /*
923 * ldap bind with username/password authentication
924 */
925
926 debug((char *) "%s| %s: DEBUG: Bind to ldap server with Username/Password\n", LogTime(), PROGRAM);
927 rc = ldap_simple_bind_s(ld, margs->luser, margs->lpass);
928 if (rc != LDAP_SUCCESS) {
929 error((char *) "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
930 ldap_unbind(ld);
931 ld = NULL;
932 continue;
933 }
934 lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
935 lcreds->dn = xstrdup(margs->luser);
936 lcreds->pw = xstrdup(margs->lpass);
937 ldap_set_rebind_proc(ld, ldap_simple_rebind, (char *) lcreds);
938 debug((char *) "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM, ld ? "Successfully" : "Failed to", ssl ? "SSL protected " : "", hlist[i].host, port);
939 break;
940
941 }
942 nhosts = free_hostname_list(&hlist, nhosts);
4ad7aabf 943 xfree(bindp);
2e881a6f
A
944 if (margs->lbind) {
945 bindp = xstrdup(margs->lbind);
946 } else {
947 bindp = convert_domain_to_bind_path(domain);
948 }
b1218840
AJ
949 }
950 if (ld == NULL) {
2e881a6f
A
951 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM, strerror(errno));
952 retval = 0;
953 goto cleanup;
b1218840
AJ
954 }
955 /*
956 * ldap search for user
957 */
2e881a6f 958 /*
b1218840
AJ
959 * Check if server is AD by querying for attribute samaccountname
960 */
961 margs->AD = 0;
962 rc = check_AD(margs, ld);
963 if (rc != LDAP_SUCCESS) {
2e881a6f
A
964 error((char *) "%s| %s: ERROR: Error determining ldap server type: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
965 ldap_unbind(ld);
966 ld = NULL;
967 retval = 0;
968 goto cleanup;
b1218840
AJ
969 }
970 if (margs->AD)
2e881a6f 971 filter = (char *) FILTER_AD;
b1218840 972 else
2e881a6f 973 filter = (char *) FILTER;
b1218840
AJ
974
975 ldap_filter_esc = escape_filter(user);
976
977 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
978 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
979
4ad7aabf 980 xfree(ldap_filter_esc);
b1218840
AJ
981
982 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
983 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
2e881a6f
A
984 search_exp, NULL, 0,
985 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 986 xfree(search_exp);
b1218840
AJ
987
988 if (rc != LDAP_SUCCESS) {
2e881a6f
A
989 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
990 ldap_unbind(ld);
991 ld = NULL;
992 retval = 0;
993 goto cleanup;
b1218840
AJ
994 }
995 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
996
997 if (ldap_count_entries(ld, res) != 0) {
998
2e881a6f
A
999 if (margs->AD)
1000 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_AD, &attr_value);
1001 else {
1002 max_attr = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value);
1003 }
1004
1005 /*
1006 * Compare group names
1007 */
1008 retval = 0;
a2f5277a 1009 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1010
1011 /* Compare first CN= value assuming it is the same as the group name itself */
1012 av = attr_value[j];
1013 if (!strncasecmp("CN=", av, 3)) {
1014 av += 3;
1015 if ((avp = strchr(av, ','))) {
1016 *avp = '\0';
1017 }
1018 }
1019 if (debug_enabled) {
1020 int n;
1021 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM, j + 1, av);
a2f5277a 1022 for (n = 0; av[n] != '\0'; ++n)
2e881a6f
A
1023 fprintf(stderr, "%02x", (unsigned char) av[n]);
1024 fprintf(stderr, "\n");
1025 }
1026 if (!strcasecmp(group, av)) {
1027 retval = 1;
1028 if (debug_enabled)
1029 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1030 else
1031 break;
1032 } else
1033 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1034 }
1035 /*
1036 * Do recursive group search for AD only since posixgroups can not contain other groups
1037 */
1038 if (!retval && margs->AD) {
1039 if (debug_enabled && max_attr > 0) {
1040 debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM);
1041 }
a2f5277a 1042 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1043
1044 av = attr_value[j];
1045 if (search_group_tree(margs, ld, bindp, av, group, 1)) {
1046 retval = 1;
1047 if (!strncasecmp("CN=", av, 3)) {
1048 av += 3;
1049 if ((avp = strchr(av, ','))) {
1050 *avp = '\0';
1051 }
1052 }
1053 if (debug_enabled)
1054 debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM, j + 1, av, group);
1055 else
1056 break;
1057 }
1058 }
1059 }
1060 /*
1061 * Cleanup
1062 */
1063 if (attr_value) {
a2f5277a 1064 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1065 xfree(attr_value[j]);
1066 }
1067 xfree(attr_value);
1068 attr_value = NULL;
1069 }
1070 ldap_msgfree(res);
b1218840 1071 } else if (ldap_count_entries(ld, res) == 0 && margs->AD) {
2e881a6f
A
1072 ldap_msgfree(res);
1073 ldap_unbind(ld);
1074 ld = NULL;
1075 retval = 0;
1076 goto cleanup;
b1218840 1077 } else {
2e881a6f
A
1078 ldap_msgfree(res);
1079 retval = 0;
b1218840
AJ
1080 }
1081
1082 if (!margs->AD && retval == 0) {
2e881a6f
A
1083 /*
1084 * Check for primary Group membership
1085 */
1086 debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM, group);
1087 filter = (char *) FILTER_UID;
1088
1089 ldap_filter_esc = escape_filter(user);
1090
1091 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
1092 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
1093
4ad7aabf 1094 xfree(ldap_filter_esc);
2e881a6f
A
1095
1096 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
1097 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
1098 search_exp, NULL, 0,
1099 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 1100 xfree(search_exp);
2e881a6f
A
1101
1102 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
1103
1104 max_attr = get_attributes(margs, ld, res, ATTRIBUTE_GID, &attr_value);
1105
1106 if (max_attr == 1) {
1107 char **attr_value_2 = NULL;
1108 int max_attr_2 = 0;
1109
1110 ldap_msgfree(res);
1111 filter = (char *) FILTER_GID;
1112
1113 ldap_filter_esc = escape_filter(attr_value[0]);
1114
1115 search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
1116 snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
1117
4ad7aabf 1118 xfree(ldap_filter_esc);
2e881a6f
A
1119
1120 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
1121 rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
1122 search_exp, NULL, 0,
1123 NULL, NULL, &searchtime, 0, &res);
4ad7aabf 1124 xfree(search_exp);
2e881a6f
A
1125
1126 max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
1127 /*
1128 * Compare group names
1129 */
1130 retval = 0;
1131 if (max_attr_2 == 1) {
1132
1133 /* Compare first CN= value assuming it is the same as the group name itself */
1134 av = attr_value_2[0];
1135 if (!strcasecmp(group, av)) {
1136 retval = 1;
1137 debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM, av, group);
1138 } else
1139 debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM, av, group);
1140
1141 }
1142 /*
1143 * Cleanup
1144 */
1145 if (attr_value_2) {
a2f5277a 1146 for (j = 0; j < max_attr_2; ++j) {
2e881a6f
A
1147 xfree(attr_value_2[j]);
1148 }
1149 xfree(attr_value_2);
1150 attr_value_2 = NULL;
1151 }
1152 ldap_msgfree(res);
1153
1154 debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM, retval ? "matches" : "does not match", group);
1155
96072b37 1156 } else {
4f10fd9b 1157 ldap_msgfree(res);
96072b37
AJ
1158 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM, group);
1159 }
2e881a6f
A
1160 /*
1161 * Cleanup
1162 */
1163 if (attr_value) {
a2f5277a 1164 for (j = 0; j < max_attr; ++j) {
2e881a6f
A
1165 xfree(attr_value[j]);
1166 }
1167 xfree(attr_value);
1168 attr_value = NULL;
1169 }
b1218840
AJ
1170 }
1171 rc = ldap_unbind(ld);
1172 ld = NULL;
1173 if (rc != LDAP_SUCCESS) {
2e881a6f 1174 error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
b1218840
AJ
1175 }
1176 debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM);
2e881a6f 1177cleanup:
bec91ba0 1178#ifdef HAVE_KRB5
b1218840 1179 if (domain)
2e881a6f 1180 krb5_cleanup();
bec91ba0 1181#endif
b1218840 1182 if (lcreds) {
4ad7aabf
AJ
1183 xfree(lcreds->dn);
1184 xfree(lcreds->pw);
2e881a6f 1185 xfree(lcreds);
b1218840 1186 }
4ad7aabf 1187 xfree(bindp);
b1218840 1188 return (retval);
b1218840
AJ
1189}
1190#endif