Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.2:Staging:A
adcli
0027-add-option-use-ldaps.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0027-add-option-use-ldaps.patch of Package adcli
From 41db84aac101a54c4b0ef78119ccf9905f0691fe Mon Sep 17 00:00:00 2001 From: Sumit Bose <sbose@redhat.com> Date: Thu, 19 Dec 2019 07:22:33 +0100 Subject: [PATCH 2/2] add option use-ldaps In general using the LDAP port with GSS-SPNEGO should satifiy all requirements an AD DC should have for authentication on an encrypted LDAP connection. But if e.g. the LDAP port is blocked by a firewall using the LDAPS port with TLS encryption might be an alternative. For this use case the --use-ldaps option is added. Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420 (cherry picked from commit 85097245b57f190337225dbdbf6e33b58616c092) --- doc/adcli.xml | 24 +++++++++++++++ library/adconn.c | 79 ++++++++++++++++++++++++++++++++++++++++++------ library/adconn.h | 4 +++ tools/computer.c | 9 ++++++ tools/entry.c | 11 +++++++ 5 files changed, 118 insertions(+), 9 deletions(-) diff --git a/doc/adcli.xml b/doc/adcli.xml index 2fe9309..f257c88 100644 --- a/doc/adcli.xml +++ b/doc/adcli.xml @@ -117,6 +117,30 @@ If not specified then an appropriate domain controller is automatically discovered.</para></listitem> </varlistentry> + <varlistentry> + <term><option>--use-ldaps</option></term> + <listitem><para>Connect to the domain controller + with LDAPS. By default the LDAP port is used and SASL + GSS-SPNEGO or GSSAPI is used for authentication and to + establish encryption. This should satisfy all + requirements set on the server side and LDAPS should + only be used if the LDAP port is not accessible due to + firewalls or other reasons.</para> + <para> Please note that the place where CA certificates + can be found to validate the AD DC certificates + must be configured in the OpenLDAP configuration + file, e.g. <filename>/etc/openldap/ldap.conf</filename>. + As an alternative it can be specified with the help of + an environment variable, e.g. +<programlisting> +$ LDAPTLS_CACERT=/path/to/ad_dc_ca_cert.pem adcli join --use-ldaps -D domain.example.com +... +</programlisting> + Please see + <citerefentry><refentrytitle>ldap.conf</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + </para></listitem> + </varlistentry> <varlistentry> <term><option>-C, --login-ccache=<parameter>ccache_name</parameter></option></term> <listitem><para>Use the specified kerberos credential diff --git a/library/adconn.c b/library/adconn.c index a3f4548..8a55776 100644 --- a/library/adconn.c +++ b/library/adconn.c @@ -70,6 +70,7 @@ struct _adcli_conn_ctx { char *domain_name; char *domain_realm; char *domain_controller; + bool use_ldaps; char *canonical_host; char *domain_short; char *domain_sid; @@ -773,7 +774,8 @@ int ldap_init_fd (ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap static LDAP * connect_to_address (const char *host, - const char *canonical_host) + const char *canonical_host, + bool use_ldaps) { struct addrinfo *res = NULL; struct addrinfo *ai; @@ -783,6 +785,16 @@ connect_to_address (const char *host, char *url; int sock; int rc; + int opt_rc; + const char *port = "389"; + const char *proto = "ldap"; + const char *errmsg = NULL; + + if (use_ldaps) { + port = "636"; + proto = "ldaps"; + _adcli_info ("Using LDAPS to connect to %s", host); + } memset (&hints, '\0', sizeof(hints)); #ifdef AI_ADDRCONFIG @@ -794,7 +806,7 @@ connect_to_address (const char *host, if (!canonical_host) canonical_host = host; - rc = getaddrinfo (host, "389", &hints, &res); + rc = getaddrinfo (host, port, &hints, &res); if (rc != 0) { _adcli_err ("Couldn't resolve host name: %s: %s", host, gai_strerror (rc)); return NULL; @@ -810,7 +822,7 @@ connect_to_address (const char *host, close (sock); } else { error = 0; - if (asprintf (&url, "ldap://%s", canonical_host) < 0) + if (asprintf (&url, "%s://%s", proto, canonical_host) < 0) return_val_if_reached (NULL); rc = ldap_init_fd (sock, 1, url, &ldap); free (url); @@ -820,6 +832,25 @@ connect_to_address (const char *host, ldap_err2string (rc)); break; } + + if (use_ldaps) { + rc = ldap_install_tls (ldap); + if (rc != LDAP_SUCCESS) { + opt_rc = ldap_get_option (ldap, + LDAP_OPT_DIAGNOSTIC_MESSAGE, + (void *) &errmsg); + if (opt_rc != LDAP_SUCCESS) { + errmsg = NULL; + } + _adcli_err ("Couldn't initialize TLS [%s]: %s", + ldap_err2string (rc), + errmsg == NULL ? "- no details -" + : errmsg); + ldap_unbind_ext_s (ldap, NULL, NULL); + ldap = NULL; + break; + } + } } } @@ -856,7 +887,8 @@ connect_and_lookup_naming (adcli_conn *conn, if (!canonical_host) canonical_host = disco->host_addr; - ldap = connect_to_address (disco->host_addr, canonical_host); + ldap = connect_to_address (disco->host_addr, canonical_host, + adcli_conn_get_use_ldaps (conn)); if (ldap == NULL) return ADCLI_ERR_DIRECTORY; @@ -1041,14 +1073,28 @@ authenticate_to_directory (adcli_conn *conn) status = gss_krb5_ccache_name (&minor, conn->login_ccache_name, NULL); return_unexpected_if_fail (status == 0); - /* Clumsily tell ldap + cyrus-sasl that we want encryption */ - ssf = 1; - ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); - return_unexpected_if_fail (ret == 0); + if (adcli_conn_get_use_ldaps (conn)) { + /* do not use SASL encryption on LDAPS connection */ + ssf = 0; + ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); + return_unexpected_if_fail (ret == 0); + ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MAX, &ssf); + return_unexpected_if_fail (ret == 0); + } else { + /* Clumsily tell ldap + cyrus-sasl that we want encryption */ + ssf = 1; + ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf); + return_unexpected_if_fail (ret == 0); + } - if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) { + /* There are issues with cryrus-sasl and GSS-SPNEGO with TLS even if + * ssf_max is set to 0. To be on the safe side GSS-SPNEGO is only used + * without LDAPS. */ + if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO") + && !adcli_conn_get_use_ldaps (conn)) { mech = "GSS-SPNEGO"; } + _adcli_info ("Using %s for SASL bind", mech); ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL, LDAP_SASL_QUIET, sasl_interact, NULL); @@ -1230,6 +1276,7 @@ adcli_conn_new (const char *domain_name) conn->refs = 1; conn->logins_allowed = ADCLI_LOGIN_COMPUTER_ACCOUNT | ADCLI_LOGIN_USER_ACCOUNT; adcli_conn_set_domain_name (conn, domain_name); + adcli_conn_set_use_ldaps (conn, false); return conn; } @@ -1389,6 +1436,20 @@ adcli_conn_set_domain_controller (adcli_conn *conn, no_more_disco (conn); } +bool +adcli_conn_get_use_ldaps (adcli_conn *conn) +{ + return_val_if_fail (conn != NULL, NULL); + return conn->use_ldaps; +} + +void +adcli_conn_set_use_ldaps (adcli_conn *conn, bool value) +{ + return_if_fail (conn != NULL); + conn->use_ldaps = value; +} + const char * adcli_conn_get_domain_short (adcli_conn *conn) { diff --git a/library/adconn.h b/library/adconn.h index 8e88045..3e287b1 100644 --- a/library/adconn.h +++ b/library/adconn.h @@ -89,6 +89,10 @@ const char * adcli_conn_get_domain_controller (adcli_conn *conn); void adcli_conn_set_domain_controller (adcli_conn *conn, const char *value); +bool adcli_conn_get_use_ldaps (adcli_conn *conn); +void adcli_conn_set_use_ldaps (adcli_conn *conn, + bool value); + const char * adcli_conn_get_domain_short (adcli_conn *conn); const char * adcli_conn_get_domain_sid (adcli_conn *conn); diff --git a/tools/computer.c b/tools/computer.c index 7a0c6f5..bb77963 100644 --- a/tools/computer.c +++ b/tools/computer.c @@ -109,12 +109,14 @@ typedef enum { opt_trusted_for_delegation, opt_add_service_principal, opt_remove_service_principal, + opt_use_ldaps, } Option; static adcli_tool_desc common_usages[] = { { opt_domain, "active directory domain name" }, { opt_domain_realm, "kerberos realm for the domain" }, { opt_domain_controller, "domain controller to connect to" }, + { opt_use_ldaps, "use LDAPS port for communication" }, { opt_host_fqdn, "override the fully qualified domain name of the\n" "local machine" }, { opt_host_keytab, "filename for the host kerberos keytab" }, @@ -282,6 +284,9 @@ parse_option (Option opt, case opt_remove_service_principal: adcli_enroll_add_service_principal_to_remove (enroll, optarg); return; + case opt_use_ldaps: + adcli_conn_set_use_ldaps (conn, true); + return; case opt_verbose: return; @@ -326,6 +331,7 @@ adcli_tool_computer_join (adcli_conn *conn, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, { "domain-server", required_argument, NULL, opt_domain_controller }, /* compat */ + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "user", required_argument, NULL, opt_login_user }, /* compat */ { "login-ccache", optional_argument, NULL, opt_login_ccache }, @@ -542,6 +548,7 @@ adcli_tool_computer_preset (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "domain-ou", required_argument, NULL, opt_domain_ou }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, @@ -641,6 +648,7 @@ adcli_tool_computer_reset (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "login-type", required_argument, NULL, opt_login_type }, @@ -716,6 +724,7 @@ adcli_tool_computer_delete (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, diff --git a/tools/entry.c b/tools/entry.c index 7b6a200..737fefe 100644 --- a/tools/entry.c +++ b/tools/entry.c @@ -52,6 +52,7 @@ typedef enum { opt_unix_uid, opt_unix_gid, opt_unix_shell, + opt_use_ldaps, } Option; static adcli_tool_desc common_usages[] = { @@ -65,6 +66,7 @@ static adcli_tool_desc common_usages[] = { { opt_domain, "active directory domain name" }, { opt_domain_realm, "kerberos realm for the domain" }, { opt_domain_controller, "domain directory server to connect to" }, + { opt_use_ldaps, "use LDAPS port for communication" }, { opt_login_ccache, "kerberos credential cache file which contains\n" "ticket to used to connect to the domain" }, { opt_login_user, "user (usually administrative) login name of\n" @@ -131,6 +133,9 @@ parse_option (Option opt, stdin_password = 1; } return; + case opt_use_ldaps: + adcli_conn_set_use_ldaps (conn, true); + return; case opt_verbose: return; default: @@ -163,6 +168,7 @@ adcli_tool_user_create (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, @@ -263,6 +269,7 @@ adcli_tool_user_delete (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, @@ -340,6 +347,7 @@ adcli_tool_group_create (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "domain-ou", required_argument, NULL, opt_domain_ou }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, @@ -426,6 +434,7 @@ adcli_tool_group_delete (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, @@ -536,6 +545,7 @@ adcli_tool_member_add (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, @@ -618,6 +628,7 @@ adcli_tool_member_remove (adcli_conn *conn, { "domain", required_argument, NULL, opt_domain }, { "domain-realm", required_argument, NULL, opt_domain_realm }, { "domain-controller", required_argument, NULL, opt_domain_controller }, + { "use-ldaps", no_argument, 0, opt_use_ldaps }, { "login-user", required_argument, NULL, opt_login_user }, { "login-ccache", optional_argument, NULL, opt_login_ccache }, { "no-password", no_argument, 0, opt_no_password }, -- 2.25.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor