2 * -----------------------------------------------------------------------------
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
6 * Copyright (C) 2007 Markus Moeller. All rights reserved.
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.
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.
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.
22 * -----------------------------------------------------------------------------
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
);
42 #define CONNECT_TIMEOUT 2
43 #define SEARCH_TIMEOUT 30
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"
51 #define FILTER_AD "(samaccountname=%s)"
52 #define ATTRIBUTE_AD "memberof"
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
);
57 #if defined(HAVE_SUN_LDAP_SDK) || defined(HAVE_MOZILLA_LDAP_SDK)
58 #ifdef HAVE_LDAP_REBINDPROC_CALLBACK
60 #if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
61 static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind
;
63 static int LDAP_CALL LDAP_CALLBACK
72 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
77 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
81 static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind
;
83 static int LDAP_CALL LDAP_CALLBACK
92 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
97 return ldap_bind_s(ld
, cp
->dn
, cp
->pw
, LDAP_AUTH_SIMPLE
);
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
;
106 LDAP_CONST
char *url
,
111 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
115 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
119 static LDAP_REBIND_PROC ldap_simple_rebind
;
124 LDAP_CONST
char *url
,
129 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
133 return ldap_bind_s(ld
, cp
->dn
, cp
->pw
, LDAP_AUTH_SIMPLE
);
136 #elif defined(HAVE_LDAP_REBIND_FUNCTION)
137 #ifndef LDAP_REFERRALS
138 #define LDAP_REFERRALS
140 #if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
141 static LDAP_REBIND_FUNCTION ldap_sasl_rebind
;
152 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
157 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
161 static LDAP_REBIND_FUNCTION ldap_simple_rebind
;
172 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
177 return ldap_bind_s(ld
, cp
->dn
, cp
->pw
, LDAP_AUTH_SIMPLE
);
180 #error "No rebind functione defined"
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
;
189 LDAP_CONST
char *url
,
194 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
198 return tool_sasl_bind(ld
, cp
->dn
, cp
->pw
);
202 static LDAP_REBIND_PROC ldap_simple_rebind
;
207 LDAP_CONST
char *url
,
213 struct ldap_creds
*cp
= (struct ldap_creds
*) params
;
217 return ldap_bind_s(ld
, cp
->dn
, cp
->pw
, LDAP_AUTH_SIMPLE
);
222 convert_domain_to_bind_path(char *domain
)
224 char *dp
, *bindp
= NULL
, *bp
= NULL
;
230 for (dp
= domain
; *dp
; ++dp
) {
236 * replace . with ,dc= => new length = old length + #dots * 3 + 3
238 bindp
= (char *) xmalloc(strlen(domain
) + 3 + i
* 3 + 1);
242 for (dp
= domain
; *dp
; ++dp
) {
256 escape_filter(char *filter
)
259 char *ldap_filter_esc
, *ldf
;
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
== '\\'))
270 ldap_filter_esc
= (char *) xcalloc(strlen(filter
) + i
+ 1, sizeof(char));
271 ldf
= ldap_filter_esc
;
272 for (; *filter
; ++filter
) {
273 if (*filter
== '*') {
276 } else if (*filter
== '(') {
279 } else if (*filter
== ')') {
282 } else if (*filter
== '\\') {
292 return ldap_filter_esc
;
296 check_AD(struct main_args
*margs
, LDAP
* ld
)
299 char **attr_value
= NULL
;
300 struct timeval searchtime
;
304 #define FILTER_SCHEMA "(objectclass=*)"
305 #define ATTRIBUTE_SCHEMA "schemaNamingContext"
306 #define FILTER_SAM "(ldapdisplayname=samaccountname)"
308 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
309 searchtime
.tv_usec
= 0;
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
);
315 if (rc
== LDAP_SUCCESS
)
316 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_SCHEMA
, &attr_value
);
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)
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 ");
333 for (j
= 0; j
< max_attr
; ++j
) {
334 xfree(attr_value
[j
]);
343 search_group_tree(struct main_args
*margs
, LDAP
* ld
, char *bindp
, char *ldap_group
, char *group
, int depth
)
345 LDAPMessage
*res
= NULL
;
346 char **attr_value
= NULL
;
349 char *search_exp
= NULL
;
350 int j
, rc
= 0, retval
= 0;
351 char *av
= NULL
, *avp
= NULL
;
353 char *ldap_filter_esc
= NULL
;
354 struct timeval searchtime
;
356 #define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
357 #define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
359 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
360 searchtime
.tv_usec
= 0;
363 filter
= (char *) FILTER_GROUP_AD
;
365 filter
= (char *) FILTER_GROUP
;
367 ldap_filter_esc
= escape_filter(ldap_group
);
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
);
373 xfree(ldap_filter_esc
);
375 if (depth
> margs
->mdepth
) {
376 debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM
, depth
, margs
->mdepth
);
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
,
382 NULL
, NULL
, &searchtime
, 0, &res
);
386 if (rc
!= LDAP_SUCCESS
) {
387 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
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");
394 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_AD
, &attr_value
);
396 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value
);
399 * Compare group names
403 for (j
= 0; j
< max_attr
; ++j
) {
405 /* Compare first CN= value assuming it is the same as the group name itself */
407 if (!strncasecmp("CN=", av
, 3)) {
409 if ((avp
= strchr(av
, ','))) {
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");
420 if (!strcasecmp(group
, av
)) {
422 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
425 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
427 * Do recursive group search
429 debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM
, av
);
431 if (search_group_tree(margs
, ld
, bindp
, av
, group
, ldepth
)) {
433 if (!strncasecmp("CN=", av
, 3)) {
435 if ((avp
= strchr(av
, ','))) {
440 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
451 for (j
= 0; j
< max_attr
; ++j
) {
452 xfree(attr_value
[j
]);
463 ldap_set_defaults(struct main_args
*margs
, LDAP
* ld
)
466 #ifdef LDAP_OPT_NETWORK_TIMEOUT
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
));
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
));
480 #ifdef LDAP_OPT_NETWORK_TIMEOUT
481 tv
.tv_sec
= CONNECT_TIMEOUT
;
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
));
488 #endif /* LDAP_OPT_NETWORK_TIMEOUT */
493 ldap_set_ssl_defaults(struct main_args
*margs
)
495 #if defined(HAVE_OPENLDAP) || defined(HAVE_LDAPSSL_CLIENT_INIT)
500 char *ssl_cacertfile
= NULL
;
502 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
503 char *ssl_certdbpath
= NULL
;
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
));
515 ssl_cacertfile
= getenv("TLS_CACERTFILE");
517 if (!ssl_cacertfile
) {
518 ssl_cacertfile
= xstrdup("/etc/ssl/certs/cert.pem");
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
;
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
));
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
));
540 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
542 * Solaris SSL ldap calls require path to certificate database
545 * rc = ldapssl_client_init( ssl_certdbpath, NULL );
546 * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
548 ssl_certdbpath
= getenv("SSL_CERTDBPATH");
549 if (!ssl_certdbpath
) {
550 ssl_certdbpath
= xstrdup("/etc/certs");
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);
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
);
559 if (ssl_certdbpath
) {
560 xfree(ssl_certdbpath
);
561 ssl_certdbpath
= NULL
;
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
));
568 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM
);
574 get_attributes(struct main_args
*margs
, LDAP
* ld
, LDAPMessage
* res
, const char *attribute
, char ***ret_value
)
578 char **attr_value
= NULL
;
581 attr_value
= *ret_value
;
583 * loop over attributes
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
)) {
591 switch (ldap_msgtype(msg
)) {
593 case LDAP_RES_SEARCH_ENTRY
:
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
;
601 if ((values
= ldap_get_values_len(ld
, msg
, attr
)) != NULL
) {
602 for (il
= 0; values
[il
] != NULL
; ++il
) {
604 attr_value
= (char **) xrealloc(attr_value
, (il
+ 1) * sizeof(char *));
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;
614 ber_bvecfree(values
);
620 case LDAP_RES_SEARCH_REFERENCE
:
621 debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM
);
623 case LDAP_RES_SEARCH_RESULT
:
624 debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM
);
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
);
633 *ret_value
= attr_value
;
638 * call to open ldap server with or without SSL
641 tool_ldap_open(struct main_args
* margs
, char *host
, int port
, char *ssl
)
645 LDAPURLDesc
*url
= NULL
;
646 char *ldapuri
= NULL
;
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)
655 url
= (LDAPURLDesc
*) xmalloc(sizeof(*url
));
656 memset(url
, 0, sizeof(*url
));
657 #ifdef HAVE_LDAP_URL_LUD_SCHEME
659 url
->lud_scheme
= (char *) "ldaps";
661 url
->lud_scheme
= (char *) "ldap";
663 url
->lud_host
= host
;
664 url
->lud_port
= port
;
665 #ifdef HAVE_LDAP_SCOPE_DEFAULT
666 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
668 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
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
));
683 #error "No URL parsing function"
689 rc
= ldap_initialize(&ld
, 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
));
699 ld
= ldap_init(host
, port
);
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
));
710 * Try Start TLS first
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
));
722 * Use tls if possible
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
));
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";
734 url
->lud_host
= host
;
735 url
->lud_port
= port
;
736 #ifdef HAVE_LDAP_SCOPE_DEFAULT
737 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
739 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
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
));
754 #error "No URL parsing function"
760 rc
= ldap_initialize(&ld
, 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
));
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
));
777 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
778 ld
= ldapssl_init(host
, port
, 1);
780 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM
, ldapssl_err2string(rc
));
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
));
793 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM
);
800 * ldap calls to get attribute from Ldap Directory Server
803 get_memberof(struct main_args
*margs
, char *user
, char *domain
, char *group
)
807 #ifndef HAVE_SUN_LDAP_SDK
810 struct ldap_creds
*lcreds
= NULL
;
814 struct timeval searchtime
;
815 int i
, j
, rc
= 0, kc
= 1;
817 char **attr_value
= NULL
;
818 char *av
= NULL
, *avp
= NULL
;
820 struct hstruct
*hlist
= NULL
;
827 char *ldap_filter_esc
= NULL
;
829 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
830 searchtime
.tv_usec
= 0;
832 * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
835 debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM
);
838 kc
= krb5_create_cache(margs
, domain
);
840 error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM
);
844 debug((char *) "%s| %s: DEBUG: Kerberos is not supported. Use username/passwaord with ldap url instead\n", LogTime(), PROGRAM
);
848 if (kc
&& (!margs
->lurl
|| !margs
->luser
| !margs
->lpass
)) {
850 * If Kerberos fails and no url given exit here
855 #ifndef HAVE_SUN_LDAP_SDK
859 ldap_debug
= 127 /* LDAP_DEBUG_TRACE */ ;
860 ldap_debug
= -1 /* LDAP_DEBUG_ANY */ ;
862 (void) ldap_set_option(NULL
, LDAP_OPT_DEBUG_LEVEL
, &ldap_debug
);
864 debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM
);
868 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM
);
870 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM
, domain
);
872 * Loop over list of ldap servers of users domain
874 nhosts
= get_ldap_hostname_list(margs
, &hlist
, 0, domain
);
875 for (i
= 0; i
< nhosts
; ++i
) {
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
);
881 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, margs
->ssl
);
886 * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
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
);
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
));
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
);
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
);
910 error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM
);
914 nhosts
= free_hostname_list(&hlist
, nhosts
);
916 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM
, strerror(errno
));
918 bindp
= convert_domain_to_bind_path(domain
);
920 if ((!domain
|| !ld
) && margs
->lurl
&& strstr(margs
->lurl
, "://")) {
922 * If username does not contain a domain and a url was given then try it
924 hostname
= strstr(margs
->lurl
, "://") + 3;
925 ssl
= strstr(margs
->lurl
, "ldaps://");
927 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM
);
929 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM
, hostname
);
931 * Loop over list of ldap servers
933 host
= xstrdup(hostname
);
935 if ((p
= strchr(host
, ':'))) {
940 nhosts
= get_hostname_list(margs
, &hlist
, 0, host
);
944 for (i
= 0; i
< nhosts
; ++i
) {
946 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, ssl
);
950 * ldap bind with username/password authentication
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
));
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
);
969 nhosts
= free_hostname_list(&hlist
, nhosts
);
973 bindp
= xstrdup(margs
->lbind
);
975 bindp
= convert_domain_to_bind_path(domain
);
979 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM
, strerror(errno
));
984 * ldap search for user
987 * Check if server is AD by querying for attribute samaccountname
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
));
999 filter
= (char *) FILTER_AD
;
1001 filter
= (char *) FILTER
;
1003 ldap_filter_esc
= escape_filter(user
);
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
);
1008 if (ldap_filter_esc
)
1009 xfree(ldap_filter_esc
);
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
);
1018 if (rc
!= LDAP_SUCCESS
) {
1019 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
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");
1027 if (ldap_count_entries(ld
, res
) != 0) {
1030 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_AD
, &attr_value
);
1032 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value
);
1036 * Compare group names
1039 for (j
= 0; j
< max_attr
; ++j
) {
1041 /* Compare first CN= value assuming it is the same as the group name itself */
1043 if (!strncasecmp("CN=", av
, 3)) {
1045 if ((avp
= strchr(av
, ','))) {
1049 if (debug_enabled
) {
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");
1056 if (!strcasecmp(group
, av
)) {
1059 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1063 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1066 * Do recursive group search for AD only since posixgroups can not contain other groups
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
);
1072 for (j
= 0; j
< max_attr
; ++j
) {
1075 if (search_group_tree(margs
, ld
, bindp
, av
, group
, 1)) {
1077 if (!strncasecmp("CN=", av
, 3)) {
1079 if ((avp
= strchr(av
, ','))) {
1084 debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1094 for (j
= 0; j
< max_attr
; ++j
) {
1095 xfree(attr_value
[j
]);
1101 } else if (ldap_count_entries(ld
, res
) == 0 && margs
->AD
) {
1112 if (!margs
->AD
&& retval
== 0) {
1114 * Check for primary Group membership
1116 debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM
, group
);
1117 filter
= (char *) FILTER_UID
;
1119 ldap_filter_esc
= escape_filter(user
);
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
);
1124 if (ldap_filter_esc
)
1125 xfree(ldap_filter_esc
);
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
);
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");
1136 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_GID
, &attr_value
);
1138 if (max_attr
== 1) {
1139 char **attr_value_2
= NULL
;
1143 filter
= (char *) FILTER_GID
;
1145 ldap_filter_esc
= escape_filter(attr_value
[0]);
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
);
1150 if (ldap_filter_esc
)
1151 xfree(ldap_filter_esc
);
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
);
1160 max_attr_2
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value_2
);
1162 * Compare group names
1165 if (max_attr_2
== 1) {
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
)) {
1171 debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, av
, group
);
1173 debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, av
, group
);
1180 for (j
= 0; j
< max_attr_2
; ++j
) {
1181 xfree(attr_value_2
[j
]);
1183 xfree(attr_value_2
);
1184 attr_value_2
= NULL
;
1188 debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM
, retval
? "matches" : "does not match", group
);
1191 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM
, group
);
1196 for (j
= 0; j
< max_attr
; ++j
) {
1197 xfree(attr_value
[j
]);
1203 rc
= ldap_unbind(ld
);
1205 if (rc
!= LDAP_SUCCESS
) {
1206 error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
1208 debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM
);