55char *convert_domain_to_bind_path(
char *domain);
56char *escape_filter(
char *filter);
58int ldap_set_defaults(LDAP *
ld);
59int ldap_set_ssl_defaults(
struct main_args *margs);
60LDAP *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)"
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"
77size_t get_attributes(LDAP *
ld, LDAPMessage * res,
78 const char *attribute ,
char ***out_val );
79size_t get_bin_attributes(LDAP *
ld, LDAPMessage * res,
80 const char *attribute ,
char ***out_val,
82int 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
89static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
91static int LDAP_CALL LDAP_CALLBACK
92ldap_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);
104static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
106static int LDAP_CALL LDAP_CALLBACK
107ldap_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 || HAVE_SASL_DARWIN
125static LDAP_REBIND_PROC ldap_sasl_rebind;
128ldap_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);
136static LDAP_REBIND_PROC ldap_simple_rebind;
139ldap_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 || HAVE_SASL_DARWIN
157static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
160ldap_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);
172static LDAP_REBIND_FUNCTION ldap_simple_rebind;
175ldap_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 || HAVE_SASL_DARWIN
196static LDAP_REBIND_PROC ldap_sasl_rebind;
199ldap_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);
207static LDAP_REBIND_PROC ldap_simple_rebind;
210ldap_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,
226convert_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) {
260escape_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;
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);
326 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
328 rc = ldap_search_ext_s(
ld, attr_value[0], LDAP_SCOPE_SUBTREE,
329 (
char *) FILTER_SAM,
nullptr, 0,
nullptr,
nullptr, &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",
347 for (j = 0; j < max_attr; ++j) {
348 xfree(attr_value[j]);
357search_group_tree(
struct main_args *margs, LDAP *
ld,
char *bindp,
358 char *ldap_group,
char *group,
int depth)
360 LDAPMessage *res =
nullptr;
361 char **attr_value =
nullptr;
363 char *filter =
nullptr;
364 char *search_exp =
nullptr;
366 int rc = 0, retval = 0;
368 char *ldap_filter_esc =
nullptr;
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",
397 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
399 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
400 nullptr,
nullptr, &searchtime, 0, &res);
403 if (rc != LDAP_SUCCESS) {
404 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
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);
422 for (
size_t j = 0; j < max_attr; ++j) {
427 if (!strncasecmp(
"CN=", av, 3)) {
430 if ((avp = strchr(av,
','))) {
436 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" in hex UTF-8 is ",
LogTime(),
PROGRAM, j + 1, av);
437 for (n = 0; av[n] !=
'\0'; ++n)
438 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
439 fprintf(stderr,
"\n");
441 if (!strcasecmp(group, av)) {
443 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" matches group name \"%s\"\n",
LogTime(),
PROGRAM,
447 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" does not match group name \"%s\"\n",
LogTime(),
453 "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
456 if (search_group_tree(margs,
ld, bindp, av, group, ldepth)) {
458 if (!strncasecmp(
"CN=", av, 3)) {
461 if ((avp = strchr(av,
','))) {
466 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" is member of group named \"%s\"\n",
LogTime(),
478 for (
size_t j = 0; j < max_attr; ++j) {
479 xfree(attr_value[j]);
489ldap_set_defaults(LDAP *
ld)
492#if LDAP_OPT_NETWORK_TIMEOUT
496 rc = ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &val);
497 if (rc != LDAP_SUCCESS) {
499 "%s| %s: DEBUG: Error while setting protocol version: %s\n",
503 rc = ldap_set_option(
ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
504 if (rc != LDAP_SUCCESS) {
505 debug((
char *)
"%s| %s: DEBUG: Error while setting referrals off: %s\n",
509#if LDAP_OPT_NETWORK_TIMEOUT
510 tv.tv_sec = CONNECT_TIMEOUT;
512 rc = ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
513 if (rc != LDAP_SUCCESS) {
515 "%s| %s: DEBUG: Error while setting network timeout: %s\n",
524ldap_set_ssl_defaults(
struct main_args *margs)
526#if HAVE_OPENLDAP || HAVE_LDAPSSL_CLIENT_INIT
531#elif HAVE_LDAPSSL_CLIENT_INIT
532 char *ssl_certdbpath =
nullptr;
537 char *ssl_cacertfile =
nullptr;
538 char *ssl_cacertdir =
nullptr;
540 "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
542 val = LDAP_OPT_X_TLS_DEMAND;
543 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
544 if (rc != LDAP_SUCCESS) {
546 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
550 ssl_cacertfile =
xstrdup(getenv(
"TLS_CACERTFILE"));
551 if (!ssl_cacertfile) {
552 ssl_cacertfile =
xstrdup(
"/etc/ssl/certs/cert.pem");
554 if (access(ssl_cacertfile, R_OK) == 0) {
556 "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
558 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTFILE,
560 xfree(ssl_cacertfile);
561 if (rc != LDAP_OPT_SUCCESS) {
563 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
569 "%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",
571 xfree(ssl_cacertfile);
572 ssl_cacertdir =
xstrdup(getenv(
"TLS_CACERTDIR"));
573 if (!ssl_cacertdir) {
574 ssl_cacertdir =
xstrdup(
"/etc/ssl/certs");
576 if (access(ssl_cacertdir, R_OK) == 0) {
578 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
580 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTDIR,
582 xfree(ssl_cacertdir);
583 if (rc != LDAP_OPT_SUCCESS) {
585 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
591 "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
593 xfree(ssl_cacertdir);
599 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
601 val = LDAP_OPT_X_TLS_ALLOW;
602 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
603 if (rc != LDAP_SUCCESS) {
605 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
610#elif HAVE_LDAPSSL_CLIENT_INIT
618 ssl_certdbpath = getenv(
"SSL_CERTDBPATH");
619 if (!ssl_certdbpath) {
620 ssl_certdbpath =
xstrdup(
"/etc/certs");
623 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable SSL_CERTDBPATH)\n",
626 rc = ldapssl_advclientauth_init(ssl_certdbpath,
nullptr, 0,
nullptr,
nullptr, 0,
629 rc = ldapssl_advclientauth_init(ssl_certdbpath,
nullptr, 0,
nullptr,
nullptr, 0,
632 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
635 xfree(ssl_certdbpath);
636 if (rc != LDAP_SUCCESS) {
638 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
644 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
651get_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
655 char **attr_value = *ret_value;
661 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
663 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
664 msg = ldap_next_entry(
ld, msg)) {
666 switch (ldap_msgtype(msg)) {
668 case LDAP_RES_SEARCH_ENTRY: {
669 BerElement *b =
nullptr;
670 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
671 attr = ldap_next_attribute(
ld, msg, b)) {
672 if (strcasecmp(attr, attribute) == 0) {
673 struct berval **values;
676 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
677 for (
int il = 0; values[il] !=
nullptr; ++il) {
681 (max_attr + 1) *
sizeof(
char *));
685 attr_value[max_attr] =
686 (
char *)
xmalloc(values[il]->bv_len + 1);
687 memcpy(attr_value[max_attr], values[il]->bv_val,
689 attr_value[max_attr][values[il]->bv_len] = 0;
693 ber_bvecfree(values);
700 case LDAP_RES_SEARCH_REFERENCE:
702 "%s| %s: DEBUG: Received a search reference message\n",
705 case LDAP_RES_SEARCH_RESULT:
706 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
714 debug((
char *)
"%s| %s: DEBUG: %zu ldap entr%s found with attribute : %s\n",
LogTime(),
PROGRAM,
715 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
717 *ret_value = attr_value;
722get_bin_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
723 char ***ret_value,
int **ret_len)
726 char **attr_value = *ret_value;
727 int *attr_len = *ret_len;
733 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
735 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
736 msg = ldap_next_entry(
ld, msg)) {
738 switch (ldap_msgtype(msg)) {
740 case LDAP_RES_SEARCH_ENTRY: {
741 BerElement *b =
nullptr;
742 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
743 attr = ldap_next_attribute(
ld, msg, b)) {
744 if (strcasecmp(attr, attribute) == 0) {
745 struct berval **values;
748 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
749 for (
int il = 0; values[il] !=
nullptr; ++il) {
753 (max_attr + 1) *
sizeof(
char *));
759 (max_attr + 1) *
sizeof(
int));
763 attr_value[max_attr] =
764 (
char *)
xmalloc(values[il]->bv_len + 1);
765 memcpy(attr_value[max_attr], values[il]->bv_val,
767 attr_value[max_attr][values[il]->bv_len] = 0;
768 attr_len[max_attr] = values[il]->bv_len;
772 ber_bvecfree(values);
779 case LDAP_RES_SEARCH_REFERENCE:
781 "%s| %s: DEBUG: Received a search reference message\n",
784 case LDAP_RES_SEARCH_RESULT:
785 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
793 debug((
char *)
"%s| %s: DEBUG: %zu ldap entr%s found with attribute : %s\n",
LogTime(),
PROGRAM,
794 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
796 *ret_value = attr_value;
805tool_ldap_open(
struct main_args * margs,
char *host,
int port,
char *ssl)
809 LDAPURLDesc *url =
nullptr;
810 char *ldapuri =
nullptr;
819 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
820 memset(url, 0,
sizeof(*url));
821#if HAVE_LDAP_URL_LUD_SCHEME
823 url->lud_scheme =
xstrdup(
"ldaps");
825 url->lud_scheme =
xstrdup(
"ldap");
828 url->lud_port =
port;
829#if HAVE_LDAP_SCOPE_DEFAULT
830 url->lud_scope = LDAP_SCOPE_DEFAULT;
832 url->lud_scope = LDAP_SCOPE_SUBTREE;
834#if HAVE_LDAP_URL_DESC2STR
835 ldapuri = ldap_url_desc2str(url);
836#elif HAVE_LDAP_URL_PARSE
837 rc = ldap_url_parse(ldapuri, &url);
838 if (rc != LDAP_SUCCESS) {
839 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
842 ldap_free_urldesc(url);
846#error "No URL parsing function"
848 ldap_free_urldesc(url);
849 rc = ldap_initialize(&
ld, ldapuri);
851 if (rc != LDAP_SUCCESS) {
853 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
855 ldap_unbind_ext(
ld,
nullptr,
nullptr);
860 ld = ldap_init(host,
port);
862 rc = ldap_set_defaults(
ld);
863 if (rc != LDAP_SUCCESS) {
865 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
867 ldap_unbind_ext(
ld,
nullptr,
nullptr);
876 rc = ldap_set_ssl_defaults(margs);
877 if (rc != LDAP_SUCCESS) {
879 "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n",
881 ldap_unbind_ext(
ld,
nullptr,
nullptr);
889 rc = ldap_start_tls_s(
ld,
nullptr,
nullptr);
890 if (rc != LDAP_SUCCESS) {
892 "%s| %s: WARNING: Error while setting start_tls for ldap server: %s\n",
894 ldap_unbind_ext(
ld,
nullptr,
nullptr);
896 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
897 memset(url, 0,
sizeof(*url));
898#if HAVE_LDAP_URL_LUD_SCHEME
899 url->lud_scheme =
xstrdup(
"ldaps");
902 url->lud_port =
port;
903#if HAVE_LDAP_SCOPE_DEFAULT
904 url->lud_scope = LDAP_SCOPE_DEFAULT;
906 url->lud_scope = LDAP_SCOPE_SUBTREE;
908#if HAVE_LDAP_URL_DESC2STR
909 ldapuri = ldap_url_desc2str(url);
910#elif HAVE_LDAP_URL_PARSE
911 rc = ldap_url_parse(ldapuri, &url);
912 if (rc != LDAP_SUCCESS) {
913 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
916 ldap_free_urldesc(url);
920#error "No URL parsing function"
922 ldap_free_urldesc(url);
923 rc = ldap_initialize(&
ld, ldapuri);
925 if (rc != LDAP_SUCCESS) {
927 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
929 ldap_unbind_ext(
ld,
nullptr,
nullptr);
933 rc = ldap_set_defaults(
ld);
934 if (rc != LDAP_SUCCESS) {
936 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
938 ldap_unbind_ext(
ld,
nullptr,
nullptr);
943#elif HAVE_LDAPSSL_CLIENT_INIT
944 ld = ldapssl_init(host,
port, 1);
947 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
949 ldap_unbind_ext(
ld,
nullptr,
nullptr);
953 rc = ldap_set_defaults(
ld);
954 if (rc != LDAP_SUCCESS) {
956 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
958 ldap_unbind_ext(
ld,
nullptr,
nullptr);
963 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
978#if !HAVE_SUN_LDAP_SDK
982 char *bindp =
nullptr;
983 char *filter =
nullptr;
986 struct timeval searchtime;
989 char **attr_value =
nullptr;
991 struct hstruct *hlist =
nullptr;
993 char *ldap_filter_esc =
nullptr;
995 searchtime.tv_sec = SEARCH_TIMEOUT;
996 searchtime.tv_usec = 0;
1001 debug((
char *)
"%s| %s: DEBUG: Setup Kerberos credential cache\n",
1008 "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n",
1011 kc = krb5_create_cache(domain, margs->
principal);
1014 "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",
1021 "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n",
1033#if !HAVE_SUN_LDAP_SDK
1040 (void) ldap_set_option(
nullptr, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
1042 debug((
char *)
"%s| %s: DEBUG: Initialise ldap connection\n",
LogTime(),
1045 if (domain && !kc) {
1047 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1051 "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n",
1057 for (
size_t i = 0; i < nhosts; ++i) {
1059 if (hlist[i].
port != -1)
1062 "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n",
1065 ld = tool_ldap_open(margs, hlist[i].
host,
port, margs->
ssl);
1073#if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
1075 "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n",
1078 rc = tool_sasl_bind(
ld, bindp, margs->
ssl);
1079 if (rc != LDAP_SUCCESS) {
1081 "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n",
1083 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1088 lcreds->
dn =
nullptr;
1090 ldap_set_rebind_proc(
ld, ldap_sasl_rebind, (
char *) lcreds);
1091 if (
ld !=
nullptr) {
1093 "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n",
1095 margs->
ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1099 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1101 error((
char *)
"%s| %s: ERROR: SASL not supported on system\n",
1107 if (
ld ==
nullptr) {
1109 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1115 bindp = convert_domain_to_bind_path(domain);
1118 if ((!domain || !
ld) && margs->
lurl && strstr(margs->
lurl,
"://")) {
1122 char *ssl =
nullptr;
1127 hostname = strstr(margs->
lurl,
"://") + 3;
1128 ssl = strstr(margs->
lurl,
"ldaps://");
1130 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1133 debug((
char *)
"%s| %s: DEBUG: Canonicalise ldap server name %s\n",
1140 if ((p = strchr(host,
':'))) {
1147 for (
size_t i = 0; i < nhosts; ++i) {
1150 cred.bv_val = margs->
lpass;
1151 cred.bv_len = strlen(margs->
lpass);
1153 ld = tool_ldap_open(margs, hlist[i].host,
port, ssl);
1161 "%s| %s: DEBUG: Bind to ldap server with Username/Password\n",
1163 rc = ldap_sasl_bind_s(
ld, margs->
luser, LDAP_SASL_SIMPLE, &cred,
1164 nullptr,
nullptr,
nullptr);
1165 if (rc != LDAP_SUCCESS) {
1167 "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n",
1169 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1176 ldap_set_rebind_proc(
ld, ldap_simple_rebind, (
char *) lcreds);
1178 "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n",
1180 ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1189 bindp = convert_domain_to_bind_path(domain);
1192 if (
ld ==
nullptr) {
1194 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1206 rc = check_AD(margs,
ld);
1207 if (rc != LDAP_SUCCESS) {
1209 "%s| %s: ERROR: Error determining ldap server type: %s\n",
1211 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1217 filter = (
char *) FILTER_AD;
1219 filter = (
char *) FILTER;
1221 ldap_filter_esc = escape_filter(user);
1223 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1224 search_exp = (
char *)
xmalloc(se_len);
1225 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1227 xfree(ldap_filter_esc);
1230 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
1232 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
1233 nullptr,
nullptr, &searchtime, 0, &res);
1236 if (rc != LDAP_SUCCESS) {
1237 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
1239 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1245 ldap_count_entries(
ld, res), ldap_count_entries(
ld, res) > 1
1246 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1248 if (ldap_count_entries(
ld, res) != 0) {
1251 max_attr = get_attributes(
ld, res, ATTRIBUTE_AD, &attr_value);
1253 max_attr = get_attributes(
ld, res, ATTRIBUTE, &attr_value);
1260 for (
size_t k = 0; k < max_attr; ++k) {
1265 if (!strncasecmp(
"CN=", av, 3)) {
1266 char *avp =
nullptr;
1268 if ((avp = strchr(av,
','))) {
1273 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" in hex UTF-8 is ",
LogTime(),
PROGRAM, k + 1, av);
1274 for (
unsigned int n = 0; av[n] !=
'\0'; ++n)
1275 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
1276 fprintf(stderr,
"\n");
1278 if (!strcasecmp(group, av)) {
1281 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" matches group name \"%s\"\n",
LogTime(),
1286 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" does not match group name \"%s\"\n",
LogTime(),
1292 if (!retval && margs->
AD) {
1295 "%s| %s: DEBUG: Perform recursive group search\n",
1298 for (
size_t j = 0; j < max_attr; ++j) {
1302 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1304 if (!strncasecmp(
"CN=", av, 3)) {
1305 char *avp =
nullptr;
1307 if ((avp = strchr(av,
','))) {
1312 debug((
char *)
"%s| %s: DEBUG: Entry %zu group \"%s\" is (in)direct member of group \"%s\"\n",
1323 for (
size_t j = 0; j < max_attr; ++j) {
1324 xfree(attr_value[j]);
1329 }
else if (ldap_count_entries(
ld, res) == 0 && margs->
AD) {
1331 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1345 "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n",
1348 filter = (
char *) FILTER_AD;
1350 filter = (
char *) FILTER_UID;
1352 ldap_filter_esc = escape_filter(user);
1354 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1355 search_exp = (
char *)
xmalloc(se_len);
1356 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1358 xfree(ldap_filter_esc);
1361 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1363 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr,
1364 0,
nullptr,
nullptr, &searchtime, 0, &res);
1367 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
LogTime(),
1368 PROGRAM, ldap_count_entries(
ld, res), ldap_count_entries(
ld,
1369 res) > 1 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1375 get_attributes(
ld, res, ATTRIBUTE_GID_AD, &attr_value);
1377 max_attr = get_attributes(
ld, res, ATTRIBUTE_GID, &attr_value);
1380 if (max_attr == 1) {
1381 char **attr_value_2 =
nullptr;
1382 size_t max_attr_2 = 0;
1385 char **attr_value_3 =
nullptr;
1386 int *attr_len_3 =
nullptr;
1387 size_t max_attr_3 = 0;
1388 uint32_t gid = atoi(attr_value[0]);
1392 debug((
char *)
"%s| %s: DEBUG: Got primaryGroupID %u\n",
1395 get_bin_attributes(
ld, res, ATTRIBUTE_SID, &attr_value_3,
1398 if (max_attr_3 == 1) {
1399 int len = attr_len_3[0];
1402 "%s| %s: ERROR: Length %d is too short for objectSID\n",
1407 attr_value_3[0][len - 1] = ((gid >> 24) & 0xff);
1408 attr_value_3[0][len - 2] = ((gid >> 16) & 0xff);
1409 attr_value_3[0][len - 3] = ((gid >> 8) & 0xff);
1410 attr_value_3[0][len - 4] = ((gid >> 0) & 0xff);
1412#define FILTER_SID_1 "(objectSID="
1413#define FILTER_SID_2 ")"
1416 strlen(FILTER_SID_1) + len * 3 +
1417 strlen(FILTER_SID_2) + 1;
1418 search_exp = (
char *)
xmalloc(se_len);
1419 snprintf(search_exp, se_len,
"%s", FILTER_SID_1);
1421 for (
int j = 0; j < len; j++) {
1423 snprintf(search_exp, se_len,
"%s\\%02x", se,
1424 attr_value_3[0][j] & 0xFF);
1428 snprintf(search_exp, se_len,
"%s%s", se, FILTER_SID_2);
1432 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1434 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1435 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0,
1439 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
1441 ldap_count_entries(
ld, res) > 1
1442 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1450 for (j = 0; j < max_attr_3; ++j) {
1451 xfree(attr_value_3[j]);
1460 filter = (
char *) FILTER_GID;
1462 ldap_filter_esc = escape_filter(attr_value[0]);
1464 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1465 search_exp = (
char *)
xmalloc(se_len);
1466 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1468 xfree(ldap_filter_esc);
1471 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1473 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1474 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
1481 get_attributes(
ld, res, ATTRIBUTE_DN, &attr_value_2);
1484 get_attributes(
ld, res, ATTRIBUTE, &attr_value_2);
1493 if (max_attr_2 == 1) {
1495 char *av = attr_value_2[0];
1496 if (!strncasecmp(
"CN=", av, 3)) {
1497 char *avp =
nullptr;
1499 if ((avp = strchr(av,
','))) {
1503 if (!strcasecmp(group, av)) {
1506 "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n",
1510 "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n",
1517 if (!retval && margs->
AD) {
1520 "%s| %s: DEBUG: Perform recursive group search\n",
1523 for (
size_t j = 0; j < max_attr_2; ++j) {
1526 av = attr_value_2[j];
1527 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1529 if (!strncasecmp(
"CN=", av, 3)) {
1530 char *avp =
nullptr;
1532 if ((avp = strchr(av,
','))) {
1537 debug((
char *)
"%s| %s: DEBUG: Entry %zu group \"%s\" is (in)direct member of group \"%s\"\n",
1550 for (j = 0; j < max_attr_2; ++j) {
1551 xfree(attr_value_2[j]);
1556 debug((
char *)
"%s| %s: DEBUG: Users primary group %s %s\n",
1563 "%s| %s: DEBUG: Did not find ldap entry for group %s\n",
1570 for (
size_t j = 0; j < max_attr; ++j) {
1571 xfree(attr_value[j]);
1576 rc = ldap_unbind_ext(
ld,
nullptr,
nullptr);
1578 if (rc != LDAP_SUCCESS) {
1579 error((
char *)
"%s| %s: ERROR: Error unbind ldap server: %s\n",
void error(char *format,...)
size_t get_hostname_list(struct hstruct **hlist, size_t nhosts, char *name)
int get_memberof(struct main_args *margs, char *user, char *domain, char *group)
const char * LogTime(void)
size_t free_hostname_list(struct hstruct **hlist, size_t nhosts)
size_t get_ldap_hostname_list(struct main_args *margs, struct hstruct **hlist, size_t nhosts, char *domain)
void debug(const char *format,...)
void * xrealloc(void *s, size_t sz)
void * xcalloc(size_t n, size_t sz)