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