54char *convert_domain_to_bind_path(
char *domain);
55char *escape_filter(
char *filter);
57int ldap_set_defaults(LDAP *
ld);
58int ldap_set_ssl_defaults(
struct main_args *margs);
59LDAP *tool_ldap_open(
struct main_args *margs,
char *host,
int port,
char *ssl);
61#define CONNECT_TIMEOUT 2
62#define SEARCH_TIMEOUT 30
64#define FILTER "(memberuid=%s)"
66#define ATTRIBUTE_DN "distinguishedName"
67#define FILTER_UID "(uid=%s)"
68#define FILTER_GID "(&(gidNumber=%s)(objectclass=posixgroup))"
69#define ATTRIBUTE_GID "gidNumber"
70#define ATTRIBUTE_GID_AD "primaryGroupID"
71#define ATTRIBUTE_SID "objectSID"
73#define FILTER_AD "(samaccountname=%s)"
74#define ATTRIBUTE_AD "memberof"
76size_t get_attributes(LDAP *
ld, LDAPMessage * res,
77 const char *attribute ,
char ***out_val );
78size_t get_bin_attributes(LDAP *
ld, LDAPMessage * res,
79 const char *attribute ,
char ***out_val,
81int search_group_tree(
struct main_args *margs, LDAP *
ld,
char *bindp,
82 char *ldap_group,
char *group,
int depth);
84#if HAVE_SUN_LDAP_SDK || HAVE_MOZILLA_LDAP_SDK
85#if HAVE_LDAP_REBINDPROC_CALLBACK
87#if HAVE_SASL_H || HAVE_SASL_SASL_H
88static LDAP_REBINDPROC_CALLBACK ldap_sasl_rebind;
90static int LDAP_CALL LDAP_CALLBACK
91ldap_sasl_rebind(LDAP *
ld,
92 char **whop,
char **credp,
int *methodp,
int freeit,
void *params)
99 return tool_sasl_bind(
ld, cp->
dn, cp->
pw);
103static LDAP_REBINDPROC_CALLBACK ldap_simple_rebind;
105static int LDAP_CALL LDAP_CALLBACK
106ldap_simple_rebind(LDAP *
ld,
107 char **whop,
char **credp,
int *methodp,
int freeit,
void *params)
112 cred.bv_val = cp->
pw;
113 cred.bv_len = strlen(cp->
pw);
119 return ldap_sasl_bind_s(
ld, cp->
dn, LDAP_SASL_SIMPLE, &cred,
nullptr,
nullptr,
122#elif HAVE_LDAP_REBIND_PROC
123#if HAVE_SASL_H || HAVE_SASL_SASL_H
124static LDAP_REBIND_PROC ldap_sasl_rebind;
127ldap_sasl_rebind(LDAP *
ld,
128 LDAP_CONST
char *url, ber_tag_t request, ber_int_t msgid,
void *params)
131 return tool_sasl_bind(
ld, cp->
dn, cp->
pw);
135static LDAP_REBIND_PROC ldap_simple_rebind;
138ldap_simple_rebind(LDAP *
ld,
139 LDAP_CONST
char *url, ber_tag_t request, ber_int_t msgid,
void *params)
144 cred.bv_val = cp->
pw;
145 cred.bv_len = strlen(cp->
pw);
147 return ldap_sasl_bind_s(
ld, cp->
dn, LDAP_SASL_SIMPLE, &cred,
nullptr,
nullptr,
151#elif HAVE_LDAP_REBIND_FUNCTION
152#ifndef LDAP_REFERRALS
153#define LDAP_REFERRALS
155#if HAVE_SASL_H || HAVE_SASL_SASL_H
156static LDAP_REBIND_FUNCTION ldap_sasl_rebind;
159ldap_sasl_rebind(LDAP *
ld,
160 char **whop,
char **credp,
int *methodp,
int freeit,
void *params)
167 return tool_sasl_bind(
ld, cp->
dn, cp->
pw);
171static LDAP_REBIND_FUNCTION ldap_simple_rebind;
174ldap_simple_rebind(LDAP *
ld,
175 char **whop,
char **credp,
int *methodp,
int freeit,
void *params)
180 cred.bv_val = cp->
pw;
181 cred.bv_len = strlen(cp->
pw);
187 return ldap_sasl_bind_s(
ld, cp->
dn, LDAP_SASL_SIMPLE, &cred,
nullptr,
nullptr,
191#error "No rebind functione defined"
194#if HAVE_SASL_H || HAVE_SASL_SASL_H
195static LDAP_REBIND_PROC ldap_sasl_rebind;
198ldap_sasl_rebind(LDAP *
ld, LDAP_CONST
char *, ber_tag_t,
199 ber_int_t,
void *params)
202 return tool_sasl_bind(
ld, cp->
dn, cp->
pw);
206static LDAP_REBIND_PROC ldap_simple_rebind;
209ldap_simple_rebind(LDAP *
ld, LDAP_CONST
char *, ber_tag_t,
210 ber_int_t,
void *params)
216 cred.bv_val = cp->
pw;
217 cred.bv_len = strlen(cp->
pw);
219 return ldap_sasl_bind_s(
ld, cp->
dn, LDAP_SASL_SIMPLE, &cred,
nullptr,
nullptr,
225convert_domain_to_bind_path(
char *domain)
227 char *dp, *bindp =
nullptr, *bp =
nullptr;
233 for (dp = domain; *dp; ++dp) {
241 bindp = (
char *)
xmalloc(strlen(domain) + 3 + i * 3 + 1);
245 for (dp = domain; *dp; ++dp) {
259escape_filter(
char *filter)
261 char *ldap_filter_esc, *ldf;
265 for (ldap_filter_esc = filter; *ldap_filter_esc; ++ldap_filter_esc) {
266 if ((*ldap_filter_esc ==
'*') ||
267 (*ldap_filter_esc ==
'(') ||
268 (*ldap_filter_esc ==
')') || (*ldap_filter_esc ==
'\\'))
272 ldap_filter_esc = (
char *)
xcalloc(strlen(filter) + i + 1,
sizeof(char));
273 ldf = ldap_filter_esc;
274 for (; *filter; ++filter) {
275 if (*filter ==
'*') {
278 }
else if (*filter ==
'(') {
281 }
else if (*filter ==
')') {
284 }
else if (*filter ==
'\\') {
294 return ldap_filter_esc;
300 LDAPMessage *res =
nullptr;
301 char **attr_value =
nullptr;
302 struct timeval searchtime;
306#define FILTER_SCHEMA "(objectclass=*)"
307#define ATTRIBUTE_SCHEMA "schemaNamingContext"
308#define FILTER_SAM "(ldapdisplayname=samaccountname)"
310 searchtime.tv_sec = SEARCH_TIMEOUT;
311 searchtime.tv_usec = 0;
314 "%s| %s: DEBUG: Search ldap server with bind path \"\" and filter: %s\n",
316 rc = ldap_search_ext_s(
ld, (
char *)
"", LDAP_SCOPE_BASE,
317 (
char *) FILTER_SCHEMA,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
319 if (rc == LDAP_SUCCESS)
320 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]);
358search_group_tree(
struct main_args *margs, LDAP *
ld,
char *bindp,
359 char *ldap_group,
char *group,
int depth)
361 LDAPMessage *res =
nullptr;
362 char **attr_value =
nullptr;
364 char *filter =
nullptr;
365 char *search_exp =
nullptr;
367 int rc = 0, retval = 0;
369 char *ldap_filter_esc =
nullptr;
370 struct timeval searchtime;
372#define FILTER_GROUP_AD "(&(%s)(objectclass=group))"
373#define FILTER_GROUP "(&(memberuid=%s)(objectclass=posixgroup))"
375 searchtime.tv_sec = SEARCH_TIMEOUT;
376 searchtime.tv_usec = 0;
379 filter = (
char *) FILTER_GROUP_AD;
381 filter = (
char *) FILTER_GROUP;
383 ldap_filter_esc = escape_filter(ldap_group);
385 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
386 search_exp = (
char *)
xmalloc(se_len);
387 snprintf(search_exp, se_len, filter, ldap_filter_esc);
389 xfree(ldap_filter_esc);
391 if (depth > margs->
mdepth) {
392 debug((
char *)
"%s| %s: DEBUG: Max search depth reached %d>%d\n",
398 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
400 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
401 nullptr,
nullptr, &searchtime, 0, &res);
404 if (rc != LDAP_SUCCESS) {
405 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
410 ldap_count_entries(
ld, res), ldap_count_entries(
ld, res) > 1
411 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
414 max_attr = get_attributes(
ld, res, ATTRIBUTE_AD, &attr_value);
416 max_attr = get_attributes(
ld, res, ATTRIBUTE, &attr_value);
423 for (
size_t j = 0; j < max_attr; ++j) {
428 if (!strncasecmp(
"CN=", av, 3)) {
431 if ((avp = strchr(av,
','))) {
437 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" in hex UTF-8 is ",
LogTime(),
PROGRAM, j + 1, av);
438 for (n = 0; av[n] !=
'\0'; ++n)
439 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
440 fprintf(stderr,
"\n");
442 if (!strcasecmp(group, av)) {
444 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" matches group name \"%s\"\n",
LogTime(),
PROGRAM,
448 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" does not match group name \"%s\"\n",
LogTime(),
454 "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
457 if (search_group_tree(margs,
ld, bindp, av, group, ldepth)) {
459 if (!strncasecmp(
"CN=", av, 3)) {
462 if ((avp = strchr(av,
','))) {
467 debug((
char *)
"%s| %s: DEBUG: Entry %zu \"%s\" is member of group named \"%s\"\n",
LogTime(),
479 for (
size_t j = 0; j < max_attr; ++j) {
480 xfree(attr_value[j]);
490ldap_set_defaults(LDAP *
ld)
493#if LDAP_OPT_NETWORK_TIMEOUT
497 rc = ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &val);
498 if (rc != LDAP_SUCCESS) {
500 "%s| %s: DEBUG: Error while setting protocol version: %s\n",
504 rc = ldap_set_option(
ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
505 if (rc != LDAP_SUCCESS) {
506 debug((
char *)
"%s| %s: DEBUG: Error while setting referrals off: %s\n",
510#if LDAP_OPT_NETWORK_TIMEOUT
511 tv.tv_sec = CONNECT_TIMEOUT;
513 rc = ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
514 if (rc != LDAP_SUCCESS) {
516 "%s| %s: DEBUG: Error while setting network timeout: %s\n",
525ldap_set_ssl_defaults(
struct main_args *margs)
527#if HAVE_OPENLDAP || HAVE_LDAPSSL_CLIENT_INIT
532#elif HAVE_LDAPSSL_CLIENT_INIT
533 char *ssl_certdbpath =
nullptr;
538 char *ssl_cacertfile =
nullptr;
539 char *ssl_cacertdir =
nullptr;
541 "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
543 val = LDAP_OPT_X_TLS_DEMAND;
544 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
545 if (rc != LDAP_SUCCESS) {
547 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
551 ssl_cacertfile =
xstrdup(getenv(
"TLS_CACERTFILE"));
552 if (!ssl_cacertfile) {
553 ssl_cacertfile =
xstrdup(
"/etc/ssl/certs/cert.pem");
555 if (access(ssl_cacertfile, R_OK) == 0) {
557 "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
559 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTFILE,
561 xfree(ssl_cacertfile);
562 if (rc != LDAP_OPT_SUCCESS) {
564 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
570 "%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",
572 xfree(ssl_cacertfile);
573 ssl_cacertdir =
xstrdup(getenv(
"TLS_CACERTDIR"));
574 if (!ssl_cacertdir) {
575 ssl_cacertdir =
xstrdup(
"/etc/ssl/certs");
577 if (access(ssl_cacertdir, R_OK) == 0) {
579 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
581 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTDIR,
583 xfree(ssl_cacertdir);
584 if (rc != LDAP_OPT_SUCCESS) {
586 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
592 "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
594 xfree(ssl_cacertdir);
600 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
602 val = LDAP_OPT_X_TLS_ALLOW;
603 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
604 if (rc != LDAP_SUCCESS) {
606 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
611#elif HAVE_LDAPSSL_CLIENT_INIT
619 const auto envp = getenv(
"SSL_CERTDBPATH");
620 ssl_certdbpath =
xstrdup(envp ? envp :
"/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
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)