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,
NULL,
NULL,
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,
NULL,
NULL,
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,
NULL,
NULL,
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 %" PRIuSIZE
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 %" PRIuSIZE
449 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
450 " \"%s\" does not match group name \"%s\"\n",
LogTime(),
456 "%s| %s: DEBUG: Perform recursive group search for group \"%s\"\n",
459 if (search_group_tree(margs,
ld, bindp, av, group, ldepth)) {
461 if (!strncasecmp(
"CN=", av, 3)) {
464 if ((avp = strchr(av,
','))) {
469 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
470 " \"%s\" is member of group named \"%s\"\n",
LogTime(),
482 for (
size_t j = 0; j < max_attr; ++j) {
483 xfree(attr_value[j]);
493ldap_set_defaults(LDAP *
ld)
496#if LDAP_OPT_NETWORK_TIMEOUT
500 rc = ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &val);
501 if (rc != LDAP_SUCCESS) {
503 "%s| %s: DEBUG: Error while setting protocol version: %s\n",
507 rc = ldap_set_option(
ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
508 if (rc != LDAP_SUCCESS) {
509 debug((
char *)
"%s| %s: DEBUG: Error while setting referrals off: %s\n",
513#if LDAP_OPT_NETWORK_TIMEOUT
514 tv.tv_sec = CONNECT_TIMEOUT;
516 rc = ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
517 if (rc != LDAP_SUCCESS) {
519 "%s| %s: DEBUG: Error while setting network timeout: %s\n",
528ldap_set_ssl_defaults(
struct main_args *margs)
530#if HAVE_OPENLDAP || HAVE_LDAPSSL_CLIENT_INIT
535#elif HAVE_LDAPSSL_CLIENT_INIT
536 char *ssl_certdbpath =
NULL;
541 char *ssl_cacertfile =
nullptr;
542 char *ssl_cacertdir =
nullptr;
544 "%s| %s: DEBUG: Enable server certificate check for ldap server.\n",
546 val = LDAP_OPT_X_TLS_DEMAND;
547 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
548 if (rc != LDAP_SUCCESS) {
550 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT DEMAND for ldap server: %s\n",
554 ssl_cacertfile =
xstrdup(getenv(
"TLS_CACERTFILE"));
555 if (!ssl_cacertfile) {
556 ssl_cacertfile =
xstrdup(
"/etc/ssl/certs/cert.pem");
558 if (access(ssl_cacertfile, R_OK) == 0) {
560 "%s| %s: DEBUG: Set certificate file for ldap server to %s. (Changeable through setting environment variable TLS_CACERTFILE)\n",
562 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTFILE,
564 xfree(ssl_cacertfile);
565 if (rc != LDAP_OPT_SUCCESS) {
567 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTFILE for ldap server: %s\n",
573 "%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",
575 xfree(ssl_cacertfile);
576 ssl_cacertdir =
xstrdup(getenv(
"TLS_CACERTDIR"));
577 if (!ssl_cacertdir) {
578 ssl_cacertdir =
xstrdup(
"/etc/ssl/certs");
580 if (access(ssl_cacertdir, R_OK) == 0) {
582 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable TLS_CACERTDIR)\n",
584 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_CACERTDIR,
586 xfree(ssl_cacertdir);
587 if (rc != LDAP_OPT_SUCCESS) {
589 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_CACERTDIR for ldap server: %s\n",
595 "%s| %s: DEBUG: Set certificate database path for ldap server to %s failed (%s). (Changeable through setting environment variable TLS_CACERTDIR)\n",
597 xfree(ssl_cacertdir);
603 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
605 val = LDAP_OPT_X_TLS_ALLOW;
606 rc = ldap_set_option(
nullptr, LDAP_OPT_X_TLS_REQUIRE_CERT, &val);
607 if (rc != LDAP_SUCCESS) {
609 "%s| %s: ERROR: Error while setting LDAP_OPT_X_TLS_REQUIRE_CERT ALLOW for ldap server: %s\n",
614#elif HAVE_LDAPSSL_CLIENT_INIT
622 ssl_certdbpath = getenv(
"SSL_CERTDBPATH");
623 if (!ssl_certdbpath) {
624 ssl_certdbpath =
xstrdup(
"/etc/certs");
627 "%s| %s: DEBUG: Set certificate database path for ldap server to %s. (Changeable through setting environment variable SSL_CERTDBPATH)\n",
630 rc = ldapssl_advclientauth_init(ssl_certdbpath,
NULL, 0,
NULL,
NULL, 0,
633 rc = ldapssl_advclientauth_init(ssl_certdbpath,
NULL, 0,
NULL,
NULL, 0,
636 "%s| %s: DEBUG: Disable server certificate check for ldap server.\n",
639 xfree(ssl_certdbpath);
640 if (rc != LDAP_SUCCESS) {
642 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
648 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
655get_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
659 char **attr_value = *ret_value;
665 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
667 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
668 msg = ldap_next_entry(
ld, msg)) {
670 switch (ldap_msgtype(msg)) {
672 case LDAP_RES_SEARCH_ENTRY: {
673 BerElement *b =
nullptr;
674 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
675 attr = ldap_next_attribute(
ld, msg, b)) {
676 if (strcasecmp(attr, attribute) == 0) {
677 struct berval **values;
680 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
681 for (
int il = 0; values[il] !=
nullptr; ++il) {
685 (max_attr + 1) *
sizeof(
char *));
689 attr_value[max_attr] =
690 (
char *)
xmalloc(values[il]->bv_len + 1);
691 memcpy(attr_value[max_attr], values[il]->bv_val,
693 attr_value[max_attr][values[il]->bv_len] = 0;
697 ber_bvecfree(values);
704 case LDAP_RES_SEARCH_REFERENCE:
706 "%s| %s: DEBUG: Received a search reference message\n",
709 case LDAP_RES_SEARCH_RESULT:
710 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
718 debug((
char *)
"%s| %s: DEBUG: %" PRIuSIZE
720 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
722 *ret_value = attr_value;
727get_bin_attributes(LDAP *
ld, LDAPMessage * res,
const char *attribute,
728 char ***ret_value,
int **ret_len)
731 char **attr_value = *ret_value;
732 int *attr_len = *ret_len;
738 debug((
char *)
"%s| %s: DEBUG: Search ldap entries for attribute : %s\n",
740 for (LDAPMessage * msg = ldap_first_entry(
ld, res); msg;
741 msg = ldap_next_entry(
ld, msg)) {
743 switch (ldap_msgtype(msg)) {
745 case LDAP_RES_SEARCH_ENTRY: {
746 BerElement *b =
nullptr;
747 for (
char *attr = ldap_first_attribute(
ld, msg, &b); attr;
748 attr = ldap_next_attribute(
ld, msg, b)) {
749 if (strcasecmp(attr, attribute) == 0) {
750 struct berval **values;
753 ldap_get_values_len(
ld, msg, attr)) !=
nullptr) {
754 for (
int il = 0; values[il] !=
nullptr; ++il) {
758 (max_attr + 1) *
sizeof(
char *));
764 (max_attr + 1) *
sizeof(
int));
768 attr_value[max_attr] =
769 (
char *)
xmalloc(values[il]->bv_len + 1);
770 memcpy(attr_value[max_attr], values[il]->bv_val,
772 attr_value[max_attr][values[il]->bv_len] = 0;
773 attr_len[max_attr] = values[il]->bv_len;
777 ber_bvecfree(values);
784 case LDAP_RES_SEARCH_REFERENCE:
786 "%s| %s: DEBUG: Received a search reference message\n",
789 case LDAP_RES_SEARCH_RESULT:
790 debug((
char *)
"%s| %s: DEBUG: Received a search result message\n",
798 debug((
char *)
"%s| %s: DEBUG: %" PRIuSIZE
800 max_attr, max_attr > 1 || max_attr == 0 ?
"ies" :
"y", attribute);
802 *ret_value = attr_value;
811tool_ldap_open(
struct main_args * margs,
char *host,
int port,
char *ssl)
815 LDAPURLDesc *url =
nullptr;
816 char *ldapuri =
nullptr;
825 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
826 memset(url, 0,
sizeof(*url));
827#if HAVE_LDAP_URL_LUD_SCHEME
829 url->lud_scheme =
xstrdup(
"ldaps");
831 url->lud_scheme =
xstrdup(
"ldap");
834 url->lud_port =
port;
835#if HAVE_LDAP_SCOPE_DEFAULT
836 url->lud_scope = LDAP_SCOPE_DEFAULT;
838 url->lud_scope = LDAP_SCOPE_SUBTREE;
840#if HAVE_LDAP_URL_DESC2STR
841 ldapuri = ldap_url_desc2str(url);
842#elif HAVE_LDAP_URL_PARSE
843 rc = ldap_url_parse(ldapuri, &url);
844 if (rc != LDAP_SUCCESS) {
845 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
848 ldap_free_urldesc(url);
852#error "No URL parsing function"
854 ldap_free_urldesc(url);
855 rc = ldap_initialize(&
ld, ldapuri);
857 if (rc != LDAP_SUCCESS) {
859 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
861 ldap_unbind_ext(
ld,
nullptr,
nullptr);
866 ld = ldap_init(host,
port);
868 rc = ldap_set_defaults(
ld);
869 if (rc != LDAP_SUCCESS) {
871 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
873 ldap_unbind_ext(
ld,
nullptr,
nullptr);
882 rc = ldap_set_ssl_defaults(margs);
883 if (rc != LDAP_SUCCESS) {
885 "%s| %s: ERROR: Error while setting SSL default options for ldap server: %s\n",
887 ldap_unbind_ext(
ld,
nullptr,
nullptr);
895 rc = ldap_start_tls_s(
ld,
nullptr,
nullptr);
896 if (rc != LDAP_SUCCESS) {
898 "%s| %s: WARNING: Error while setting start_tls for ldap server: %s\n",
900 ldap_unbind_ext(
ld,
nullptr,
nullptr);
902 url = (LDAPURLDesc *)
xmalloc(
sizeof(*url));
903 memset(url, 0,
sizeof(*url));
904#if HAVE_LDAP_URL_LUD_SCHEME
905 url->lud_scheme =
xstrdup(
"ldaps");
908 url->lud_port =
port;
909#if HAVE_LDAP_SCOPE_DEFAULT
910 url->lud_scope = LDAP_SCOPE_DEFAULT;
912 url->lud_scope = LDAP_SCOPE_SUBTREE;
914#if HAVE_LDAP_URL_DESC2STR
915 ldapuri = ldap_url_desc2str(url);
916#elif HAVE_LDAP_URL_PARSE
917 rc = ldap_url_parse(ldapuri, &url);
918 if (rc != LDAP_SUCCESS) {
919 error((
char *)
"%s| %s: ERROR: Error while parsing url: %s\n",
922 ldap_free_urldesc(url);
926#error "No URL parsing function"
928 ldap_free_urldesc(url);
929 rc = ldap_initialize(&
ld, ldapuri);
931 if (rc != LDAP_SUCCESS) {
933 "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n",
935 ldap_unbind_ext(
ld,
nullptr,
nullptr);
939 rc = ldap_set_defaults(
ld);
940 if (rc != LDAP_SUCCESS) {
942 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
944 ldap_unbind_ext(
ld,
nullptr,
nullptr);
949#elif HAVE_LDAPSSL_CLIENT_INIT
950 ld = ldapssl_init(host,
port, 1);
953 "%s| %s: ERROR: Error while setting SSL for ldap server: %s\n",
959 rc = ldap_set_defaults(
ld);
960 if (rc != LDAP_SUCCESS) {
962 "%s| %s: ERROR: Error while setting default options for ldap server: %s\n",
969 error((
char *)
"%s| %s: ERROR: SSL not supported by ldap library\n",
984#if !HAVE_SUN_LDAP_SDK
988 char *bindp =
nullptr;
989 char *filter =
nullptr;
992 struct timeval searchtime;
995 char **attr_value =
nullptr;
997 struct hstruct *hlist =
nullptr;
999 char *ldap_filter_esc =
nullptr;
1001 searchtime.tv_sec = SEARCH_TIMEOUT;
1002 searchtime.tv_usec = 0;
1007 debug((
char *)
"%s| %s: DEBUG: Setup Kerberos credential cache\n",
1014 "%s| %s: DEBUG: Kerberos is disabled. Use username/password with ldap url instead\n",
1017 kc = krb5_create_cache(domain, margs->
principal);
1020 "%s| %s: ERROR: Error during setup of Kerberos credential cache\n",
1027 "%s| %s: DEBUG: Kerberos is not supported. Use username/password with ldap url instead\n",
1039#if !HAVE_SUN_LDAP_SDK
1046 (void) ldap_set_option(
nullptr, LDAP_OPT_DEBUG_LEVEL, &ldap_debug);
1048 debug((
char *)
"%s| %s: DEBUG: Initialise ldap connection\n",
LogTime(),
1051 if (domain && !kc) {
1053 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1057 "%s| %s: DEBUG: Canonicalise ldap server name for domain %s\n",
1063 for (
size_t i = 0; i < nhosts; ++i) {
1065 if (hlist[i].
port != -1)
1068 "%s| %s: DEBUG: Setting up connection to ldap server %s:%d\n",
1071 ld = tool_ldap_open(margs, hlist[i].
host,
port, margs->
ssl);
1079#if HAVE_SASL_H || HAVE_SASL_SASL_H || HAVE_SASL_DARWIN
1081 "%s| %s: DEBUG: Bind to ldap server with SASL/GSSAPI\n",
1084 rc = tool_sasl_bind(
ld, bindp, margs->
ssl);
1085 if (rc != LDAP_SUCCESS) {
1087 "%s| %s: ERROR: Error while binding to ldap server with SASL/GSSAPI: %s\n",
1089 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1094 lcreds->
dn =
nullptr;
1096 ldap_set_rebind_proc(
ld, ldap_sasl_rebind, (
char *) lcreds);
1097 if (
ld !=
nullptr) {
1099 "%s| %s: DEBUG: %s initialised %sconnection to ldap server %s:%d\n",
1101 margs->
ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1107 error((
char *)
"%s| %s: ERROR: SASL not supported on system\n",
1113 if (
ld ==
nullptr) {
1115 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1121 bindp = convert_domain_to_bind_path(domain);
1124 if ((!domain || !
ld) && margs->
lurl && strstr(margs->
lurl,
"://")) {
1128 char *ssl =
nullptr;
1133 hostname = strstr(margs->
lurl,
"://") + 3;
1134 ssl = strstr(margs->
lurl,
"ldaps://");
1136 debug((
char *)
"%s| %s: DEBUG: Enable SSL to ldap servers\n",
1139 debug((
char *)
"%s| %s: DEBUG: Canonicalise ldap server name %s\n",
1146 if ((p = strchr(host,
':'))) {
1153 for (
size_t i = 0; i < nhosts; ++i) {
1156 cred.bv_val = margs->
lpass;
1157 cred.bv_len = strlen(margs->
lpass);
1159 ld = tool_ldap_open(margs, hlist[i].host,
port, ssl);
1167 "%s| %s: DEBUG: Bind to ldap server with Username/Password\n",
1169 rc = ldap_sasl_bind_s(
ld, margs->
luser, LDAP_SASL_SIMPLE, &cred,
1170 nullptr,
nullptr,
nullptr);
1171 if (rc != LDAP_SUCCESS) {
1173 "%s| %s: ERROR: Error while binding to ldap server with Username/Password: %s\n",
1175 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1182 ldap_set_rebind_proc(
ld, ldap_simple_rebind, (
char *) lcreds);
1184 "%s| %s: DEBUG: %s set up %sconnection to ldap server %s:%d\n",
1186 ssl ?
"SSL protected " :
"", hlist[i].host,
port);
1195 bindp = convert_domain_to_bind_path(domain);
1198 if (
ld ==
nullptr) {
1200 "%s| %s: DEBUG: Error during initialisation of ldap connection: %s\n",
1212 rc = check_AD(margs,
ld);
1213 if (rc != LDAP_SUCCESS) {
1215 "%s| %s: ERROR: Error determining ldap server type: %s\n",
1217 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1223 filter = (
char *) FILTER_AD;
1225 filter = (
char *) FILTER;
1227 ldap_filter_esc = escape_filter(user);
1229 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1230 search_exp = (
char *)
xmalloc(se_len);
1231 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1233 xfree(ldap_filter_esc);
1236 "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n",
1238 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr, 0,
1239 nullptr,
nullptr, &searchtime, 0, &res);
1242 if (rc != LDAP_SUCCESS) {
1243 error((
char *)
"%s| %s: ERROR: Error searching ldap server: %s\n",
1245 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1251 ldap_count_entries(
ld, res), ldap_count_entries(
ld, res) > 1
1252 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1254 if (ldap_count_entries(
ld, res) != 0) {
1257 max_attr = get_attributes(
ld, res, ATTRIBUTE_AD, &attr_value);
1259 max_attr = get_attributes(
ld, res, ATTRIBUTE, &attr_value);
1266 for (
size_t k = 0; k < max_attr; ++k) {
1271 if (!strncasecmp(
"CN=", av, 3)) {
1272 char *avp =
nullptr;
1274 if ((avp = strchr(av,
','))) {
1279 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
1281 for (
unsigned int n = 0; av[n] !=
'\0'; ++n)
1282 fprintf(stderr,
"%02x", (
unsigned char) av[n]);
1283 fprintf(stderr,
"\n");
1285 if (!strcasecmp(group, av)) {
1288 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
1289 " \"%s\" matches group name \"%s\"\n",
LogTime(),
1294 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
1295 " \"%s\" does not match group name \"%s\"\n",
LogTime(),
1301 if (!retval && margs->
AD) {
1304 "%s| %s: DEBUG: Perform recursive group search\n",
1307 for (
size_t j = 0; j < max_attr; ++j) {
1311 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1313 if (!strncasecmp(
"CN=", av, 3)) {
1314 char *avp =
nullptr;
1316 if ((avp = strchr(av,
','))) {
1321 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
1322 " group \"%s\" is (in)direct member of group \"%s\"\n",
1333 for (
size_t j = 0; j < max_attr; ++j) {
1334 xfree(attr_value[j]);
1339 }
else if (ldap_count_entries(
ld, res) == 0 && margs->
AD) {
1341 ldap_unbind_ext(
ld,
nullptr,
nullptr);
1355 "%s| %s: DEBUG: Search for primary group membership: \"%s\"\n",
1358 filter = (
char *) FILTER_AD;
1360 filter = (
char *) FILTER_UID;
1362 ldap_filter_esc = escape_filter(user);
1364 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1365 search_exp = (
char *)
xmalloc(se_len);
1366 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1368 xfree(ldap_filter_esc);
1371 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1373 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE, search_exp,
nullptr,
1374 0,
nullptr,
nullptr, &searchtime, 0, &res);
1377 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
LogTime(),
1378 PROGRAM, ldap_count_entries(
ld, res), ldap_count_entries(
ld,
1379 res) > 1 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1385 get_attributes(
ld, res, ATTRIBUTE_GID_AD, &attr_value);
1387 max_attr = get_attributes(
ld, res, ATTRIBUTE_GID, &attr_value);
1390 if (max_attr == 1) {
1391 char **attr_value_2 =
nullptr;
1392 size_t max_attr_2 = 0;
1395 char **attr_value_3 =
nullptr;
1396 int *attr_len_3 =
nullptr;
1397 size_t max_attr_3 = 0;
1398 uint32_t gid = atoi(attr_value[0]);
1402 debug((
char *)
"%s| %s: DEBUG: Got primaryGroupID %u\n",
1405 get_bin_attributes(
ld, res, ATTRIBUTE_SID, &attr_value_3,
1408 if (max_attr_3 == 1) {
1409 int len = attr_len_3[0];
1412 "%s| %s: ERROR: Length %d is too short for objectSID\n",
1417 attr_value_3[0][len - 1] = ((gid >> 24) & 0xff);
1418 attr_value_3[0][len - 2] = ((gid >> 16) & 0xff);
1419 attr_value_3[0][len - 3] = ((gid >> 8) & 0xff);
1420 attr_value_3[0][len - 4] = ((gid >> 0) & 0xff);
1422#define FILTER_SID_1 "(objectSID="
1423#define FILTER_SID_2 ")"
1426 strlen(FILTER_SID_1) + len * 3 +
1427 strlen(FILTER_SID_2) + 1;
1428 search_exp = (
char *)
xmalloc(se_len);
1429 snprintf(search_exp, se_len,
"%s", FILTER_SID_1);
1431 for (
int j = 0; j < len; j++) {
1433 snprintf(search_exp, se_len,
"%s\\%02x", se,
1434 attr_value_3[0][j] & 0xFF);
1438 snprintf(search_exp, se_len,
"%s%s", se, FILTER_SID_2);
1442 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1444 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1445 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0,
1449 debug((
char *)
"%s| %s: DEBUG: Found %d ldap entr%s\n",
1451 ldap_count_entries(
ld, res) > 1
1452 || ldap_count_entries(
ld, res) == 0 ?
"ies" :
"y");
1460 for (j = 0; j < max_attr_3; ++j) {
1461 xfree(attr_value_3[j]);
1470 filter = (
char *) FILTER_GID;
1472 ldap_filter_esc = escape_filter(attr_value[0]);
1474 se_len = strlen(filter) + strlen(ldap_filter_esc) + 1;
1475 search_exp = (
char *)
xmalloc(se_len);
1476 snprintf(search_exp, se_len, filter, ldap_filter_esc);
1478 xfree(ldap_filter_esc);
1481 "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n",
1483 rc = ldap_search_ext_s(
ld, bindp, LDAP_SCOPE_SUBTREE,
1484 search_exp,
nullptr, 0,
nullptr,
nullptr, &searchtime, 0, &res);
1491 get_attributes(
ld, res, ATTRIBUTE_DN, &attr_value_2);
1494 get_attributes(
ld, res, ATTRIBUTE, &attr_value_2);
1503 if (max_attr_2 == 1) {
1505 char *av = attr_value_2[0];
1506 if (!strncasecmp(
"CN=", av, 3)) {
1507 char *avp =
nullptr;
1509 if ((avp = strchr(av,
','))) {
1513 if (!strcasecmp(group, av)) {
1516 "%s| %s: DEBUG: \"%s\" matches group name \"%s\"\n",
1520 "%s| %s: DEBUG: \"%s\" does not match group name \"%s\"\n",
1527 if (!retval && margs->
AD) {
1530 "%s| %s: DEBUG: Perform recursive group search\n",
1533 for (
size_t j = 0; j < max_attr_2; ++j) {
1536 av = attr_value_2[j];
1537 if (search_group_tree(margs,
ld, bindp, av, group, 1)) {
1539 if (!strncasecmp(
"CN=", av, 3)) {
1540 char *avp =
nullptr;
1542 if ((avp = strchr(av,
','))) {
1547 debug((
char *)
"%s| %s: DEBUG: Entry %" PRIuSIZE
1548 " group \"%s\" is (in)direct member of group \"%s\"\n",
1561 for (j = 0; j < max_attr_2; ++j) {
1562 xfree(attr_value_2[j]);
1567 debug((
char *)
"%s| %s: DEBUG: Users primary group %s %s\n",
1574 "%s| %s: DEBUG: Did not find ldap entry for group %s\n",
1581 for (
size_t j = 0; j < max_attr; ++j) {
1582 xfree(attr_value[j]);
1587 rc = ldap_unbind_ext(
ld,
nullptr,
nullptr);
1589 if (rc != LDAP_SUCCESS) {
1590 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)