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
++) {
254 escape_filter(char *filter
)
257 char *ldap_filter_esc
, *ldf
;
260 for (ldap_filter_esc
= filter
; *ldap_filter_esc
; ldap_filter_esc
++) {
261 if ((*ldap_filter_esc
== '*') ||
262 (*ldap_filter_esc
== '(') ||
263 (*ldap_filter_esc
== ')') ||
264 (*ldap_filter_esc
== '\\'))
268 ldap_filter_esc
= (char *) xcalloc(strlen(filter
) + i
+ 1, sizeof(char));
269 ldf
= ldap_filter_esc
;
270 for (; *filter
; filter
++) {
271 if (*filter
== '*') {
274 } else if (*filter
== '(') {
277 } else if (*filter
== ')') {
280 } else if (*filter
== '\\') {
290 return ldap_filter_esc
;
294 check_AD(struct main_args
*margs
, LDAP
* ld
)
297 char **attr_value
= NULL
;
298 struct timeval searchtime
;
302 #define FILTER_SCHEMA "(objectclass=*)"
303 #define ATTRIBUTE_SCHEMA "schemaNamingContext"
304 #define FILTER_SAM "(ldapdisplayname=samaccountname)"
306 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
307 searchtime
.tv_usec
= 0;
309 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n", LogTime(), PROGRAM
, FILTER_SCHEMA
);
310 rc
= ldap_search_ext_s(ld
, (char *) "", LDAP_SCOPE_BASE
, (char *) FILTER_SCHEMA
, NULL
, 0,
311 NULL
, NULL
, &searchtime
, 0, &res
);
313 if (rc
== LDAP_SUCCESS
)
314 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_SCHEMA
, &attr_value
);
318 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM
, attr_value
[0], FILTER_SAM
);
319 rc
= ldap_search_ext_s(ld
, attr_value
[0], LDAP_SCOPE_SUBTREE
, (char *) FILTER_SAM
, NULL
, 0,
320 NULL
, NULL
, &searchtime
, 0, &res
);
321 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
322 if (ldap_count_entries(ld
, res
) > 0)
325 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n", LogTime(), PROGRAM
);
326 debug((char *) "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n", LogTime(), PROGRAM
, margs
->AD
? "" : "not ");
331 for (j
= 0; j
< max_attr
; j
++) {
332 xfree(attr_value
[j
]);
341 search_group_tree(struct main_args
*margs
, LDAP
* ld
, char *bindp
, char *ldap_group
, char *group
, int depth
)
343 LDAPMessage
*res
= NULL
;
344 char **attr_value
= NULL
;
347 char *search_exp
= NULL
;
348 int j
, rc
= 0, retval
= 0;
349 char *av
= NULL
, *avp
= NULL
;
351 char *ldap_filter_esc
= NULL
;
352 struct timeval searchtime
;
354 #define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
355 #define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
357 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
358 searchtime
.tv_usec
= 0;
361 filter
= (char *) FILTER_GROUP_AD
;
363 filter
= (char *) FILTER_GROUP
;
365 ldap_filter_esc
= escape_filter(ldap_group
);
367 search_exp
= (char *) xmalloc(strlen(filter
) + strlen(ldap_filter_esc
) + 1);
368 snprintf(search_exp
, strlen(filter
) + strlen(ldap_filter_esc
) + 1, filter
, ldap_filter_esc
);
371 xfree(ldap_filter_esc
);
373 if (depth
> margs
->mdepth
) {
374 debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM
, depth
, margs
->mdepth
);
377 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM
, bindp
, search_exp
);
378 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
380 NULL
, NULL
, &searchtime
, 0, &res
);
384 if (rc
!= LDAP_SUCCESS
) {
385 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
389 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
392 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_AD
, &attr_value
);
394 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value
);
397 * Compare group names
401 for (j
= 0; j
< max_attr
; j
++) {
403 /* Compare first CN= value assuming it is the same as the group name itself */
405 if (!strncasecmp("CN=", av
, 3)) {
407 if ((avp
= strchr(av
, ','))) {
413 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM
, j
+ 1, av
);
414 for (n
= 0; av
[n
] != '\0'; n
++)
415 fprintf(stderr
, "%02x", (unsigned char) av
[n
]);
416 fprintf(stderr
, "\n");
418 if (!strcasecmp(group
, av
)) {
420 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
423 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
425 * Do recursive group search
427 debug((char *) "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n", LogTime(), PROGRAM
, av
);
429 if (search_group_tree(margs
, ld
, bindp
, av
, group
, ldepth
)) {
431 if (!strncasecmp("CN=", av
, 3)) {
433 if ((avp
= strchr(av
, ','))) {
438 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" is member of group named \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
449 for (j
= 0; j
< max_attr
; j
++) {
450 xfree(attr_value
[j
]);
461 ldap_set_defaults(struct main_args
*margs
, LDAP
* ld
)
464 #ifdef LDAP_OPT_NETWORK_TIMEOUT
468 rc
= ldap_set_option(ld
, LDAP_OPT_PROTOCOL_VERSION
, &val
);
469 if (rc
!= LDAP_SUCCESS
) {
470 debug((char *) "%s| %s: DEBUG: Error while setting protocol version: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
473 rc
= ldap_set_option(ld
, LDAP_OPT_REFERRALS
, LDAP_OPT_OFF
);
474 if (rc
!= LDAP_SUCCESS
) {
475 debug((char *) "%s| %s: DEBUG: Error while setting referrals off: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
478 #ifdef LDAP_OPT_NETWORK_TIMEOUT
479 tv
.tv_sec
= CONNECT_TIMEOUT
;
481 rc
= ldap_set_option(ld
, LDAP_OPT_NETWORK_TIMEOUT
, &tv
);
482 if (rc
!= LDAP_SUCCESS
) {
483 debug((char *) "%s| %s: DEBUG: Error while setting network timeout: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
486 #endif /* LDAP_OPT_NETWORK_TIMEOUT */
491 ldap_set_ssl_defaults(struct main_args
*margs
)
493 #if defined(HAVE_OPENLDAP) || defined(HAVE_LDAPSSL_CLIENT_INIT)
498 char *ssl_cacertfile
= NULL
;
500 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
501 char *ssl_certdbpath
= NULL
;
505 if (!margs
->rc_allow
) {
506 debug((char *) "%s| %s: DEBUG: Enable server certificate check for ldap server.\n", LogTime(), PROGRAM
);
507 val
= LDAP_OPT_X_TLS_DEMAND
;
508 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &val
);
509 if (rc
!= LDAP_SUCCESS
) {
510 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
513 ssl_cacertfile
= getenv("TLS_CACERTFILE");
515 if (!ssl_cacertfile
) {
516 ssl_cacertfile
= xstrdup("/etc/ssl/certs/cert.pem");
519 debug((char *) "%s| %s: DEBUG: Set certificate file for ldap server to %s.(Changeable through setting environment variable TLS_CACERTFILE)\n", LogTime(), PROGRAM
, ssl_cacertfile
);
520 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_CACERTFILE
, ssl_cacertfile
);
521 if (ssl_cacertfile
&& free_path
) {
522 xfree(ssl_cacertfile
);
523 ssl_cacertfile
= NULL
;
525 if (rc
!= LDAP_OPT_SUCCESS
) {
526 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
530 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM
);
531 val
= LDAP_OPT_X_TLS_ALLOW
;
532 rc
= ldap_set_option(NULL
, LDAP_OPT_X_TLS_REQUIRE_CERT
, &val
);
533 if (rc
!= LDAP_SUCCESS
) {
534 error((char *) "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
538 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
540 * Solaris SSL ldap calls require path to certificate database
543 * rc = ldapssl_client_init( ssl_certdbpath, NULL );
544 * rc = ldapssl_advclientauth_init( ssl_certdbpath, NULL , 0 , NULL, NULL, 0, NULL, 2);
546 ssl_certdbpath
= getenv("SSL_CERTDBPATH");
547 if (!ssl_certdbpath
) {
548 ssl_certdbpath
= xstrdup("/etc/certs");
550 debug((char *) "%s| %s: DEBUG: Set certificate database path for ldap server to %s.(Changeable through setting environment variable SSL_CERTDBPATH)\n", LogTime(), PROGRAM
, ssl_certdbpath
);
551 if (!margs
->rc_allow
) {
552 rc
= ldapssl_advclientauth_init(ssl_certdbpath
, NULL
, 0, NULL
, NULL
, 0, NULL
, 2);
554 rc
= ldapssl_advclientauth_init(ssl_certdbpath
, NULL
, 0, NULL
, NULL
, 0, NULL
, 0);
555 debug((char *) "%s| %s: DEBUG: Disable server certificate check for ldap server.\n", LogTime(), PROGRAM
);
557 if (ssl_certdbpath
) {
558 xfree(ssl_certdbpath
);
559 ssl_certdbpath
= NULL
;
561 if (rc
!= LDAP_SUCCESS
) {
562 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM
, ldapssl_err2string(rc
));
566 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM
);
572 get_attributes(struct main_args
*margs
, LDAP
* ld
, LDAPMessage
* res
, const char *attribute
, char ***ret_value
)
576 char **attr_value
= NULL
;
579 attr_value
= *ret_value
;
581 * loop over attributes
583 debug((char *) "%s| %s: DEBUG: Search ldap entries for attribute : %s\n", LogTime(), PROGRAM
, attribute
);
584 for (msg
= ldap_first_entry(ld
, res
); msg
; msg
= ldap_next_entry(ld
, msg
)) {
589 switch (ldap_msgtype(msg
)) {
591 case LDAP_RES_SEARCH_ENTRY
:
593 for (attr
= ldap_first_attribute(ld
, msg
, &b
); attr
;
594 attr
= ldap_next_attribute(ld
, msg
, b
)) {
595 if (strcasecmp(attr
, attribute
) == 0) {
596 struct berval
**values
;
599 if ((values
= ldap_get_values_len(ld
, msg
, attr
)) != NULL
) {
600 for (il
= 0; values
[il
] != NULL
; il
++) {
602 attr_value
= (char **) xrealloc(attr_value
, (il
+ 1) * sizeof(char *));
606 attr_value
[il
] = (char *) xmalloc(values
[il
]->bv_len
+ 1);
607 memcpy(attr_value
[il
], values
[il
]->bv_val
, values
[il
]->bv_len
);
608 attr_value
[il
][values
[il
]->bv_len
] = 0;
612 ber_bvecfree(values
);
618 case LDAP_RES_SEARCH_REFERENCE
:
619 debug((char *) "%s| %s: DEBUG: Received a search reference message\n", LogTime(), PROGRAM
);
621 case LDAP_RES_SEARCH_RESULT
:
622 debug((char *) "%s| %s: DEBUG: Received a search result message\n", LogTime(), PROGRAM
);
629 debug((char *) "%s| %s: DEBUG: %d ldap entr%s found with attribute : %s\n", LogTime(), PROGRAM
, max_attr
, max_attr
> 1 || max_attr
== 0 ? "ies" : "y", attribute
);
631 *ret_value
= attr_value
;
636 * call to open ldap server with or without SSL
639 tool_ldap_open(struct main_args
* margs
, char *host
, int port
, char *ssl
)
643 LDAPURLDesc
*url
= NULL
;
644 char *ldapuri
= NULL
;
649 * Use ldap open here to check if TCP connection is possible. If possible use it.
650 * (Not sure if this is the best way)
653 url
= (LDAPURLDesc
*) xmalloc(sizeof(*url
));
654 memset(url
, 0, sizeof(*url
));
655 #ifdef HAVE_LDAP_URL_LUD_SCHEME
657 url
->lud_scheme
= (char *) "ldaps";
659 url
->lud_scheme
= (char *) "ldap";
661 url
->lud_host
= host
;
662 url
->lud_port
= port
;
663 #ifdef HAVE_LDAP_SCOPE_DEFAULT
664 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
666 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
668 #ifdef HAVE_LDAP_URL_DESC2STR
669 ldapuri
= ldap_url_desc2str(url
);
670 #elif defined(HAVE_LDAP_URL_PARSE)
671 rc
= ldap_url_parse(ldapuri
, &url
);
672 if (rc
!= LDAP_SUCCESS
) {
673 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
681 #error "No URL parsing function"
687 rc
= ldap_initialize(&ld
, ldapuri
);
690 if (rc
!= LDAP_SUCCESS
) {
691 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
697 ld
= ldap_init(host
, port
);
699 rc
= ldap_set_defaults(margs
, ld
);
700 if (rc
!= LDAP_SUCCESS
) {
701 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
708 * Try Start TLS first
710 debug((char *) "%s| %s: DEBUG: Set SSL defaults\n", LogTime(), PROGRAM
);
711 rc
= ldap_set_ssl_defaults(margs
);
712 if (rc
!= LDAP_SUCCESS
) {
713 error((char *) "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
720 * Use tls if possible
722 rc
= ldap_start_tls_s(ld
, NULL
, NULL
);
723 if (rc
!= LDAP_SUCCESS
) {
724 error((char *) "%s| %s: ERROR: Error while setting start_tls for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
727 url
= (LDAPURLDesc
*) xmalloc(sizeof(*url
));
728 memset(url
, 0, sizeof(*url
));
729 #ifdef HAVE_LDAP_URL_LUD_SCHEME
730 url
->lud_scheme
= (char *) "ldaps";
732 url
->lud_host
= host
;
733 url
->lud_port
= port
;
734 #ifdef HAVE_LDAP_SCOPE_DEFAULT
735 url
->lud_scope
= LDAP_SCOPE_DEFAULT
;
737 url
->lud_scope
= LDAP_SCOPE_SUBTREE
;
739 #ifdef HAVE_LDAP_URL_DESC2STR
740 ldapuri
= ldap_url_desc2str(url
);
741 #elif defined(HAVE_LDAP_URL_PARSE)
742 rc
= ldap_url_parse(ldapuri
, &url
);
743 if (rc
!= LDAP_SUCCESS
) {
744 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
752 #error "No URL parsing function"
758 rc
= ldap_initialize(&ld
, ldapuri
);
761 if (rc
!= LDAP_SUCCESS
) {
762 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
767 rc
= ldap_set_defaults(margs
, ld
);
768 if (rc
!= LDAP_SUCCESS
) {
769 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
775 #elif defined(HAVE_LDAPSSL_CLIENT_INIT)
776 ld
= ldapssl_init(host
, port
, 1);
778 error((char *) "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n", LogTime(), PROGRAM
, ldapssl_err2string(rc
));
783 rc
= ldap_set_defaults(margs
, ld
);
784 if (rc
!= LDAP_SUCCESS
) {
785 error((char *) "%s| %s: ERROR: Error while setting default options for ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
791 error((char *) "%s| %s: ERROR: SSL not supported by ldap library\n", LogTime(), PROGRAM
);
798 * ldap calls to get attribute from Ldap Directory Server
801 get_memberof(struct main_args
*margs
, char *user
, char *domain
, char *group
)
805 #ifndef HAVE_SUN_LDAP_SDK
808 struct ldap_creds
*lcreds
= NULL
;
812 struct timeval searchtime
;
813 int i
, j
, rc
= 0, kc
= 1;
815 char **attr_value
= NULL
;
816 char *av
= NULL
, *avp
= NULL
;
818 struct hstruct
*hlist
= NULL
;
825 char *ldap_filter_esc
= NULL
;
828 searchtime
.tv_sec
= SEARCH_TIMEOUT
;
829 searchtime
.tv_usec
= 0;
831 * Fill Kerberos memory cache with credential from keytab for SASL/GSSAPI
834 debug((char *) "%s| %s: DEBUG: Setup Kerberos credential cache\n", LogTime(), PROGRAM
);
837 kc
= krb5_create_cache(margs
, domain
);
839 error((char *) "%s| %s: ERROR: Error during setup of Kerberos credential cache\n", LogTime(), PROGRAM
);
843 debug((char *) "%s| %s: DEBUG: Kerberos is not supported. Use username/passwaord with ldap url instead\n", LogTime(), PROGRAM
);
847 if (kc
&& (!margs
->lurl
|| !margs
->luser
| !margs
->lpass
)) {
849 * If Kerberos fails and no url given exit here
854 #ifndef HAVE_SUN_LDAP_SDK
858 ldap_debug
= 127 /* LDAP_DEBUG_TRACE */ ;
859 ldap_debug
= -1 /* LDAP_DEBUG_ANY */ ;
861 (void) ldap_set_option(NULL
, LDAP_OPT_DEBUG_LEVEL
, &ldap_debug
);
863 debug((char *) "%s| %s: DEBUG: Initialise ldap connection\n", LogTime(), PROGRAM
);
867 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM
);
869 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n", LogTime(), PROGRAM
, domain
);
871 * Loop over list of ldap servers of users domain
873 nhosts
= get_ldap_hostname_list(margs
, &hlist
, 0, domain
);
874 for (i
= 0; i
< nhosts
; i
++) {
876 if (hlist
[i
].port
!= -1)
877 port
= hlist
[i
].port
;
878 debug((char *) "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n", LogTime(), PROGRAM
, hlist
[i
].host
, port
);
880 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, margs
->ssl
);
885 * ldap bind with SASL/GSSAPI authentication (only possible if a domain was part of the username)
888 #if defined(HAVE_SASL_H) || defined(HAVE_SASL_SASL_H) || defined(HAVE_SASL_DARWIN)
889 debug((char *) "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n", LogTime(), PROGRAM
);
891 rc
= tool_sasl_bind(ld
, bindp
, margs
->ssl
);
892 if (rc
!= LDAP_SUCCESS
) {
893 error((char *) "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
898 lcreds
= (ldap_creds
*) xmalloc(sizeof(struct ldap_creds
));
899 lcreds
->dn
= bindp
? xstrdup(bindp
) : NULL
;
900 lcreds
->pw
= margs
->ssl
? xstrdup(margs
->ssl
) : NULL
;
901 ldap_set_rebind_proc(ld
, ldap_sasl_rebind
, (char *) lcreds
);
903 debug((char *) "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM
, ld
? "Successfully" : "Failed to", margs
->ssl
? "SSL protected " : "", hlist
[i
].host
, port
);
909 error((char *) "%s| %s: ERROR: SASL not supported on system\n", LogTime(), PROGRAM
);
913 nhosts
= free_hostname_list(&hlist
, nhosts
);
915 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM
, strerror(errno
));
917 bindp
= convert_domain_to_bind_path(domain
);
919 if ((!domain
|| !ld
) && margs
->lurl
&& strstr(margs
->lurl
, "://")) {
921 * If username does not contain a domain and a url was given then try it
923 hostname
= strstr(margs
->lurl
, "://") + 3;
924 ssl
= strstr(margs
->lurl
, "ldaps://");
926 debug((char *) "%s| %s: DEBUG: Enable SSL to ldap servers\n", LogTime(), PROGRAM
);
928 debug((char *) "%s| %s: DEBUG: Canonicalise ldap server name %s\n", LogTime(), PROGRAM
, hostname
);
930 * Loop over list of ldap servers
932 host
= xstrdup(hostname
);
934 if ((p
= strchr(host
, ':'))) {
939 nhosts
= get_hostname_list(margs
, &hlist
, 0, host
);
943 for (i
= 0; i
< nhosts
; i
++) {
945 ld
= tool_ldap_open(margs
, hlist
[i
].host
, port
, ssl
);
949 * ldap bind with username/password authentication
952 debug((char *) "%s| %s: DEBUG: Bind to ldap server with Username/Password\n", LogTime(), PROGRAM
);
953 rc
= ldap_simple_bind_s(ld
, margs
->luser
, margs
->lpass
);
954 if (rc
!= LDAP_SUCCESS
) {
955 error((char *) "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
960 lcreds
= (ldap_creds
*) xmalloc(sizeof(struct ldap_creds
));
961 lcreds
->dn
= xstrdup(margs
->luser
);
962 lcreds
->pw
= xstrdup(margs
->lpass
);
963 ldap_set_rebind_proc(ld
, ldap_simple_rebind
, (char *) lcreds
);
964 debug((char *) "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n", LogTime(), PROGRAM
, ld
? "Successfully" : "Failed to", ssl
? "SSL protected " : "", hlist
[i
].host
, port
);
968 nhosts
= free_hostname_list(&hlist
, nhosts
);
972 bindp
= xstrdup(margs
->lbind
);
974 bindp
= convert_domain_to_bind_path(domain
);
978 debug((char *) "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n", LogTime(), PROGRAM
, strerror(errno
));
983 * ldap search for user
986 * Check if server is AD by querying for attribute samaccountname
989 rc
= check_AD(margs
, ld
);
990 if (rc
!= LDAP_SUCCESS
) {
991 error((char *) "%s| %s: ERROR: Error determining ldap server type: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
998 filter
= (char *) FILTER_AD
;
1000 filter
= (char *) FILTER
;
1002 ldap_filter_esc
= escape_filter(user
);
1004 search_exp
= (char *) xmalloc(strlen(filter
) + strlen(ldap_filter_esc
) + 1);
1005 snprintf(search_exp
, strlen(filter
) + strlen(ldap_filter_esc
) + 1, filter
, ldap_filter_esc
);
1007 if (ldap_filter_esc
)
1008 xfree(ldap_filter_esc
);
1010 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM
, bindp
, search_exp
);
1011 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
1012 search_exp
, NULL
, 0,
1013 NULL
, NULL
, &searchtime
, 0, &res
);
1017 if (rc
!= LDAP_SUCCESS
) {
1018 error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
1024 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
1026 if (ldap_count_entries(ld
, res
) != 0) {
1029 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_AD
, &attr_value
);
1031 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value
);
1035 * Compare group names
1038 for (j
= 0; j
< max_attr
; j
++) {
1040 /* Compare first CN= value assuming it is the same as the group name itself */
1042 if (!strncasecmp("CN=", av
, 3)) {
1044 if ((avp
= strchr(av
, ','))) {
1048 if (debug_enabled
) {
1050 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" in hex UTF-8 is ", LogTime(), PROGRAM
, j
+ 1, av
);
1051 for (n
= 0; av
[n
] != '\0'; n
++)
1052 fprintf(stderr
, "%02x", (unsigned char) av
[n
]);
1053 fprintf(stderr
, "\n");
1055 if (!strcasecmp(group
, av
)) {
1058 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1062 debug((char *) "%s| %s: DEBUG: Entry %d \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1065 * Do recursive group search for AD only since posixgroups can not contain other groups
1067 if (!retval
&& margs
->AD
) {
1068 if (debug_enabled
&& max_attr
> 0) {
1069 debug((char *) "%s| %s: DEBUG: Perform recursive group search\n", LogTime(), PROGRAM
);
1071 for (j
= 0; j
< max_attr
; j
++) {
1074 if (search_group_tree(margs
, ld
, bindp
, av
, group
, 1)) {
1076 if (!strncasecmp("CN=", av
, 3)) {
1078 if ((avp
= strchr(av
, ','))) {
1083 debug((char *) "%s| %s: DEBUG: Entry %d group \"%s\" is (in)direct member of group \"%s\"\n", LogTime(), PROGRAM
, j
+ 1, av
, group
);
1093 for (j
= 0; j
< max_attr
; j
++) {
1094 xfree(attr_value
[j
]);
1100 } else if (ldap_count_entries(ld
, res
) == 0 && margs
->AD
) {
1111 if (!margs
->AD
&& retval
== 0) {
1113 * Check for primary Group membership
1115 debug((char *) "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n", LogTime(), PROGRAM
, group
);
1116 filter
= (char *) FILTER_UID
;
1118 ldap_filter_esc
= escape_filter(user
);
1120 search_exp
= (char *) xmalloc(strlen(filter
) + strlen(ldap_filter_esc
) + 1);
1121 snprintf(search_exp
, strlen(filter
) + strlen(ldap_filter_esc
) + 1, filter
, ldap_filter_esc
);
1123 if (ldap_filter_esc
)
1124 xfree(ldap_filter_esc
);
1126 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM
, bindp
, search_exp
);
1127 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
1128 search_exp
, NULL
, 0,
1129 NULL
, NULL
, &searchtime
, 0, &res
);
1133 debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM
, ldap_count_entries(ld
, res
), ldap_count_entries(ld
, res
) > 1 || ldap_count_entries(ld
, res
) == 0 ? "ies" : "y");
1135 max_attr
= get_attributes(margs
, ld
, res
, ATTRIBUTE_GID
, &attr_value
);
1137 if (max_attr
== 1) {
1138 char **attr_value_2
= NULL
;
1142 filter
= (char *) FILTER_GID
;
1144 ldap_filter_esc
= escape_filter(attr_value
[0]);
1146 search_exp
= (char *) xmalloc(strlen(filter
) + strlen(ldap_filter_esc
) + 1);
1147 snprintf(search_exp
, strlen(filter
) + strlen(ldap_filter_esc
) + 1, filter
, ldap_filter_esc
);
1149 if (ldap_filter_esc
)
1150 xfree(ldap_filter_esc
);
1152 debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM
, bindp
, search_exp
);
1153 rc
= ldap_search_ext_s(ld
, bindp
, LDAP_SCOPE_SUBTREE
,
1154 search_exp
, NULL
, 0,
1155 NULL
, NULL
, &searchtime
, 0, &res
);
1159 max_attr_2
= get_attributes(margs
, ld
, res
, ATTRIBUTE
, &attr_value_2
);
1161 * Compare group names
1164 if (max_attr_2
== 1) {
1166 /* Compare first CN= value assuming it is the same as the group name itself */
1167 av
= attr_value_2
[0];
1168 if (!strcasecmp(group
, av
)) {
1170 debug((char *) "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n", LogTime(), PROGRAM
, av
, group
);
1172 debug((char *) "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n", LogTime(), PROGRAM
, av
, group
);
1179 for (j
= 0; j
< max_attr_2
; j
++) {
1180 xfree(attr_value_2
[j
]);
1182 xfree(attr_value_2
);
1183 attr_value_2
= NULL
;
1187 debug((char *) "%s| %s: DEBUG: Users primary group %s %s\n", LogTime(), PROGRAM
, retval
? "matches" : "does not match", group
);
1190 debug((char *) "%s| %s: DEBUG: Did not find ldap entry for group %s\n", LogTime(), PROGRAM
, group
);
1195 for (j
= 0; j
< max_attr
; j
++) {
1196 xfree(attr_value
[j
]);
1202 rc
= ldap_unbind(ld
);
1204 if (rc
!= LDAP_SUCCESS
) {
1205 error((char *) "%s| %s: ERROR: Error unbind ldap server: %s\n", LogTime(), PROGRAM
, ldap_err2string(rc
));
1207 debug((char *) "%s| %s: DEBUG: Unbind ldap server\n", LogTime(), PROGRAM
);