Skip to content

Commit

Permalink
Merge c8c76fb into 1fe13aa
Browse files Browse the repository at this point in the history
  • Loading branch information
ssgelm committed Nov 12, 2018
2 parents 1fe13aa + c8c76fb commit 6e4da68
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 13 deletions.
20 changes: 20 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ 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
and uid_attr must also be set. Enabling this will cause
'ldap_bind_user' and 'ldap_bind_password' to be ignored

urllist::
List of URL templates to be used. This is set by calling
ykclient_set_url_bases. The list should be in the format :
Expand Down Expand Up @@ -225,6 +236,15 @@ ldapdn::
specify the dn where the users are stored
(eg: ou=users,dc=domain,dc=com).

ldap_clientcertfile::
The path to a client cert file to use when talking to the LDAP
server. Note this requires 'ldap_clientkeyfile' to be set as well.

ldap_clientkeyfile::
The path to a key to be used with the client cert when talking to
the LDAP server. Note this requires 'ldap_clientcertfile' to be
set as well.

ldap_bind_user::
The user to attempt a LDAP bind as.

Expand Down
12 changes: 12 additions & 0 deletions pam_yubico.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ 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.

*urllist*=_list_::
List of URL templates to be used. This is set by calling ykclient_set_url_bases.
The list should be in the format:
Expand Down Expand Up @@ -74,6 +80,12 @@ The LDAP server host (default LDAP port is used). *Deprecated. Use 'ldap_uri' in
*ldapdn*=_dn_::
The distinguished name (DN) where the users are stored (eg: ou=users,dc=domain,dc=com). If 'ldap_filter' is used this is the base from which the subtree search will be performed.

*ldap_clientcertfile*=_clientcertfile_::
The path to a client cert file to use when talking to the LDAP server. Note this requires 'ldap_clientkeyfile' to be set as well.

*ldap_clientkeyfile*=_clientkeyfile_::
The path to a key to be used with the client cert when talking to the LDAP server. Note this requires 'ldap_clientcertfile' to be set as well.

*user_attr*=_attr_::
The LDAP attribute used to store user names (eg:cn).

Expand Down
77 changes: 64 additions & 13 deletions pam_yubico.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ 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;
const char *cainfo;
Expand All @@ -123,6 +125,8 @@ struct cfg
const char *ldap_filter;
const char *ldap_cacertfile;
const char *ldapdn;
const char *ldap_clientcertfile;
const char *ldap_clientkeyfile;
const char *user_attr;
const char *yubi_attr;
const char *yubi_attr_prefix;
Expand Down Expand Up @@ -229,7 +233,8 @@ authorize_user_token (struct cfg *cfg,
static int
authorize_user_token_ldap (struct cfg *cfg,
const char *user,
const char *token_id)
const char *token_id,
pam_handle_t *pamh)
{
int retval = AUTH_ERROR;
#ifdef HAVE_LIBLDAP
Expand Down Expand Up @@ -288,19 +293,27 @@ authorize_user_token_ldap (struct cfg *cfg,
/* Set CA CERTFILE. This makes ldaps work when using ldap_uri */
ldap_set_option (0, LDAP_OPT_X_TLS_CACERTFILE, cfg->ldap_cacertfile);
}
/* Bind anonymously to the LDAP server. */
if (cfg->ldap_bind_user && cfg->ldap_bind_password) {
DBG ("try bind with: %s:[%s]", cfg->ldap_bind_user, cfg->ldap_bind_password);
rc = ldap_simple_bind_s (ld, cfg->ldap_bind_user, cfg->ldap_bind_password);
} else {
DBG ("try anonymous bind");
rc = ldap_simple_bind_s (ld, NULL, NULL);

if (cfg->ldap_clientcertfile && cfg->ldap_clientkeyfile) {
rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, cfg->ldap_clientcertfile);
if (rc != LDAP_SUCCESS) {
DBG ("tls_certfile: %s", ldap_err2string (rc));
goto done;
}
rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, cfg->ldap_clientkeyfile);
if (rc != LDAP_SUCCESS) {
DBG ("tls_keyfile: %s", ldap_err2string (rc));
goto done;
}
}
if (rc != LDAP_SUCCESS)
{
DBG ("ldap_simple_bind_s: %s", ldap_err2string (rc));

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) {
Expand All @@ -318,6 +331,32 @@ authorize_user_token_ldap (struct cfg *cfg,
} else if (cfg->ldapdn) {
find = strdup(cfg->ldapdn); /* allow free later */
}

/* Bind to the LDAP server. */
if (cfg->ldap_bind_as_user && cfg->user_attr && cfg->yubi_attr && cfg->ldapdn) {
/* Bind as the user logging in with their password they provided to PAM */
const char *bind_password = NULL;
rc = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &bind_password);
if (rc != PAM_SUCCESS) {
DBG ("pam_get_item failed to retrieve password: %s", pam_strerror (pamh, rc));
goto done;
}
DBG ("try bind as user with: %s", find);
rc = ldap_simple_bind_s (ld, find, bind_password);
} else if (cfg->ldap_bind_user && cfg->ldap_bind_password) {
/* Bind with a provided username and password */
DBG ("try bind with: %s:[%s]", cfg->ldap_bind_user, cfg->ldap_bind_password);
rc = ldap_simple_bind_s (ld, cfg->ldap_bind_user, cfg->ldap_bind_password);
} else {
DBG ("try anonymous bind");
rc = ldap_simple_bind_s (ld, NULL, NULL);
}
if (rc != LDAP_SUCCESS)
{
DBG ("ldap_simple_bind_s: %s", ldap_err2string (rc));
goto done;
}

if (cfg->ldap_filter) {
filter = filter_printf(cfg->ldap_filter, user);
scope = LDAP_SCOPE_SUBTREE;
Expand Down Expand Up @@ -766,6 +805,10 @@ 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)
cfg->auth_file = argv[i] + 9;
if (strncmp (argv[i], "capath=", 7) == 0)
Expand All @@ -790,6 +833,10 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
cfg->ldap_filter = argv[i] + 12;
if (strncmp (argv[i], "ldap_cacertfile=", 16) == 0)
cfg->ldap_cacertfile = argv[i] + 16;
if (strncmp (argv[i], "ldap_clientcertfile=", 20) == 0)
cfg->ldap_clientcertfile = argv[i] + 20;
if (strncmp (argv[i], "ldap_clientkeyfile=", 19) == 0)
cfg->ldap_clientkeyfile = argv[i] + 19;
if (strncmp (argv[i], "ldapdn=", 7) == 0)
cfg->ldapdn = argv[i] + 7;
if (strncmp (argv[i], "user_attr=", 10) == 0)
Expand Down Expand Up @@ -856,6 +903,8 @@ 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)");
DBG ("ldap_uri=%s", cfg->ldap_uri ? cfg->ldap_uri : "(null)");
Expand All @@ -864,6 +913,8 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
DBG ("ldap_filter=%s", cfg->ldap_filter ? cfg->ldap_filter : "(null)");
DBG ("ldap_cacertfile=%s", cfg->ldap_cacertfile ? cfg->ldap_cacertfile : "(null)");
DBG ("ldapdn=%s", cfg->ldapdn ? cfg->ldapdn : "(null)");
DBG ("ldap_clientcertfile=%s", cfg->ldap_clientcertfile ? cfg->ldap_clientcertfile : "(null)");
DBG ("ldap_clientkeyfile=%s", cfg->ldap_clientkeyfile ? cfg->ldap_clientkeyfile : "(null)");
DBG ("user_attr=%s", cfg->user_attr ? cfg->user_attr : "(null)");
DBG ("yubi_attr=%s", cfg->yubi_attr ? cfg->yubi_attr : "(null)");
DBG ("yubi_attr_prefix=%s", cfg->yubi_attr_prefix ? cfg->yubi_attr_prefix : "(null)");
Expand Down Expand Up @@ -1028,7 +1079,7 @@ pam_sm_authenticate (pam_handle_t * pamh,
/* we set otp_id to NULL so that no matches will ever be found
* but AUTH_NO_TOKENS will be returned if there are no tokens for the user */
if (cfg->ldapserver != NULL || cfg->ldap_uri != NULL)
valid_token = authorize_user_token_ldap (cfg, user, NULL);
valid_token = authorize_user_token_ldap (cfg, user, NULL, pamh);
else
valid_token = authorize_user_token (cfg, user, NULL, pamh);

Expand Down Expand Up @@ -1153,7 +1204,7 @@ pam_sm_authenticate (pam_handle_t * pamh,

/* authorize the user with supplied token id */
if (cfg->ldapserver != NULL || cfg->ldap_uri != NULL)
valid_token = authorize_user_token_ldap (cfg, user, otp_id);
valid_token = authorize_user_token_ldap (cfg, user, otp_id, pamh);
else
valid_token = authorize_user_token (cfg, user, otp_id, pamh);

Expand Down

0 comments on commit 6e4da68

Please sign in to comment.