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