55 char *convert_domain_to_bind_path(
char *domain);
56 char *escape_filter(
char *filter);
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 ,
char ***out_val );
79 size_t get_bin_attributes(LDAP *
ld, LDAPMessage * res,
80 const char *attribute ,
char ***out_val,
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
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)
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)
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,
nullptr,
nullptr,
123 #elif HAVE_LDAP_REBIND_PROC
124 #if HAVE_SASL_H || HAVE_SASL_SASL_H
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)
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)
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,
nullptr,
nullptr,
152 #elif HAVE_LDAP_REBIND_FUNCTION
153 #ifndef LDAP_REFERRALS
154 #define LDAP_REFERRALS
156 #if HAVE_SASL_H || HAVE_SASL_SASL_H
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)
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)
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,
nullptr,
nullptr,
192 #error "No rebind functione defined"
195 #if HAVE_SASL_H || HAVE_SASL_SASL_H
196 static LDAP_REBIND_PROC ldap_sasl_rebind;
199 ldap_sasl_rebind(LDAP *
ld, LDAP_CONST
char *, ber_tag_t,
200 ber_int_t,
void *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,
211 ber_int_t,
void *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,
nullptr,
nullptr,
226 convert_domain_to_bind_path(
char *domain)
228 char *dp, *bindp =
nullptr, *bp =
nullptr;
234 for (dp = domain; *dp; ++dp) {
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;
301 LDAPMessage *res =
nullptr;
302 char **attr_value =
nullptr;
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",
317 rc = ldap_search_ext_s(
ld, (
char *)
"", LDAP_SCOPE_BASE,
318 (
char *) FILTER_SCHEMA,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
320 if (rc == LDAP_SUCCESS)
321 max_attr = get_attributes(
ld, res, ATTRIBUTE_SCHEMA, &attr_value);
327 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
329 rc = ldap_search_ext_s(
ld, attr_value[0], LDAP_SCOPE_SUBTREE,
330 (
char *) FILTER_SAM,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
331 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
LogTime(),
332 PROGRAM, ldap_count_entries(
ld, res), ldap_count_entries(
ld,
333 res) > 1 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
334 if (ldap_count_entries(
ld, res) > 0)
338 "%s| %s: DEBUG: Did not find ldap entry for subschemasubentry\n",
341 "%s| %s: DEBUG: Determined ldap server %sas an Active Directory server\n",
348 for (j = 0; j < max_attr; ++j) {
349 xfree(attr_value[j]);
359 search_group_tree(
struct main_args *margs, LDAP *
ld,
char *bindp,
360 char *ldap_group,
char *group,
int depth)
362 LDAPMessage *res =
nullptr;
363 char **attr_value =
nullptr;
365 char *filter =
nullptr;
366 char *search_exp =
nullptr;
368 int rc = 0, retval = 0;
370 char *ldap_filter_esc =
nullptr;
371 struct timeval searchtime;
373 #define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
374 #define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
376 searchtime.tv_sec = SEARCH_TIMEOUT;
377 searchtime.tv_usec = 0;
380 filter = (
char *) FILTER_GROUP_AD;
382 filter = (
char *) FILTER_GROUP;
384 ldap_filter_esc = escape_filter(ldap_group);
386 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
387 search_exp = (
char *)
xmalloc(se_len);
388 snprintf(search_exp, se_len, filter, ldap_filter_esc);
390 xfree(ldap_filter_esc);
392 if (depth > margs->
mdepth) {
393 debug((
char *)
"%s| %s: DEBUG: Max search depth reached %d>%d\n",
399 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
401 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
402 nullptr,
nullptr, &searchtime, 0, &res);
405 if (rc != LDAP_SUCCESS) {
406 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
411 ldap_count_entries(
ld, res), ldap_count_entries(
ld, res) > 1
412 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
415 max_attr = get_attributes(
ld, res, ATTRIBUTE_AD, &attr_value);
417 max_attr = get_attributes(
ld, res, ATTRIBUTE, &attr_value);
424 for (
size_t j = 0; j < max_attr; ++j) {
429 if (!strncasecmp(
"CN=", av, 3)) {
432 if ((avp = strchr(av,
','))) {
438 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" in hex UTF-8 is ",
LogTime(),
PROGRAM, j + 1, av);
439 for (n = 0; av[n] !=
'\0'; ++n)
440 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
441 fprintf(stderr,
"\n");
443 if (!strcasecmp(group, av)) {
445 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" matches group name \"%s\"\n",
LogTime(),
PROGRAM,
449 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" does not match group name \"%s\"\n",
LogTime(),
455 "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
458 if (search_group_tree(margs,
ld, bindp, av, group, ldepth)) {
460 if (!strncasecmp(
"CN=", av, 3)) {
463 if ((avp = strchr(av,
','))) {
468 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" is member of group named \"%s\"\n",
LogTime(),
480 for (
size_t j = 0; j < max_attr; ++j) {
481 xfree(attr_value[j]);
491 ldap_set_defaults(LDAP *
ld)
494 #if LDAP_OPT_NETWORK_TIMEOUT
498 rc = ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &val);
499 if (rc != LDAP_SUCCESS) {
501 "%s| %s: DEBUG: Error while setting protocol version: %s\n",
505 rc = ldap_set_option(
ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
506 if (rc != LDAP_SUCCESS) {
507 debug((
char *)
"%s| %s: DEBUG: Error while setting referrals off: %s\n",
511 #if LDAP_OPT_NETWORK_TIMEOUT
512 tv.tv_sec = CONNECT_TIMEOUT;
514 rc = ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
515 if (rc != LDAP_SUCCESS) {
517 "%s| %s: DEBUG: Error while setting network timeout: %s\n",
526 ldap_set_ssl_defaults(
struct main_args *margs)
528 #if HAVE_OPENLDAP || HAVE_LDAPSSL_CLIENT_INIT
533 #elif HAVE_LDAPSSL_CLIENT_INIT
534 char *ssl_certdbpath =
nullptr;
539 char *ssl_cacertfile =
nullptr;
540 char *ssl_cacertdir =
nullptr;
542 "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
544 val = LDAP_OPT_X_TLS_DEMAND;
545 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
546 if (rc != LDAP_SUCCESS) {
548 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
552 ssl_cacertfile =
xstrdup(getenv(
"TLS_CACERTFILE"));
553 if (!ssl_cacertfile) {
554 ssl_cacertfile =
xstrdup(
"/etc/ssl/certs/cert.pem");
556 if (access(ssl_cacertfile, R_OK) == 0) {
558 "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
560 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTFILE,
562 xfree(ssl_cacertfile);
563 if (rc != LDAP_OPT_SUCCESS) {
565 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
571 "%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",
573 xfree(ssl_cacertfile);
574 ssl_cacertdir =
xstrdup(getenv(
"TLS_CACERTDIR"));
575 if (!ssl_cacertdir) {
576 ssl_cacertdir =
xstrdup(
"/etc/ssl/certs");
578 if (access(ssl_cacertdir, R_OK) == 0) {
580 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
582 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTDIR,
584 xfree(ssl_cacertdir);
585 if (rc != LDAP_OPT_SUCCESS) {
587 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
593 "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
595 xfree(ssl_cacertdir);
601 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
603 val = LDAP_OPT_X_TLS_ALLOW;
604 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
605 if (rc != LDAP_SUCCESS) {
607 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
612 #elif HAVE_LDAPSSL_CLIENT_INIT
620 const auto envp = getenv(
"SSL_CERTDBPATH");
621 ssl_certdbpath =
xstrdup(envp ? envp :
"/etc/certs");
624 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable SSL_CERTDBPATH)\n",
627 rc = ldapssl_advclientauth_init(ssl_certdbpath,
nullptr, 0,
nullptr,
nullptr, 0,
630 rc = ldapssl_advclientauth_init(ssl_certdbpath,
nullptr, 0,
nullptr,
nullptr, 0,
633 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
636 xfree(ssl_certdbpath);
637 if (rc != LDAP_SUCCESS) {
639 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
645 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
652 get_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
656 char **attr_value = *ret_value;
662 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
664 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
665 msg = ldap_next_entry(
ld, msg)) {
667 switch (ldap_msgtype(msg)) {
669 case LDAP_RES_SEARCH_ENTRY: {
670 BerElement *b =
nullptr;
671 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
672 attr = ldap_next_attribute(
ld, msg, b)) {
673 if (strcasecmp(attr, attribute) == 0) {
674 struct berval **values;
677 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
678 for (
int il = 0; values[il] !=
nullptr; ++il) {
682 (max_attr + 1) *
sizeof(
char *));
686 attr_value[max_attr] =
687 (
char *)
xmalloc(values[il]->bv_len + 1);
688 memcpy(attr_value[max_attr], values[il]->bv_val,
690 attr_value[max_attr][values[il]->bv_len] = 0;
694 ber_bvecfree(values);
701 case LDAP_RES_SEARCH_REFERENCE:
703 "%s| %s: DEBUG: Received a search reference message\n",
706 case LDAP_RES_SEARCH_RESULT:
707 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
715 debug((
char *)
"%s| %s: DEBUG: %zu ldap entr%s found with attribute : %s\n",
LogTime(),
PROGRAM,
716 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
718 *ret_value = attr_value;
723 get_bin_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
724 char ***ret_value,
int **ret_len)
727 char **attr_value = *ret_value;
728 int *attr_len = *ret_len;
734 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
736 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
737 msg = ldap_next_entry(
ld, msg)) {
739 switch (ldap_msgtype(msg)) {
741 case LDAP_RES_SEARCH_ENTRY: {
742 BerElement *b =
nullptr;
743 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
744 attr = ldap_next_attribute(
ld, msg, b)) {
745 if (strcasecmp(attr, attribute) == 0) {
746 struct berval **values;
749 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
750 for (
int il = 0; values[il] !=
nullptr; ++il) {
754 (max_attr + 1) *
sizeof(
char *));
760 (max_attr + 1) *
sizeof(
int));
764 attr_value[max_attr] =
765 (
char *)
xmalloc(values[il]->bv_len + 1);
766 memcpy(attr_value[max_attr], values[il]->bv_val,
768 attr_value[max_attr][values[il]->bv_len] = 0;
769 attr_len[max_attr] = values[il]->bv_len;
773 ber_bvecfree(values);
780 case LDAP_RES_SEARCH_REFERENCE:
782 "%s| %s: DEBUG: Received a search reference message\n",
785 case LDAP_RES_SEARCH_RESULT:
786 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
794 debug((
char *)
"%s| %s: DEBUG: %zu ldap entr%s found with attribute : %s\n",
LogTime(),
PROGRAM,
795 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
797 *ret_value = attr_value;
806 tool_ldap_open(
struct main_args * margs,
char *host,
int port,
char *ssl)
810 LDAPURLDesc *url =
nullptr;
811 char *ldapuri =
nullptr;
820 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
821 memset(url, 0,
sizeof(*url));
822 #if HAVE_LDAP_URL_LUD_SCHEME
824 url->lud_scheme =
xstrdup(
"ldaps");
826 url->lud_scheme =
xstrdup(
"ldap");
829 url->lud_port =
port;
830 #if HAVE_LDAP_SCOPE_DEFAULT
831 url->lud_scope = LDAP_SCOPE_DEFAULT;
833 url->lud_scope = LDAP_SCOPE_SUBTREE;
835 #if HAVE_LDAP_URL_DESC2STR
836 ldapuri = ldap_url_desc2str(url);
837 #elif HAVE_LDAP_URL_PARSE
838 rc = ldap_url_parse(ldapuri, &url);
839 if (rc != LDAP_SUCCESS) {
840 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
843 ldap_free_urldesc(url);
847 #error "No URL parsing function"
849 ldap_free_urldesc(url);
850 rc = ldap_initialize(&
ld, ldapuri);
852 if (rc != LDAP_SUCCESS) {
854 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
856 ldap_unbind_ext(
ld,
nullptr,
nullptr);
861 ld = ldap_init(host,
port);
863 rc = ldap_set_defaults(
ld);
864 if (rc != LDAP_SUCCESS) {
866 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
868 ldap_unbind_ext(
ld,
nullptr,
nullptr);
877 rc = ldap_set_ssl_defaults(margs);
878 if (rc != LDAP_SUCCESS) {
880 "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n",
882 ldap_unbind_ext(
ld,
nullptr,
nullptr);
890 rc = ldap_start_tls_s(
ld,
nullptr,
nullptr);
891 if (rc != LDAP_SUCCESS) {
893 "%s| %s: WARNING: Error while setting start_tls for ldap server: %s\n",
895 ldap_unbind_ext(
ld,
nullptr,
nullptr);
897 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
898 memset(url, 0,
sizeof(*url));
899 #if HAVE_LDAP_URL_LUD_SCHEME
900 url->lud_scheme =
xstrdup(
"ldaps");
903 url->lud_port =
port;
904 #if HAVE_LDAP_SCOPE_DEFAULT
905 url->lud_scope = LDAP_SCOPE_DEFAULT;
907 url->lud_scope = LDAP_SCOPE_SUBTREE;
909 #if HAVE_LDAP_URL_DESC2STR
910 ldapuri = ldap_url_desc2str(url);
911 #elif HAVE_LDAP_URL_PARSE
912 rc = ldap_url_parse(ldapuri, &url);
913 if (rc != LDAP_SUCCESS) {
914 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
917 ldap_free_urldesc(url);
921 #error "No URL parsing function"
923 ldap_free_urldesc(url);
924 rc = ldap_initialize(&
ld, ldapuri);
926 if (rc != LDAP_SUCCESS) {
928 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
930 ldap_unbind_ext(
ld,
nullptr,
nullptr);
934 rc = ldap_set_defaults(
ld);
935 if (rc != LDAP_SUCCESS) {
937 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
939 ldap_unbind_ext(
ld,
nullptr,
nullptr);
944 #elif HAVE_LDAPSSL_CLIENT_INIT
945 ld = ldapssl_init(host,
port, 1);
948 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
950 ldap_unbind_ext(
ld,
nullptr,
nullptr);
954 rc = ldap_set_defaults(
ld);
955 if (rc != LDAP_SUCCESS) {
957 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
959 ldap_unbind_ext(
ld,
nullptr,
nullptr);
964 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
979 #if !HAVE_SUN_LDAP_SDK
983 char *bindp =
nullptr;
984 char *filter =
nullptr;
987 struct timeval searchtime;
990 char **attr_value =
nullptr;
992 struct hstruct *hlist =
nullptr;
994 char *ldap_filter_esc =
nullptr;
996 searchtime.tv_sec = SEARCH_TIMEOUT;
997 searchtime.tv_usec = 0;
1002 debug((
char *)
"%s| %s: DEBUG: Setup Kerberos credential cache\n",
1009 "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n",
1012 kc = krb5_create_cache(domain, margs->
principal);
1015 "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",
1022 "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n",
1034 #if !HAVE_SUN_LDAP_SDK
1041 (void) ldap_set_option(
nullptr, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
1043 debug((
char *)
"%s| %s: DEBUG: Initialise ldap connection\n",
LogTime(),
1046 if (domain && !kc) {
1048 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1052 "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n",
1058 for (
size_t i = 0; i < nhosts; ++i) {
1060 if (hlist[i].
port != -1)
1063 "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n",
1066 ld = tool_ldap_open(margs, hlist[i].
host,
port, margs->
ssl);
1074 #if HAVE_SASL_H || HAVE_SASL_SASL_H
1076 "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n",
1079 rc = tool_sasl_bind(
ld, bindp, margs->
ssl);
1080 if (rc != LDAP_SUCCESS) {
1082 "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n",
1084 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1089 lcreds->
dn =
nullptr;
1091 ldap_set_rebind_proc(
ld, ldap_sasl_rebind, (
char *) lcreds);
1092 if (
ld !=
nullptr) {
1094 "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n",
1096 margs->
ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1100 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1102 error((
char *)
"%s| %s: ERROR: SASL not supported on system\n",
1108 if (
ld ==
nullptr) {
1110 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1116 bindp = convert_domain_to_bind_path(domain);
1119 if ((!domain || !
ld) && margs->
lurl && strstr(margs->
lurl,
"://")) {
1123 char *ssl =
nullptr;
1128 hostname = strstr(margs->
lurl,
"://") + 3;
1129 ssl = strstr(margs->
lurl,
"ldaps://");
1131 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1134 debug((
char *)
"%s| %s: DEBUG: Canonicalise ldap server name %s\n",
1141 if ((p = strchr(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);
1162 "%s| %s: DEBUG: Bind to ldap server with Username/Password\n",
1164 rc = ldap_sasl_bind_s(
ld, margs->
luser, LDAP_SASL_SIMPLE, &cred,
1165 nullptr,
nullptr,
nullptr);
1166 if (rc != LDAP_SUCCESS) {
1168 "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n",
1170 ldap_unbind_ext(
ld,
nullptr,
nullptr);
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",
1181 ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1190 bindp = convert_domain_to_bind_path(domain);
1193 if (
ld ==
nullptr) {
1195 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1207 rc = check_AD(margs,
ld);
1208 if (rc != LDAP_SUCCESS) {
1210 "%s| %s: ERROR: Error determining ldap server type: %s\n",
1212 ldap_unbind_ext(
ld,
nullptr,
nullptr);
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",
1233 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
1234 nullptr,
nullptr, &searchtime, 0, &res);
1237 if (rc != LDAP_SUCCESS) {
1238 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
1240 ldap_unbind_ext(
ld,
nullptr,
nullptr);
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);
1261 for (
size_t k = 0; k < max_attr; ++k) {
1266 if (!strncasecmp(
"CN=", av, 3)) {
1267 char *avp =
nullptr;
1269 if ((avp = strchr(av,
','))) {
1274 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" in hex UTF-8 is ",
LogTime(),
PROGRAM, k + 1, av);
1275 for (
unsigned int n = 0; av[n] !=
'\0'; ++n)
1276 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
1277 fprintf(stderr,
"\n");
1279 if (!strcasecmp(group, av)) {
1282 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" matches group name \"%s\"\n",
LogTime(),
1287 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" does not match group name \"%s\"\n",
LogTime(),
1293 if (!retval && margs->
AD) {
1296 "%s| %s: DEBUG: Perform recursive group search\n",
1299 for (
size_t j = 0; j < max_attr; ++j) {
1303 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1305 if (!strncasecmp(
"CN=", av, 3)) {
1306 char *avp =
nullptr;
1308 if ((avp = strchr(av,
','))) {
1313 debug((
char *)
"%s| %s: DEBUG: Entry %zu group \"%s\" is (in)direct member of group \"%s\"\n",
1324 for (
size_t j = 0; j < max_attr; ++j) {
1325 xfree(attr_value[j]);
1330 }
else if (ldap_count_entries(
ld, res) == 0 && margs->
AD) {
1332 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1346 "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n",
1349 filter = (
char *) FILTER_AD;
1351 filter = (
char *) FILTER_UID;
1353 ldap_filter_esc = escape_filter(user);
1355 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1356 search_exp = (
char *)
xmalloc(se_len);
1357 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1359 xfree(ldap_filter_esc);
1362 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1364 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr,
1365 0,
nullptr,
nullptr, &searchtime, 0, &res);
1368 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
LogTime(),
1369 PROGRAM, ldap_count_entries(
ld, res), ldap_count_entries(
ld,
1370 res) > 1 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1376 get_attributes(
ld, res, ATTRIBUTE_GID_AD, &attr_value);
1378 max_attr = get_attributes(
ld, res, ATTRIBUTE_GID, &attr_value);
1381 if (max_attr == 1) {
1382 char **attr_value_2 =
nullptr;
1383 size_t max_attr_2 = 0;
1386 char **attr_value_3 =
nullptr;
1387 int *attr_len_3 =
nullptr;
1388 size_t max_attr_3 = 0;
1389 uint32_t gid = atoi(attr_value[0]);
1393 debug((
char *)
"%s| %s: DEBUG: Got primaryGroupID %u\n",
1396 get_bin_attributes(
ld, res, ATTRIBUTE_SID, &attr_value_3,
1399 if (max_attr_3 == 1) {
1400 int len = attr_len_3[0];
1403 "%s| %s: ERROR: Length %d is too short for objectSID\n",
1408 attr_value_3[0][len - 1] = ((gid >> 24) & 0xff);
1409 attr_value_3[0][len - 2] = ((gid >> 16) & 0xff);
1410 attr_value_3[0][len - 3] = ((gid >> 8) & 0xff);
1411 attr_value_3[0][len - 4] = ((gid >> 0) & 0xff);
1413 #define FILTER_SID_1 "(objectSID="
1414 #define FILTER_SID_2 ")"
1417 strlen(FILTER_SID_1) + len * 3 +
1418 strlen(FILTER_SID_2) + 1;
1419 search_exp = (
char *)
xmalloc(se_len);
1420 snprintf(search_exp, se_len,
"%s", FILTER_SID_1);
1422 for (
int j = 0; j < len; j++) {
1424 snprintf(search_exp, se_len,
"%s\\%02x", se,
1425 attr_value_3[0][j] & 0xFF);
1429 snprintf(search_exp, se_len,
"%s%s", se, FILTER_SID_2);
1433 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1435 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1436 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0,
1440 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
1442 ldap_count_entries(
ld, res) > 1
1443 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1451 for (j = 0; j < max_attr_3; ++j) {
1452 xfree(attr_value_3[j]);
1461 filter = (
char *) FILTER_GID;
1463 ldap_filter_esc = escape_filter(attr_value[0]);
1465 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1466 search_exp = (
char *)
xmalloc(se_len);
1467 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1469 xfree(ldap_filter_esc);
1472 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1474 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1475 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
1482 get_attributes(
ld, res, ATTRIBUTE_DN, &attr_value_2);
1485 get_attributes(
ld, res, ATTRIBUTE, &attr_value_2);
1494 if (max_attr_2 == 1) {
1496 char *av = attr_value_2[0];
1497 if (!strncasecmp(
"CN=", av, 3)) {
1498 char *avp =
nullptr;
1500 if ((avp = strchr(av,
','))) {
1504 if (!strcasecmp(group, av)) {
1507 "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n",
1511 "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n",
1518 if (!retval && margs->
AD) {
1521 "%s| %s: DEBUG: Perform recursive group search\n",
1524 for (
size_t j = 0; j < max_attr_2; ++j) {
1527 av = attr_value_2[j];
1528 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1530 if (!strncasecmp(
"CN=", av, 3)) {
1531 char *avp =
nullptr;
1533 if ((avp = strchr(av,
','))) {
1538 debug((
char *)
"%s| %s: DEBUG: Entry %zu group \"%s\" is (in)direct member of group \"%s\"\n",
1551 for (j = 0; j < max_attr_2; ++j) {
1552 xfree(attr_value_2[j]);
1557 debug((
char *)
"%s| %s: DEBUG: Users primary group %s %s\n",
1564 "%s| %s: DEBUG: Did not find ldap entry for group %s\n",
1571 for (
size_t j = 0; j < max_attr; ++j) {
1572 xfree(attr_value[j]);
1577 rc = ldap_unbind_ext(
ld,
nullptr,
nullptr);
1579 if (rc != LDAP_SUCCESS) {
1580 error((
char *)
"%s| %s: ERROR: Error unbind ldap server: %s\n",