2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * -----------------------------------------------------------------------------
12 * Author: Markus Moeller (markus_moeller at compuserve.com)
14 * Copyright (C) 2007 Markus Moeller. All rights reserved.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
30 * -----------------------------------------------------------------------------
33 /* get_attributes is partly from OpenLDAP Software <http://www.openldap.org/>.
35 * Copyright 1998-2009 The OpenLDAP Foundation.
36 * All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted only as authorized by the OpenLDAP
42 * A copy of this license is available in the file LICENSE in the
43 * top-level directory of the distribution or, alternatively, at
44 * <http://www.OpenLDAP.org/license.html>.
55 char *convert_domain_to_bind_path(char *domain
);
56 char *escape_filter(char *filter
);
57 int check_AD(struct main_args
*margs
, LDAP
* ld
);
58 int ldap_set_defaults(LDAP
* ld
);
59 int ldap_set_ssl_defaults(struct main_args
*margs
);
60 LDAP
*tool_ldap_open(struct main_args
*margs
, char *host
, int port
, char *ssl
);
62 #define CONNECT_TIMEOUT 2
63 #define SEARCH_TIMEOUT 30
65 #define FILTER "(memberuid=%s)"
66 #define ATTRIBUTE "cn"
67 #define ATTRIBUTE_DN "distinguishedName"
68 #define FILTER_UID "(uid=%s)"
69 #define FILTER_GID "(&(gidNumber=%s)(objectclass=posixgroup))"
70 #define ATTRIBUTE_GID "gidNumber"
71 #define ATTRIBUTE_GID_AD "primaryGroupID"
72 #define ATTRIBUTE_SID "objectSID"
74 #define FILTER_AD "(samaccountname=%s)"
75 #define ATTRIBUTE_AD "memberof"
77 size_t get_attributes(LDAP
* ld
, LDAPMessage
* res
,
78 const char *attribute
/* IN */, char ***out_val
/* OUT (caller frees) */ );
79 size_t get_bin_attributes(LDAP
* ld
, LDAPMessage
* res
,
80 const char *attribute
/* IN */, char ***out_val
,
81 int **out_len
/* OUT (caller frees) */ );
82 int search_group_tree(struct main_args
*margs
, LDAP
* ld
, char *bindp
,
83 char *ldap_group
, char *group
, int depth
);
85 #if HAVE_SUN_LDAP_SDK || HAVE_MOZILLA_LDAP_SDK
86 #if HAVE_LDAP_REBINDPROC_CALLBACK
88 #if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
89 static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind
;
91 static int LDAP_CALL LDAP_CALLBACK
92 ldap_sasl_rebind(LDAP
* ld
,
93 char **whop
, char **credp
, int *methodp
, int freeit
, void *params
)
95 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
100 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
104 static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind
;
106 static int LDAP_CALL LDAP_CALLBACK
107 ldap_simple_rebind(LDAP
* ld
,
108 char **whop
, char **credp
, int *methodp
, int freeit
, void *params
)
110 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
113 cred
.bv_val
= cp
->pw
;
114 cred
.bv_len
= strlen(cp
->pw
);
120 return ldap_sasl_bind_s(ld
, cp
->dn
, LDAP_SASL_SIMPLE
, &cred
, NULL
, NULL
,
123 #elif HAVE_LDAP_REBIND_PROC
124 #if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
125 static LDAP_REBIND_PROC ldap_sasl_rebind
;
128 ldap_sasl_rebind(LDAP
* ld
,
129 LDAP_CONST
char *url
, ber_tag_t request
, ber_int_t msgid
, void *params
)
131 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
132 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
136 static LDAP_REBIND_PROC ldap_simple_rebind
;
139 ldap_simple_rebind(LDAP
* ld
,
140 LDAP_CONST
char *url
, ber_tag_t request
, ber_int_t msgid
, void *params
)
142 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
145 cred
.bv_val
= cp
->pw
;
146 cred
.bv_len
= strlen(cp
->pw
);
148 return ldap_sasl_bind_s(ld
, cp
->dn
, LDAP_SASL_SIMPLE
, &cred
, NULL
, NULL
,
152 #elif HAVE_LDAP_REBIND_FUNCTION
153 #ifndef LDAP_REFERRALS
154 #define LDAP_REFERRALS
156 #if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
157 static LDAP_REBIND_FUNCTION ldap_sasl_rebind
;
160 ldap_sasl_rebind(LDAP
* ld
,
161 char **whop
, char **credp
, int *methodp
, int freeit
, void *params
)
163 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
168 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
172 static LDAP_REBIND_FUNCTION ldap_simple_rebind
;
175 ldap_simple_rebind(LDAP
* ld
,
176 char **whop
, char **credp
, int *methodp
, int freeit
, void *params
)
178 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
181 cred
.bv_val
= cp
->pw
;
182 cred
.bv_len
= strlen(cp
->pw
);
188 return ldap_sasl_bind_s(ld
, cp
->dn
, LDAP_SASL_SIMPLE
, &cred
, NULL
, NULL
,
192 #error "No rebind functione defined"
194 #else /* HAVE_SUN_LDAP_SDK */
195 #if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
196 static LDAP_REBIND_PROC ldap_sasl_rebind
;
199 ldap_sasl_rebind(LDAP
* ld
, LDAP_CONST
char *, ber_tag_t request
,
200 ber_int_t msgid
, void *params
)
202 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
203 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
207 static LDAP_REBIND_PROC ldap_simple_rebind
;
210 ldap_simple_rebind(LDAP
* ld
, LDAP_CONST
char *, ber_tag_t request
,
211 ber_int_t msgid
, void *params
)
214 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
217 cred
.bv_val
= cp
->pw
;
218 cred
.bv_len
= strlen(cp
->pw
);
220 return ldap_sasl_bind_s(ld
, cp
->dn
, LDAP_SASL_SIMPLE
, &cred
, NULL
, NULL
,
226 convert_domain_to_bind_path(char *domain
)
228 char *dp
, *bindp
= NULL
, *bp
= NULL
;
234 for (dp
= domain
; *dp
; ++dp
) {
240 * replace . with ,dc= => new length = old length + #dots * 3 + 3
242 bindp
= (char *) xmalloc(strlen(domain
) + 3 + i
* 3 + 1);
246 for (dp
= domain
; *dp
; ++dp
) {
260 escape_filter(char *filter
)
262 char *ldap_filter_esc
, *ldf
;
266 for (ldap_filter_esc
= filter
; *ldap_filter_esc
; ++ldap_filter_esc
) {
267 if ((*ldap_filter_esc
== '*') ||
268 (*ldap_filter_esc
== '(') ||
269 (*ldap_filter_esc
== ')') || (*ldap_filter_esc
== '\\'))
273 ldap_filter_esc
= (char *) xcalloc(strlen(filter
) + i
+ 1, sizeof(char));
274 ldf
= ldap_filter_esc
;
275 for (; *filter
; ++filter
) {
276 if (*filter
== '*') {
279 } else if (*filter
== '(') {
282 } else if (*filter
== ')') {
285 } else if (*filter
== '\\') {
295 return ldap_filter_esc
;
299 check_AD(struct main_args
*margs
, LDAP
* ld
)
302 char **attr_value
= NULL
;
303 struct timeval searchtime
;
307 #define FILTER_SCHEMA "(objectclass=*)"
308 #define ATTRIBUTE_SCHEMA "schemaNamingContext"
309 #define FILTER_SAM "(ldapdisplayname=samaccountname)"
311 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
312 searchtime
.tv_usec
= 0;
315 "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n",
316 LogTime(), PROGRAM
, FILTER_SCHEMA
);
317 rc
= ldap_search_ext_s(ld
, (char *) "", LDAP_SCOPE_BASE
,
318 (char *) FILTER_SCHEMA
, NULL
, 0, NULL
, NULL
, &searchtime
, 0, &res
);
320 if (rc
== LDAP_SUCCESS
)
321 max_attr
= get_attributes(ld
, res
, ATTRIBUTE_SCHEMA
, &attr_value
);
326 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
327 LogTime(), PROGRAM
, attr_value
[0], FILTER_SAM
);
328 rc
= ldap_search_ext_s(ld
, attr_value
[0], LDAP_SCOPE_SUBTREE
,
329 (char *) FILTER_SAM
, NULL
, 0, NULL
, NULL
, &searchtime
, 0, &res
);
330 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(),
331 PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
,
332 res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
333 if (ldap_count_entries(ld
, res
) > 0)
337 "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n",
340 "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n",
341 LogTime(), PROGRAM
, margs
->AD
? "" : "not ");
347 for (j
= 0; j
< max_attr
; ++j
) {
348 xfree(attr_value
[j
]);
350 safe_free(attr_value
);
357 search_group_tree(struct main_args
*margs
, LDAP
* ld
, char *bindp
,
358 char *ldap_group
, char *group
, int depth
)
360 LDAPMessage
*res
= NULL
;
361 char **attr_value
= NULL
;
364 char *search_exp
= NULL
;
366 int rc
= 0, retval
= 0;
368 char *ldap_filter_esc
= NULL
;
369 struct timeval searchtime
;
371 #define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
372 #define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
374 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
375 searchtime
.tv_usec
= 0;
378 filter
= (char *) FILTER_GROUP_AD
;
380 filter
= (char *) FILTER_GROUP
;
382 ldap_filter_esc
= escape_filter(ldap_group
);
384 se_len
= strlen(filter
) + strlen(ldap_filter_esc
) + 1;
385 search_exp
= (char *) xmalloc(se_len
);
386 snprintf(search_exp
, se_len
, filter
, ldap_filter_esc
);
388 xfree(ldap_filter_esc
);
390 if (depth
> margs
->mdepth
) {
391 debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n",
392 LogTime(), PROGRAM
, depth
, margs
->mdepth
);
397 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
398 LogTime(), PROGRAM
, bindp
, search_exp
);
399 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
, search_exp
, NULL
, 0,
400 NULL
, NULL
, &searchtime
, 0, &res
);
403 if (rc
!= LDAP_SUCCESS
) {
404 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n",
405 LogTime(), PROGRAM
, ldap_err2string(rc
));
408 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
,
409 ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1
410 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
413 max_attr
= get_attributes(ld
, res
, ATTRIBUTE_AD
, &attr_value
);
415 max_attr
= get_attributes(ld
, res
, ATTRIBUTE
, &attr_value
);
418 * Compare group names
422 for (size_t j
= 0; j
< max_attr
; ++j
) {
425 /* Compare first CN= value assuming it is the same as the group name itself */
427 if (!strncasecmp("CN=", av
, 3)) {
430 if ((avp
= strchr(av
, ','))) {
436 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
437 " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM
, j
+ 1, av
);
438 for (n
= 0; av
[n
] != '\0'; ++n
)
439 fprintf(stderr
, "%02x", (unsigned char) av
[n
]);
440 fprintf(stderr
, "\n");
442 if (!strcasecmp(group
, av
)) {
444 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
445 " \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
,
449 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
450 " \"%s\" does not match group name \"%s\"\n", LogTime(),
451 PROGRAM
, j
+ 1, av
, group
);
453 * Do recursive group search
456 "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
457 LogTime(), PROGRAM
, av
);
459 if (search_group_tree(margs
, ld
, bindp
, av
, group
, ldepth
)) {
461 if (!strncasecmp("CN=", av
, 3)) {
464 if ((avp
= strchr(av
, ','))) {
469 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
470 " \"%s\" is member of group named \"%s\"\n", LogTime(),
471 PROGRAM
, j
+ 1, av
, group
);
482 for (size_t j
= 0; j
< max_attr
; ++j
) {
483 xfree(attr_value
[j
]);
485 safe_free(attr_value
);
493 ldap_set_defaults(LDAP
* ld
)
496 #if LDAP_OPT_NETWORK_TIMEOUT
500 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, &val
);
501 if (rc
!= LDAP_SUCCESS
) {
503 "%s| %s: DEBUG: Error while setting protocol version: %s\n",
504 LogTime(), PROGRAM
, ldap_err2string(rc
));
507 rc
= ldap_set_option(ld
, LDAP_OPT_REFERRALS
, LDAP_OPT_OFF
);
508 if (rc
!= LDAP_SUCCESS
) {
509 debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n",
510 LogTime(), PROGRAM
, ldap_err2string(rc
));
513 #if LDAP_OPT_NETWORK_TIMEOUT
514 tv
.tv_sec
= CONNECT_TIMEOUT
;
516 rc
= ldap_set_option(ld
, LDAP_OPT_NETWORK_TIMEOUT
, &tv
);
517 if (rc
!= LDAP_SUCCESS
) {
519 "%s| %s: DEBUG: Error while setting network timeout: %s\n",
520 LogTime(), PROGRAM
, ldap_err2string(rc
));
523 #endif /* LDAP_OPT_NETWORK_TIMEOUT */
528 ldap_set_ssl_defaults(struct main_args
*margs
)
530 #if HAVE_OPENLDAP || HAVE_LDAPSSL_CLIENT_INIT
535 #elif HAVE_LDAPSSL_CLIENT_INIT
536 char *ssl_certdbpath
= NULL
;
540 if (!margs
->rc_allow
) {
541 char *ssl_cacertfile
= NULL
;
542 char *ssl_cacertdir
= NULL
;
544 "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
546 val
= LDAP_OPT_X_TLS_DEMAND
;
547 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &val
);
548 if (rc
!= LDAP_SUCCESS
) {
550 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
551 LogTime(), PROGRAM
, ldap_err2string(rc
));
554 ssl_cacertfile
= xstrdup(getenv("TLS_CACERTFILE"));
555 if (!ssl_cacertfile
) {
556 ssl_cacertfile
= xstrdup("/etc/ssl/certs/cert.pem");
558 if (access(ssl_cacertfile
, R_OK
) == 0) {
560 "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
561 LogTime(), PROGRAM
, ssl_cacertfile
);
562 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_CACERTFILE
,
564 xfree(ssl_cacertfile
);
565 if (rc
!= LDAP_OPT_SUCCESS
) {
567 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
568 LogTime(), PROGRAM
, ldap_err2string(rc
));
573 "%s| %s: DEBUG: Set certificate file for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTFILE) Trying db certificate directory\n",
574 LogTime(), PROGRAM
, ssl_cacertfile
, strerror(errno
));
575 xfree(ssl_cacertfile
);
576 ssl_cacertdir
= xstrdup(getenv("TLS_CACERTDIR"));
577 if (!ssl_cacertdir
) {
578 ssl_cacertdir
= xstrdup("/etc/ssl/certs");
580 if (access(ssl_cacertdir
, R_OK
) == 0) {
582 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
583 LogTime(), PROGRAM
, ssl_cacertdir
);
584 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_CACERTDIR
,
586 xfree(ssl_cacertdir
);
587 if (rc
!= LDAP_OPT_SUCCESS
) {
589 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
590 LogTime(), PROGRAM
, ldap_err2string(rc
));
595 "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
596 LogTime(), PROGRAM
, ssl_cacertdir
, strerror(errno
));
597 xfree(ssl_cacertdir
);
603 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
605 val
= LDAP_OPT_X_TLS_ALLOW
;
606 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &val
);
607 if (rc
!= LDAP_SUCCESS
) {
609 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
610 LogTime(), PROGRAM
, ldap_err2string(rc
));
614 #elif HAVE_LDAPSSL_CLIENT_INIT
616 * Solaris SSL ldap calls require path to certificate database
619 * rc = ldapssl_client_init( ssl_certdbpath, NULL );
620 * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
622 ssl_certdbpath
= getenv("SSL_CERTDBPATH");
623 if (!ssl_certdbpath
) {
624 ssl_certdbpath
= xstrdup("/etc/certs");
627 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable SSL_CERTDBPATH)\n",
628 LogTime(), PROGRAM
, ssl_certdbpath
);
629 if (!margs
->rc_allow
) {
630 rc
= ldapssl_advclientauth_init(ssl_certdbpath
, NULL
, 0, NULL
, NULL
, 0,
633 rc
= ldapssl_advclientauth_init(ssl_certdbpath
, NULL
, 0, NULL
, NULL
, 0,
636 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
639 xfree(ssl_certdbpath
);
640 if (rc
!= LDAP_SUCCESS
) {
642 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
643 LogTime(), PROGRAM
, ldapssl_err2string(rc
));
647 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n",
654 get_attributes(LDAP
* ld
, LDAPMessage
* res
, const char *attribute
,
658 char **attr_value
= *ret_value
;
662 * loop over attributes
664 debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
665 LogTime(), PROGRAM
, attribute
);
666 for (LDAPMessage
* msg
= ldap_first_entry(ld
, res
); msg
;
667 msg
= ldap_next_entry(ld
, msg
)) {
669 switch (ldap_msgtype(msg
)) {
671 case LDAP_RES_SEARCH_ENTRY
: {
672 BerElement
*b
= NULL
;
673 for (char *attr
= ldap_first_attribute(ld
, msg
, &b
); attr
;
674 attr
= ldap_next_attribute(ld
, msg
, b
)) {
675 if (strcasecmp(attr
, attribute
) == 0) {
676 struct berval
**values
;
679 ldap_get_values_len(ld
, msg
, attr
)) != NULL
) {
680 for (int il
= 0; values
[il
] != NULL
; ++il
) {
683 (char **) xrealloc(attr_value
,
684 (max_attr
+ 1) * sizeof(char *));
688 attr_value
[max_attr
] =
689 (char *) xmalloc(values
[il
]->bv_len
+ 1);
690 memcpy(attr_value
[max_attr
], values
[il
]->bv_val
,
692 attr_value
[max_attr
][values
[il
]->bv_len
] = 0;
696 ber_bvecfree(values
);
703 case LDAP_RES_SEARCH_REFERENCE
:
705 "%s| %s: DEBUG: Received a search reference message\n",
708 case LDAP_RES_SEARCH_RESULT
:
709 debug((char *) "%s| %s: DEBUG: Received a search result message\n",
717 debug((char *) "%s| %s: DEBUG: %" PRIuSIZE
718 " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM
,
719 max_attr
, max_attr
> 1 || max_attr
== 0 ? "ies" : "y", attribute
);
721 *ret_value
= attr_value
;
726 get_bin_attributes(LDAP
* ld
, LDAPMessage
* res
, const char *attribute
,
727 char ***ret_value
, int **ret_len
)
730 char **attr_value
= *ret_value
;
731 int *attr_len
= *ret_len
;
735 * loop over attributes
737 debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
738 LogTime(), PROGRAM
, attribute
);
739 for (LDAPMessage
* msg
= ldap_first_entry(ld
, res
); msg
;
740 msg
= ldap_next_entry(ld
, msg
)) {
742 switch (ldap_msgtype(msg
)) {
744 case LDAP_RES_SEARCH_ENTRY
: {
745 BerElement
*b
= NULL
;
746 for (char *attr
= ldap_first_attribute(ld
, msg
, &b
); attr
;
747 attr
= ldap_next_attribute(ld
, msg
, b
)) {
748 if (strcasecmp(attr
, attribute
) == 0) {
749 struct berval
**values
;
752 ldap_get_values_len(ld
, msg
, attr
)) != NULL
) {
753 for (int il
= 0; values
[il
] != NULL
; ++il
) {
756 (char **) xrealloc(attr_value
,
757 (max_attr
+ 1) * sizeof(char *));
762 (int *) xrealloc(attr_len
,
763 (max_attr
+ 1) * sizeof(int));
767 attr_value
[max_attr
] =
768 (char *) xmalloc(values
[il
]->bv_len
+ 1);
769 memcpy(attr_value
[max_attr
], values
[il
]->bv_val
,
771 attr_value
[max_attr
][values
[il
]->bv_len
] = 0;
772 attr_len
[max_attr
] = values
[il
]->bv_len
;
776 ber_bvecfree(values
);
783 case LDAP_RES_SEARCH_REFERENCE
:
785 "%s| %s: DEBUG: Received a search reference message\n",
788 case LDAP_RES_SEARCH_RESULT
:
789 debug((char *) "%s| %s: DEBUG: Received a search result message\n",
797 debug((char *) "%s| %s: DEBUG: %" PRIuSIZE
798 " ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM
,
799 max_attr
, max_attr
> 1 || max_attr
== 0 ? "ies" : "y", attribute
);
801 *ret_value
= attr_value
;
807 * call to open ldap server with or without SSL
810 tool_ldap_open(struct main_args
* margs
, char *host
, int port
, char *ssl
)
814 LDAPURLDesc
*url
= NULL
;
815 char *ldapuri
= NULL
;
820 * Use ldap open here to check if TCP connection is possible. If possible use it.
821 * (Not sure if this is the best way)
824 url
= (LDAPURLDesc
*) xmalloc(sizeof(*url
));
825 memset(url
, 0, sizeof(*url
));
826 #if HAVE_LDAP_URL_LUD_SCHEME
828 url
->lud_scheme
= xstrdup("ldaps");
830 url
->lud_scheme
= xstrdup("ldap");
832 url
->lud_host
= xstrdup(host
);
833 url
->lud_port
= port
;
834 #if HAVE_LDAP_SCOPE_DEFAULT
835 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
837 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
839 #if HAVE_LDAP_URL_DESC2STR
840 ldapuri
= ldap_url_desc2str(url
);
841 #elif HAVE_LDAP_URL_PARSE
842 rc
= ldap_url_parse(ldapuri
, &url
);
843 if (rc
!= LDAP_SUCCESS
) {
844 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n",
845 LogTime(), PROGRAM
, ldap_err2string(rc
));
847 ldap_free_urldesc(url
);
851 #error "No URL parsing function"
853 ldap_free_urldesc(url
);
854 rc
= ldap_initialize(&ld
, ldapuri
);
856 if (rc
!= LDAP_SUCCESS
) {
858 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
859 LogTime(), PROGRAM
, ldap_err2string(rc
));
860 ldap_unbind_ext(ld
, NULL
, NULL
);
865 ld
= ldap_init(host
, port
);
867 rc
= ldap_set_defaults(ld
);
868 if (rc
!= LDAP_SUCCESS
) {
870 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
871 LogTime(), PROGRAM
, ldap_err2string(rc
));
872 ldap_unbind_ext(ld
, NULL
, NULL
);
878 * Try Start TLS first
880 debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM
);
881 rc
= ldap_set_ssl_defaults(margs
);
882 if (rc
!= LDAP_SUCCESS
) {
884 "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n",
885 LogTime(), PROGRAM
, ldap_err2string(rc
));
886 ldap_unbind_ext(ld
, NULL
, NULL
);
892 * Use tls if possible
894 rc
= ldap_start_tls_s(ld
, NULL
, NULL
);
895 if (rc
!= LDAP_SUCCESS
) {
897 "%s| %s: WARNING: Error while setting start_tls for ldap server: %s\n",
898 LogTime(), PROGRAM
, ldap_err2string(rc
));
899 ldap_unbind_ext(ld
, NULL
, NULL
);
901 url
= (LDAPURLDesc
*) xmalloc(sizeof(*url
));
902 memset(url
, 0, sizeof(*url
));
903 #if HAVE_LDAP_URL_LUD_SCHEME
904 url
->lud_scheme
= xstrdup("ldaps");
906 url
->lud_host
= xstrdup(host
);
907 url
->lud_port
= port
;
908 #if HAVE_LDAP_SCOPE_DEFAULT
909 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
911 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
913 #if HAVE_LDAP_URL_DESC2STR
914 ldapuri
= ldap_url_desc2str(url
);
915 #elif HAVE_LDAP_URL_PARSE
916 rc
= ldap_url_parse(ldapuri
, &url
);
917 if (rc
!= LDAP_SUCCESS
) {
918 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n",
919 LogTime(), PROGRAM
, ldap_err2string(rc
));
921 ldap_free_urldesc(url
);
925 #error "No URL parsing function"
927 ldap_free_urldesc(url
);
928 rc
= ldap_initialize(&ld
, ldapuri
);
930 if (rc
!= LDAP_SUCCESS
) {
932 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
933 LogTime(), PROGRAM
, ldap_err2string(rc
));
934 ldap_unbind_ext(ld
, NULL
, NULL
);
938 rc
= ldap_set_defaults(ld
);
939 if (rc
!= LDAP_SUCCESS
) {
941 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
942 LogTime(), PROGRAM
, ldap_err2string(rc
));
943 ldap_unbind_ext(ld
, NULL
, NULL
);
948 #elif HAVE_LDAPSSL_CLIENT_INIT
949 ld
= ldapssl_init(host
, port
, 1);
952 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
953 LogTime(), PROGRAM
, ldapssl_err2string(rc
));
954 ldap_unbind_ext(ld
, NULL
, NULL
);
958 rc
= ldap_set_defaults(ld
);
959 if (rc
!= LDAP_SUCCESS
) {
961 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
962 LogTime(), PROGRAM
, ldap_err2string(rc
));
963 ldap_unbind_ext(ld
, NULL
, NULL
);
968 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n",
976 * ldap calls to get attribute from Ldap Directory Server
979 get_memberof(struct main_args
*margs
, char *user
, char *domain
, char *group
)
983 #if !HAVE_SUN_LDAP_SDK
986 struct ldap_creds
*lcreds
= NULL
;
991 struct timeval searchtime
;
994 char **attr_value
= NULL
;
996 struct hstruct
*hlist
= NULL
;
998 char *ldap_filter_esc
= NULL
;
1000 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
1001 searchtime
.tv_usec
= 0;
1003 * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
1006 debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n",
1007 LogTime(), PROGRAM
);
1010 if (margs
->nokerberos
) {
1013 "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n",
1014 LogTime(), PROGRAM
);
1016 kc
= krb5_create_cache(domain
);
1019 "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",
1020 LogTime(), PROGRAM
);
1026 "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n",
1027 LogTime(), PROGRAM
);
1031 if (kc
&& (!margs
->lurl
|| !margs
->luser
|| !margs
->lpass
)) {
1033 * If Kerberos fails and no url given exit here
1038 #if !HAVE_SUN_LDAP_SDK
1042 // ldap_debug = 127 /* LDAP_DEBUG_TRACE */ ;
1043 // ldap_debug = -1 /* LDAP_DEBUG_ANY */ ;
1045 (void) ldap_set_option(NULL
, LDAP_OPT_DEBUG_LEVEL
, &ldap_debug
);
1047 debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(),
1050 if (domain
&& !kc
) {
1052 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n",
1053 LogTime(), PROGRAM
);
1056 "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n",
1057 LogTime(), PROGRAM
, domain
);
1059 * Loop over list of ldap servers of users domain
1061 nhosts
= get_ldap_hostname_list(margs
, &hlist
, 0, domain
);
1062 for (size_t i
= 0; i
< nhosts
; ++i
) {
1064 if (hlist
[i
].port
!= -1)
1065 port
= hlist
[i
].port
;
1067 "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n",
1068 LogTime(), PROGRAM
, hlist
[i
].host
, port
);
1070 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, margs
->ssl
);
1075 * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
1078 #if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
1080 "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n",
1081 LogTime(), PROGRAM
);
1083 rc
= tool_sasl_bind(ld
, bindp
, margs
->ssl
);
1084 if (rc
!= LDAP_SUCCESS
) {
1086 "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n",
1087 LogTime(), PROGRAM
, ldap_err2string(rc
));
1088 ldap_unbind_ext(ld
, NULL
, NULL
);
1092 lcreds
= (struct ldap_creds
*) xmalloc(sizeof(struct ldap_creds
));
1094 lcreds
->pw
= margs
->ssl
? xstrdup(margs
->ssl
) : NULL
;
1095 ldap_set_rebind_proc(ld
, ldap_sasl_rebind
, (char *) lcreds
);
1098 "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n",
1099 LogTime(), PROGRAM
, ld
? "Successfully" : "Failed to",
1100 margs
->ssl
? "SSL protected " : "", hlist
[i
].host
, port
);
1104 ldap_unbind_ext(ld
, NULL
, NULL
);
1106 error((char *) "%s| %s: ERROR: SASL not supported on system\n",
1107 LogTime(), PROGRAM
);
1111 nhosts
= free_hostname_list(&hlist
, nhosts
);
1114 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1115 LogTime(), PROGRAM
, strerror(errno
));
1117 bindp
= convert_domain_to_bind_path(domain
);
1119 if ((!domain
|| !ld
) && margs
->lurl
&& strstr(margs
->lurl
, "://")) {
1126 * If username does not contain a domain and a url was given then try it
1128 hostname
= strstr(margs
->lurl
, "://") + 3;
1129 ssl
= strstr(margs
->lurl
, "ldaps://");
1131 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n",
1132 LogTime(), PROGRAM
);
1134 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n",
1135 LogTime(), PROGRAM
, hostname
);
1137 * Loop over list of ldap servers
1139 host
= xstrdup(hostname
);
1141 if ((p
= strchr(host
, ':'))) {
1146 nhosts
= get_hostname_list(&hlist
, 0, host
);
1148 for (size_t i
= 0; i
< nhosts
; ++i
) {
1151 cred
.bv_val
= margs
->lpass
;
1152 cred
.bv_len
= strlen(margs
->lpass
);
1154 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, ssl
);
1158 * ldap bind with username/password authentication
1162 "%s| %s: DEBUG: Bind to ldap server with Username/Password\n",
1163 LogTime(), PROGRAM
);
1164 rc
= ldap_sasl_bind_s(ld
, margs
->luser
, LDAP_SASL_SIMPLE
, &cred
,
1166 if (rc
!= LDAP_SUCCESS
) {
1168 "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n",
1169 LogTime(), PROGRAM
, ldap_err2string(rc
));
1170 ldap_unbind_ext(ld
, NULL
, NULL
);
1174 lcreds
= (struct ldap_creds
*) xmalloc(sizeof(struct ldap_creds
));
1175 lcreds
->dn
= xstrdup(margs
->luser
);
1176 lcreds
->pw
= xstrdup(margs
->lpass
);
1177 ldap_set_rebind_proc(ld
, ldap_simple_rebind
, (char *) lcreds
);
1179 "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n",
1180 LogTime(), PROGRAM
, ld
? "Successfully" : "Failed to",
1181 ssl
? "SSL protected " : "", hlist
[i
].host
, port
);
1185 nhosts
= free_hostname_list(&hlist
, nhosts
);
1188 bindp
= xstrdup(margs
->lbind
);
1190 bindp
= convert_domain_to_bind_path(domain
);
1195 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1196 LogTime(), PROGRAM
, strerror(errno
));
1201 * ldap search for user
1204 * Check if server is AD by querying for attribute samaccountname
1207 rc
= check_AD(margs
, ld
);
1208 if (rc
!= LDAP_SUCCESS
) {
1210 "%s| %s: ERROR: Error determining ldap server type: %s\n",
1211 LogTime(), PROGRAM
, ldap_err2string(rc
));
1212 ldap_unbind_ext(ld
, NULL
, NULL
);
1218 filter
= (char *) FILTER_AD
;
1220 filter
= (char *) FILTER
;
1222 ldap_filter_esc
= escape_filter(user
);
1224 se_len
= strlen(filter
) + strlen(ldap_filter_esc
) + 1;
1225 search_exp
= (char *) xmalloc(se_len
);
1226 snprintf(search_exp
, se_len
, filter
, ldap_filter_esc
);
1228 xfree(ldap_filter_esc
);
1231 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
1232 LogTime(), PROGRAM
, bindp
, search_exp
);
1233 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
, search_exp
, NULL
, 0,
1234 NULL
, NULL
, &searchtime
, 0, &res
);
1237 if (rc
!= LDAP_SUCCESS
) {
1238 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n",
1239 LogTime(), PROGRAM
, ldap_err2string(rc
));
1240 ldap_unbind_ext(ld
, NULL
, NULL
);
1245 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
,
1246 ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1
1247 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
1249 if (ldap_count_entries(ld
, res
) != 0) {
1252 max_attr
= get_attributes(ld
, res
, ATTRIBUTE_AD
, &attr_value
);
1254 max_attr
= get_attributes(ld
, res
, ATTRIBUTE
, &attr_value
);
1258 * Compare group names
1261 for (size_t k
= 0; k
< max_attr
; ++k
) {
1264 /* Compare first CN= value assuming it is the same as the group name itself */
1266 if (!strncasecmp("CN=", av
, 3)) {
1269 if ((avp
= strchr(av
, ','))) {
1273 if (debug_enabled
) {
1274 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
1275 " \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM
, k
+ 1, av
);
1276 for (unsigned int n
= 0; av
[n
] != '\0'; ++n
)
1277 fprintf(stderr
, "%02x", (unsigned char) av
[n
]);
1278 fprintf(stderr
, "\n");
1280 if (!strcasecmp(group
, av
)) {
1283 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
1284 " \"%s\" matches group name \"%s\"\n", LogTime(),
1285 PROGRAM
, k
+ 1, av
, group
);
1289 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
1290 " \"%s\" does not match group name \"%s\"\n", LogTime(),
1291 PROGRAM
, k
+ 1, av
, group
);
1294 * Do recursive group search for AD only since posixgroups can not contain other groups
1296 if (!retval
&& margs
->AD
) {
1297 if (debug_enabled
&& max_attr
> 0) {
1299 "%s| %s: DEBUG: Perform recursive group search\n",
1300 LogTime(), PROGRAM
);
1302 for (size_t j
= 0; j
< max_attr
; ++j
) {
1306 if (search_group_tree(margs
, ld
, bindp
, av
, group
, 1)) {
1308 if (!strncasecmp("CN=", av
, 3)) {
1311 if ((avp
= strchr(av
, ','))) {
1316 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
1317 " group \"%s\" is (in)direct member of group \"%s\"\n",
1318 LogTime(), PROGRAM
, j
+ 1, av
, group
);
1328 for (size_t j
= 0; j
< max_attr
; ++j
) {
1329 xfree(attr_value
[j
]);
1331 safe_free(attr_value
);
1334 } else if (ldap_count_entries(ld
, res
) == 0 && margs
->AD
) {
1336 ldap_unbind_ext(ld
, NULL
, NULL
);
1347 * Check for primary Group membership
1350 "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n",
1351 LogTime(), PROGRAM
, group
);
1353 filter
= (char *) FILTER_AD
;
1355 filter
= (char *) FILTER_UID
;
1357 ldap_filter_esc
= escape_filter(user
);
1359 se_len
= strlen(filter
) + strlen(ldap_filter_esc
) + 1;
1360 search_exp
= (char *) xmalloc(se_len
);
1361 snprintf(search_exp
, se_len
, filter
, ldap_filter_esc
);
1363 xfree(ldap_filter_esc
);
1366 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1367 LogTime(), PROGRAM
, bindp
, search_exp
);
1368 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
, search_exp
, NULL
,
1369 0, NULL
, NULL
, &searchtime
, 0, &res
);
1372 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(),
1373 PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
,
1374 res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
1380 get_attributes(ld
, res
, ATTRIBUTE_GID_AD
, &attr_value
);
1382 max_attr
= get_attributes(ld
, res
, ATTRIBUTE_GID
, &attr_value
);
1385 if (max_attr
== 1) {
1386 char **attr_value_2
= NULL
;
1387 size_t max_attr_2
= 0;
1390 char **attr_value_3
= NULL
;
1391 int *attr_len_3
= NULL
;
1392 size_t max_attr_3
= 0;
1393 uint32_t gid
= atoi(attr_value
[0]);
1395 /* Get objectsid and search for group
1396 * with objectsid = domain(objectsid) + primarygroupid */
1397 debug((char *) "%s| %s: DEBUG: Got primaryGroupID %u\n",
1398 LogTime(), PROGRAM
, gid
);
1400 get_bin_attributes(ld
, res
, ATTRIBUTE_SID
, &attr_value_3
,
1403 if (max_attr_3
== 1) {
1404 int len
= attr_len_3
[0];
1407 "%s| %s: ERROR: Length %d is too short for objectSID\n",
1408 LogTime(), PROGRAM
, len
);
1412 attr_value_3
[0][len
- 1] = ((gid
>> 24) & 0xff);
1413 attr_value_3
[0][len
- 2] = ((gid
>> 16) & 0xff);
1414 attr_value_3
[0][len
- 3] = ((gid
>> 8) & 0xff);
1415 attr_value_3
[0][len
- 4] = ((gid
>> 0) & 0xff);
1417 #define FILTER_SID_1 "(objectSID="
1418 #define FILTER_SID_2 ")"
1421 strlen(FILTER_SID_1
) + len
* 3 +
1422 strlen(FILTER_SID_2
) + 1;
1423 search_exp
= (char *) xmalloc(se_len
);
1424 snprintf(search_exp
, se_len
, "%s", FILTER_SID_1
);
1426 for (int j
= 0; j
< len
; j
++) {
1427 se
= xstrdup(search_exp
);
1428 snprintf(search_exp
, se_len
, "%s\\%02x", se
,
1429 attr_value_3
[0][j
] & 0xFF);
1432 se
= xstrdup(search_exp
);
1433 snprintf(search_exp
, se_len
, "%s%s", se
, FILTER_SID_2
);
1437 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1438 LogTime(), PROGRAM
, bindp
, search_exp
);
1439 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
1440 search_exp
, NULL
, 0, NULL
, NULL
, &searchtime
, 0,
1444 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n",
1445 LogTime(), PROGRAM
, ldap_count_entries(ld
, res
),
1446 ldap_count_entries(ld
, res
) > 1
1447 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
1455 for (j
= 0; j
< max_attr_3
; ++j
) {
1456 xfree(attr_value_3
[j
]);
1458 safe_free(attr_value_3
);
1465 filter
= (char *) FILTER_GID
;
1467 ldap_filter_esc
= escape_filter(attr_value
[0]);
1469 se_len
= strlen(filter
) + strlen(ldap_filter_esc
) + 1;
1470 search_exp
= (char *) xmalloc(se_len
);
1471 snprintf(search_exp
, se_len
, filter
, ldap_filter_esc
);
1473 xfree(ldap_filter_esc
);
1476 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1477 LogTime(), PROGRAM
, bindp
, search_exp
);
1478 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
1479 search_exp
, NULL
, 0, NULL
, NULL
, &searchtime
, 0, &res
);
1486 get_attributes(ld
, res
, ATTRIBUTE_DN
, &attr_value_2
);
1489 get_attributes(ld
, res
, ATTRIBUTE
, &attr_value_2
);
1495 * Compare group names
1498 if (max_attr_2
== 1) {
1499 /* Compare first CN= value assuming it is the same as the group name itself */
1500 char *av
= attr_value_2
[0];
1501 if (!strncasecmp("CN=", av
, 3)) {
1504 if ((avp
= strchr(av
, ','))) {
1508 if (!strcasecmp(group
, av
)) {
1511 "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n",
1512 LogTime(), PROGRAM
, av
, group
);
1515 "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n",
1516 LogTime(), PROGRAM
, av
, group
);
1520 * Do recursive group search for AD only since posixgroups can not contain other groups
1522 if (!retval
&& margs
->AD
) {
1523 if (debug_enabled
&& max_attr_2
> 0) {
1525 "%s| %s: DEBUG: Perform recursive group search\n",
1526 LogTime(), PROGRAM
);
1528 for (size_t j
= 0; j
< max_attr_2
; ++j
) {
1531 av
= attr_value_2
[j
];
1532 if (search_group_tree(margs
, ld
, bindp
, av
, group
, 1)) {
1534 if (!strncasecmp("CN=", av
, 3)) {
1537 if ((avp
= strchr(av
, ','))) {
1541 if (debug_enabled
) {
1542 debug((char *) "%s| %s: DEBUG: Entry %" PRIuSIZE
1543 " group \"%s\" is (in)direct member of group \"%s\"\n",
1544 LogTime(), PROGRAM
, j
+ 1, av
, group
);
1556 for (j
= 0; j
< max_attr_2
; ++j
) {
1557 xfree(attr_value_2
[j
]);
1559 safe_free(attr_value_2
);
1562 debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n",
1563 LogTime(), PROGRAM
, retval
? "matches" : "does not match",
1569 "%s| %s: DEBUG: Did not find ldap entry for group %s\n",
1570 LogTime(), PROGRAM
, group
);
1576 for (size_t j
= 0; j
< max_attr
; ++j
) {
1577 xfree(attr_value
[j
]);
1579 safe_free(attr_value
);
1582 rc
= ldap_unbind_ext(ld
, NULL
, NULL
);
1584 if (rc
!= LDAP_SUCCESS
) {
1585 error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n",
1586 LogTime(), PROGRAM
, ldap_err2string(rc
));
1588 debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM
);