1
0
mirror of https://github.com/Yubico/yubico-pam.git synced 2025-02-20 21:54:16 +01:00

added a better ldap handling, and to allow query active directory

This commit is contained in:
Meno Abels 2014-10-28 16:27:28 +01:00 committed by Meno Abels
parent b0e243835e
commit dae9380ac7
4 changed files with 125 additions and 23 deletions

View File

@ -113,6 +113,10 @@ struct cfg
const char *urllist;
const char *ldapserver;
const char *ldap_uri;
int ldap_bind_no_anonymous;
const char *ldap_bind_user;
const char *ldap_bind_password;
const char *ldap_filter;
const char *ldapdn;
const char *user_attr;
const char *yubi_attr;
@ -206,6 +210,7 @@ free_out:
static int
authorize_user_token_ldap (struct cfg *cfg,
const char *user,
const char *password,
const char *token_id)
{
int retval = 0;
@ -221,15 +226,12 @@ authorize_user_token_ldap (struct cfg *cfg,
struct berval **vals;
int i, rc;
const char *filter = NULL;
char *find = NULL;
int scope = LDAP_SCOPE_BASE;
#endif
DBG(("called"));
#ifdef HAVE_LIBLDAP
if (cfg->user_attr == NULL) {
DBG (("Trying to look up user to YubiKey mapping in LDAP, but user_attr not set!"));
return 0;
}
if (cfg->yubi_attr == NULL) {
DBG (("Trying to look up user to YubiKey mapping in LDAP, but yubi_attr not set!"));
return 0;
@ -265,7 +267,16 @@ authorize_user_token_ldap (struct cfg *cfg,
ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol);
/* Bind anonymously to the LDAP server. */
rc = ldap_simple_bind_s (ld, NULL, NULL);
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 if (cfg->ldap_bind_no_anonymous) {
DBG (("try bind with: %s:%s", user, password));
rc = ldap_simple_bind_s (ld, user, password);
} else {
DBG (("try bind anonymous"));
rc = ldap_simple_bind_s (ld, NULL, NULL);
}
if (rc != LDAP_SUCCESS)
{
DBG (("ldap_simple_bind_s: %s", ldap_err2string (rc)));
@ -274,22 +285,29 @@ authorize_user_token_ldap (struct cfg *cfg,
}
/* Allocation of memory for search strings depending on input size */
i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char);
if ((find = malloc(i)) == NULL) {
DBG (("Failed allocating %i bytes", i));
retval = 0;
goto done;
find = strdup(cfg->ldapdn); // allow free later-:)
if (cfg->user_attr && cfg->yubi_attr) {
i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char);
if ((find = malloc(i)) == NULL) {
DBG (("Failed allocating %i bytes", i));
retval = 0;
goto done;
}
sprintf (find, "%s=%s,%s", cfg->user_attr, user, cfg->ldapdn);
filter = NULL;
}
if (cfg->ldap_filter) {
filter = filter_printf(cfg->ldap_filter, user);
scope = LDAP_SCOPE_SUBTREE;
}
sprintf (find, "%s=%s,%s", cfg->user_attr, user, cfg->ldapdn);
attrs[0] = (char *) cfg->yubi_attr;
DBG(("LDAP : look up object '%s', ask for attribute '%s'", find, cfg->yubi_attr));
DBG(("LDAP : look up object base='%s' filter='%s', ask for attribute '%s'", find,
filter ? filter:"(null)", cfg->yubi_attr));
/* Search for the entry. */
if ((rc = ldap_search_ext_s (ld, find, LDAP_SCOPE_BASE,
NULL, attrs, 0, NULL, NULL, LDAP_NO_LIMIT,
if ((rc = ldap_search_ext_s (ld, find, scope,
filter, attrs, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result)) != LDAP_SUCCESS)
{
DBG (("ldap_search_ext_s: %s", ldap_err2string (rc)));
@ -313,10 +331,10 @@ authorize_user_token_ldap (struct cfg *cfg,
{
if ((vals = ldap_get_values_len (ld, e, a)) != NULL)
{
DBG(("LDAP : Found %i values - checking if any of them match '%s%s'",
ldap_count_values_len(vals),
cfg->yubi_attr_prefix ? cfg->yubi_attr_prefix : "",
token_id));
DBG(("LDAP : Found %i values - checking if any of them match '%s:%s:%s'",
ldap_count_values_len(vals),
vals[i]->bv_val,
cfg->yubi_attr_prefix ? cfg->yubi_attr_prefix : "", token_id));
yubi_attr_prefix_len = cfg->yubi_attr_prefix ? strlen(cfg->yubi_attr_prefix) : 0;
@ -350,6 +368,8 @@ authorize_user_token_ldap (struct cfg *cfg,
/* free memory allocated for search strings */
if (find != NULL)
free(find);
if (filter != NULL)
free(filter);
#else
DBG (("Trying to use LDAP, but this function is not compiled in pam_yubico!!"));
@ -666,6 +686,14 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
cfg->ldapserver = argv[i] + 11;
if (strncmp (argv[i], "ldap_uri=", 9) == 0)
cfg->ldap_uri = argv[i] + 9;
if (strncmp (argv[i], "ldap_bind_no_anonymous", sizeof("ldap_bind_no_anonymous")-1) == 0)
cfg->ldap_bind_no_anonymous = 1;
if (strncmp (argv[i], "ldap_bind_user=", sizeof("ldap_bind_user=")-1) == 0)
cfg->ldap_bind_user = argv[i] + sizeof("ldap_bind_user=")-1;
if (strncmp (argv[i], "ldap_bind_password=", sizeof("ldap_bind_password=")-1) == 0)
cfg->ldap_bind_password = argv[i] + sizeof("ldap_bind_password=")-1;
if (strncmp (argv[i], "ldap_filter=", sizeof("ldap_filter=")-1) == 0)
cfg->ldap_filter = argv[i] + sizeof("ldap_filter=")-1;
if (strncmp (argv[i], "ldapdn=", 7) == 0)
cfg->ldapdn = argv[i] + 7;
if (strncmp (argv[i], "user_attr=", 10) == 0)
@ -700,6 +728,10 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
D (("authfile=%s", cfg->auth_file ? cfg->auth_file : "(null)"));
D (("ldapserver=%s", cfg->ldapserver ? cfg->ldapserver : "(null)"));
D (("ldap_uri=%s", cfg->ldap_uri ? cfg->ldap_uri : "(null)"));
D (("ldap_bind_no_anonymous=%d", cfg->ldap_bind_no_anonymous));
D (("ldap_bind_user=%s", cfg->ldap_bind_user ? cfg->ldap_bind_user : "(null)"));
D (("ldap_bind_password=%s", cfg->ldap_bind_password ? cfg->ldap_bind_password : "(null)"));
D (("ldap_filter=%s", cfg->ldap_filter ? cfg->ldap_filter : "(null)"));
D (("ldapdn=%s", cfg->ldapdn ? cfg->ldapdn : "(null)"));
D (("user_attr=%s", cfg->user_attr ? cfg->user_attr : "(null)"));
D (("yubi_attr=%s", cfg->yubi_attr ? cfg->yubi_attr : "(null)"));
@ -922,9 +954,10 @@ pam_sm_authenticate (pam_handle_t * pamh,
DBG (("OTP: %s ID: %s ", otp, otp_id));
/* user entered their system password followed by generated OTP? */
char *onlypasswd = NULL;
if (password_len > TOKEN_OTP_LEN + cfg->token_id_length)
{
char *onlypasswd = strdup (password);
onlypasswd = strdup (password);
if (! onlypasswd) {
retval = PAM_BUF_ERR;
@ -969,7 +1002,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, onlypasswd, otp_id);
else
valid_token = authorize_user_token (cfg, user, otp_id, pamh);

View File

@ -125,7 +125,27 @@ static void test_load_chalresp_state(void) {
#endif /* HAVE_CR */
static void test_filter_printf(void) {
assert(filter_result_len("meno %u", "doof", NULL) == 9);
assert(filter_result_len("meno %u %u", "doof", NULL) == 14);
assert(filter_result_len("%u meno %u", "doof", NULL) == 14);
assert(filter_result_len("%u me %u no %u", "doof", NULL) == 20);
assert(filter_result_len("meno %w %%u", "doof", NULL) == 13);
assert(filter_result_len("meno %w %%u meno", "doof", NULL) == 18);
assert(filter_result_len("meno ", "doof", NULL) == 5);
assert(!strcmp(filter_printf("meno %u", "doof"), "meno doof"));
assert(!strcmp(filter_printf("meno %u %u", "doof"), "meno doof doof"));
assert(!strcmp(filter_printf("%u meno %u", "doof"), "doof meno doof"));
assert(!strcmp(filter_printf("%u me %u no %u", "doof"), "doof me doof no doof"));
assert(!strcmp(filter_printf("meno %w %%u", "doof"), "meno %w %doof"));
assert(!strcmp(filter_printf("meno %w %%u meno", "doof"), "meno %w %doof meno"));
assert(!strcmp(filter_printf("meno ", "doof"), "meno "));
printf("test_filter_printf OK\n");
}
int main (void) {
test_filter_printf();
test_get_user_cfgfile_path();
test_check_user_token();
#if HAVE_CR

46
util.c
View File

@ -35,6 +35,9 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <unistd.h>
@ -460,3 +463,46 @@ write_chalresp_state(FILE *f, CR_STATE *state)
return 0;
}
#endif /* HAVE_CR */
int filter_result_len(const char *filter, const char *user, char *output) {
int user_len = strlen(user);
int filter_len = strlen(filter);
const char *result;
int result_len = 0;
const char *percent_sign;
for (result = filter ; (percent_sign = strchr(result, '%')) ; result = percent_sign) {
if ((percent_sign + 1 - filter) > filter_len) {
break;
}
if (output) {
memcpy(output, result, percent_sign - result);
output += percent_sign - result;
}
if (*(percent_sign+1) == 'u') {
if (output) {
memcpy(output, user, user_len);
output += user_len;
}
result_len += (percent_sign - result) + user_len;
++percent_sign; // skip u
} else {
if (output) {
*output++ = '%';
}
result_len += percent_sign + 1 - result;
}
++percent_sign;
}
if (output) {
memcpy(output, result, ((filter+filter_len)-result) + 1);
}
return result_len + (filter+filter_len-result);
}
const char *filter_printf(const char *filter, const char *user) {
char *result = malloc(filter_result_len(filter, user, NULL) + 1);
filter_result_len(filter, user, result);
return result;
}

3
util.h
View File

@ -96,4 +96,7 @@ int challenge_response(YK_KEY *yk, int slot,
#endif /* HAVE_CR */
int filter_result_len(const char *filter, const char *user, char *output);
const char *filter_printf(const char *filter, const char *user);
#endif /* __PAM_YUBICO_UTIL_H_INCLUDED__ */