From fc2dc1a025bbbee6960700ddbdf5110b29b3ebcb Mon Sep 17 00:00:00 2001 From: Stephen Gelman Date: Mon, 12 Nov 2018 06:40:47 +0000 Subject: [PATCH] Add STARTTLS support for LDAP This allows connecting to LDAP servers that only listen on port 389 but use STARTTLS to get a TLS connection --- README | 5 +++++ pam_yubico.8.txt | 3 +++ pam_yubico.c | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/README b/README index 7c540ac..d32a3e1 100644 --- a/README +++ b/README @@ -177,6 +177,11 @@ in the authorization mapping files or in LDAP. This can be used to make YubiKey authentication optional unless the user has associated tokens. +ldap_starttls:: +If set, issue a STARTTLS command to the LDAP connection before +attempting to bind to it. This is a common setup for servers +that only listen on port 389 but still require TLS. + ldap_bind_as_user:: If set, use the user logging in to bind to LDAP. This will use the password provided by the user via PAM. If this is set, ldapdn diff --git a/pam_yubico.8.txt b/pam_yubico.8.txt index 6d40703..415207b 100644 --- a/pam_yubico.8.txt +++ b/pam_yubico.8.txt @@ -44,6 +44,9 @@ Forces the module to use a previous stacked modules password and will never prom *nullok*:: Don’t fail when there are no tokens declared for the user in the authorization mapping files or in LDAP. This can be used to make YubiKey authentication optional unless the user has associated tokens. +*ldap_starttls*:: +If set, issue a STARTTLS command to the LDAP connection before attempting to bind to it. This is a common setup for servers that only listen on port 389 but still require TLS. + *ldap_bind_as_user*:: Use the user logging in to bind to ldap. This will use the password provided by the user via PAM. If this is set, ldapdn and uid_attr must also be set. Enabling this will cause ldap_bind_user and ldap_bind_password to be ignored. diff --git a/pam_yubico.c b/pam_yubico.c index 27f9d96..e911060 100644 --- a/pam_yubico.c +++ b/pam_yubico.c @@ -110,6 +110,7 @@ struct cfg int try_first_pass; int use_first_pass; int nullok; + int ldap_starttls; int ldap_bind_as_user; const char *auth_file; const char *capath; @@ -291,6 +292,14 @@ authorize_user_token_ldap (struct cfg *cfg, ldap_set_option (0, LDAP_OPT_X_TLS_CACERTFILE, cfg->ldap_cacertfile); } + if (cfg->ldap_starttls) { + rc = ldap_start_tls_s (ld, NULL, NULL); + if (rc != LDAP_SUCCESS) { + DBG ("ldap_start_tls: %s", ldap_err2string (rc)); + goto done; + } + } + /* Allocation of memory for search strings depending on input size */ if (cfg->user_attr && cfg->yubi_attr && cfg->ldapdn) { i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char); @@ -781,6 +790,8 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg) cfg->use_first_pass = 1; if (strcmp (argv[i], "nullok") == 0) cfg->nullok = 1; + if (strcmp (argv[i], "ldap_starttls") == 0) + cfg->ldap_starttls = 1; if (strcmp (argv[i], "ldap_bind_as_user") == 0) cfg->ldap_bind_as_user = 1; if (strncmp (argv[i], "authfile=", 9) == 0) @@ -873,6 +884,7 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg) DBG ("try_first_pass=%d", cfg->try_first_pass); DBG ("use_first_pass=%d", cfg->use_first_pass); DBG ("nullok=%d", cfg->nullok); + DBG ("ldap_starttls=%d", cfg->ldap_starttls); DBG ("ldap_bind_as_user=%d", cfg->ldap_bind_as_user); DBG ("authfile=%s", cfg->auth_file ? cfg->auth_file : "(null)"); DBG ("ldapserver=%s", cfg->ldapserver ? cfg->ldapserver : "(null)");