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

Merge branch 'feature/ldap_refactor'

Conflicts:
	pam_yubico.c
This commit is contained in:
Klas Lindfors 2015-03-04 14:40:57 +01:00
commit 8241cd0423
8 changed files with 264 additions and 56 deletions

32
README
View File

@ -20,7 +20,7 @@ later. This has introduced a dependency of libykpers-1 from the
ykpersonalize package. Pass `--without-cr` to `configure` to avoid ykpersonalize package. Pass `--without-cr` to `configure` to avoid
this dependency. this dependency.
The development community is co-ordinated via The development community is co-ordinated via
https://github.com/Yubico/yubico-pam[the GitHub project page]. https://github.com/Yubico/yubico-pam[the GitHub project page].
The project is licensed under a BSD license. See the file COPYING for The project is licensed under a BSD license. See the file COPYING for
@ -150,7 +150,7 @@ service, go https://upgrade.yubico.com/getapikey[here].
debug:: to enable debug output to stdout. debug:: to enable debug output to stdout.
alwaysok:: alwaysok::
to enable all authentication attempts to succeed to enable all authentication attempts to succeed
(aka presentation mode). (aka presentation mode).
@ -310,10 +310,10 @@ information including the OTP and ID of your token to the shell -- copy the ID
into your config file and you should be up and going. into your config file and you should be up and going.
------ ------
Yubikey for `youruser': Yubikey for `youruser':
[pam_yubico.c:pam_sm_authenticate(867)] conv returned 44 bytes [pam_yubico.c:pam_sm_authenticate(867)] conv returned 44 bytes
[pam_yubico.c:pam_sm_authenticate(885)] Skipping first 0 bytes. Length is 44, token_id set to 12 and token OTP always 32. [pam_yubico.c:pam_sm_authenticate(885)] Skipping first 0 bytes. Length is 44, token_id set to 12 and token OTP always 32.
[pam_yubico.c:pam_sm_authenticate(892)] OTP: ccccccclabcabkhbdncicglfltnukadfoifadfhhhhfe ID: cccccclabcab [pam_yubico.c:pam_sm_authenticate(892)] OTP: ccccccclabcabkhbdncicglfltnukadfoifadfhhhhfe ID: cccccclabcab
------ ------
@ -336,5 +336,27 @@ Examples
If you want to use the YubiKey to authenticate you on Linux console If you want to use the YubiKey to authenticate you on Linux console
logins, add the following to the top of `/etc/pam.d/login`: logins, add the following to the top of `/etc/pam.d/login`:
auth sufficient pam_yubico.so id=16 debug auth sufficient pam_yubico.so id=16 debug
OpenVPN and ActiveDirectory
---------------------------
create file '/etc/pam.d/openvpn':
auth required pam_yubico.so ldap_uri=ldap://ldap-srv debug id=19 yubi_attr=pager
ldapdn=dc=ad,dc=next-audience,dc=net
ldap_filter=(&(sAMAccountName=%u)(memberOf=CN=mygroup,OU=DefaultUser,DC=adivser,DC=net))
ldap_bind_user=bind_user ldap_bind_password=bind_password try_first_pass
account required pam_yubico.so
create file 'openvpn.conf'
plugin openvpn-plugin-auth-pam.so openvpn
Feedback
--------
If you want to discuss anything related to the Yubico PAM module,
please e-mail the mailing list yubico-devel@googlegroups.com.

View File

@ -57,10 +57,10 @@ This argument is used to show the OTP (One Time Password) when it is entered, i.
Specify the LDAP server URI (e.g. ldap://localhost). Specify the LDAP server URI (e.g. ldap://localhost).
*ldap_server*=_server_:: *ldap_server*=_server_::
Specify the LDAP server host (default LDAP port is used). *Deprecated. Use "ldap_uri" instead.* Specify the LDAP server host (default LDAP port is used). *Deprecated. Use 'ldap_uri' instead.*
*ldapdn*=_dn_:: *ldapdn*=_dn_::
The dn where the users are stored (eg: ou=users,dc=domain,dc=com). The 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.
*user_attr*=_attr_:: *user_attr*=_attr_::
The LDAP attribute used to store user names (eg:cn). The LDAP attribute used to store user names (eg:cn).
@ -74,12 +74,26 @@ The prefix of the LDAP attribute's value, in case of a generic attribute, used t
*token_id_length*=_length_:: *token_id_length*=_length_::
Length of ID prefixing the OTP (this is 12 if using the YubiCloud). Length of ID prefixing the OTP (this is 12 if using the YubiCloud).
*ldap_bind_user*=_user_::
The user to attempt a LDAP bind as.
*ldap_bind_password*=_password_::
The password to use on LDAP bind.
*ldap_filter*=_filter_::
An ldap filter to use for attempting to find the correct object in LDAP. In this string %u will be replaced with the username.
*ldap_cacertfile*=_cacertfile_::
Ca certfile for the LDAP connection.
== EXAMPLES == EXAMPLES
auth sufficient pam_yubico.so id=16 debug auth sufficient pam_yubico.so id=16 debug
auth required pam_yubico.so mode=challenge-response auth required pam_yubico.so mode=challenge-response
auth required pam_yubico.so id=16 ldap_uri=ldaps://ldap.example.com ldap_filter=(uid=%u) yubi_attr=yubiKeyId
== BUGS == BUGS
Report yubico-pam bugs in the issue tracker: https://github.com/Yubico/yubico-pam/issues Report yubico-pam bugs in the issue tracker: https://github.com/Yubico/yubico-pam/issues

View File

@ -113,6 +113,10 @@ struct cfg
const char *urllist; const char *urllist;
const char *ldapserver; const char *ldapserver;
const char *ldap_uri; const char *ldap_uri;
const char *ldap_bind_user;
const char *ldap_bind_password;
const char *ldap_filter;
const char *ldap_cacertfile;
const char *ldapdn; const char *ldapdn;
const char *user_attr; const char *user_attr;
const char *yubi_attr; const char *yubi_attr;
@ -193,8 +197,10 @@ free_out:
* This function will look in ldap id the token correspond to the * This function will look in ldap id the token correspond to the
* requested user. It will returns 0 for failure and 1 for success. * requested user. It will returns 0 for failure and 1 for success.
* *
* For the moment ldaps is not supported. ldap serve can be on a * ldaps is only supported for ldap_uri based connections.
* remote host. * ldap_cacertfile usually needs to be set for this to work.
*
* ldap serve can be on a remote host.
* *
* You need the following parameters in you pam config: * You need the following parameters in you pam config:
* ldapserver= OR ldap_uri= * ldapserver= OR ldap_uri=
@ -202,6 +208,9 @@ free_out:
* user_attr= * user_attr=
* yubi_attr= * yubi_attr=
* *
* If using ldap_uri, you can specify multiple failover hosts
* eg.
* ldap_uri=ldaps://host1.fqdn.example.com,ldaps://host2.fqdn.example.com
*/ */
static int static int
authorize_user_token_ldap (struct cfg *cfg, authorize_user_token_ldap (struct cfg *cfg,
@ -222,21 +231,18 @@ authorize_user_token_ldap (struct cfg *cfg,
struct berval **vals; struct berval **vals;
int i, rc; int i, rc;
char *filter = NULL;
char *find = NULL; char *find = NULL;
int scope = LDAP_SCOPE_BASE;
#endif #endif
DBG(("called")); DBG(("called"));
#ifdef HAVE_LIBLDAP #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) { if (cfg->yubi_attr == NULL) {
DBG (("Trying to look up user to YubiKey mapping in LDAP, but yubi_attr not set!")); DBG (("Trying to look up user to YubiKey mapping in LDAP, but yubi_attr not set!"));
return 0; return 0;
} }
if (cfg->ldapdn == NULL) { if (cfg->user_attr && cfg->ldapdn == NULL) {
DBG (("Trying to look up user to YubiKey mapping in LDAP, but ldapdn not set!")); DBG (("Trying to look up user to YubiKey mapping in LDAP, user_attr set but ldapdn not set!"));
return 0; return 0;
} }
@ -246,7 +252,7 @@ authorize_user_token_ldap (struct cfg *cfg,
rc = ldap_initialize (&ld, cfg->ldap_uri); rc = ldap_initialize (&ld, cfg->ldap_uri);
if (rc != LDAP_SUCCESS) if (rc != LDAP_SUCCESS)
{ {
DBG (("ldap_init: %s", ldap_err2string (rc))); DBG (("ldap_initialize: %s", ldap_err2string (rc)));
retval = 0; retval = 0;
goto done; goto done;
} }
@ -261,10 +267,21 @@ authorize_user_token_ldap (struct cfg *cfg,
} }
} }
ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol); ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol);
if (cfg->ldap_uri && cfg->ldap_cacertfile) {
/* 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. */ /* 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 {
DBG (("try bind anonymous"));
rc = ldap_simple_bind_s (ld, NULL, NULL);
}
if (rc != LDAP_SUCCESS) if (rc != LDAP_SUCCESS)
{ {
DBG (("ldap_simple_bind_s: %s", ldap_err2string (rc))); DBG (("ldap_simple_bind_s: %s", ldap_err2string (rc)));
@ -273,22 +290,30 @@ authorize_user_token_ldap (struct cfg *cfg,
} }
/* Allocation of memory for search strings depending on input size */ /* Allocation of memory for search strings depending on input size */
i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char); if (cfg->user_attr && cfg->yubi_attr && cfg->ldapdn) {
if ((find = malloc(i)) == NULL) { i = (strlen(cfg->user_attr) + strlen(cfg->ldapdn) + strlen(user) + 3) * sizeof(char);
DBG (("Failed allocating %i bytes", i)); if ((find = malloc(i)) == NULL) {
retval = 0; DBG (("Failed allocating %i bytes", i));
goto done; retval = 0;
goto done;
}
sprintf (find, "%s=%s,%s", cfg->user_attr, user, cfg->ldapdn);
filter = NULL;
} else if (cfg->ldapdn) {
find = strdup(cfg->ldapdn); /* allow free later */
}
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; 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. */ /* Search for the entry. */
if ((rc = ldap_search_ext_s (ld, find, LDAP_SCOPE_BASE, if ((rc = ldap_search_ext_s (ld, find, scope,
NULL, attrs, 0, NULL, NULL, LDAP_NO_LIMIT, filter, attrs, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result)) != LDAP_SUCCESS) LDAP_NO_LIMIT, &result)) != LDAP_SUCCESS)
{ {
DBG (("ldap_search_ext_s: %s", ldap_err2string (rc))); DBG (("ldap_search_ext_s: %s", ldap_err2string (rc)));
@ -312,16 +337,16 @@ authorize_user_token_ldap (struct cfg *cfg,
{ {
if ((vals = ldap_get_values_len (ld, e, a)) != NULL) 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));
yubi_attr_prefix_len = cfg->yubi_attr_prefix ? strlen(cfg->yubi_attr_prefix) : 0; yubi_attr_prefix_len = cfg->yubi_attr_prefix ? strlen(cfg->yubi_attr_prefix) : 0;
/* Compare each value for the attribute against the token id. */ /* Compare each value for the attribute against the token id. */
for (i = 0; vals[i] != NULL; i++) for (i = 0; vals[i] != NULL; i++)
{ {
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));
/* Only values containing this prefix are considered. */ /* Only values containing this prefix are considered. */
if ((!cfg->yubi_attr_prefix || !strncmp (cfg->yubi_attr_prefix, vals[i]->bv_val, yubi_attr_prefix_len))) if ((!cfg->yubi_attr_prefix || !strncmp (cfg->yubi_attr_prefix, vals[i]->bv_val, yubi_attr_prefix_len)))
{ {
@ -349,6 +374,8 @@ authorize_user_token_ldap (struct cfg *cfg,
/* free memory allocated for search strings */ /* free memory allocated for search strings */
if (find != NULL) if (find != NULL)
free(find); free(find);
if (filter != NULL)
free(filter);
#else #else
DBG (("Trying to use LDAP, but this function is not compiled in pam_yubico!!")); DBG (("Trying to use LDAP, but this function is not compiled in pam_yubico!!"));
@ -671,6 +698,14 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
cfg->ldapserver = argv[i] + 11; cfg->ldapserver = argv[i] + 11;
if (strncmp (argv[i], "ldap_uri=", 9) == 0) if (strncmp (argv[i], "ldap_uri=", 9) == 0)
cfg->ldap_uri = argv[i] + 9; cfg->ldap_uri = argv[i] + 9;
if (strncmp (argv[i], "ldap_bind_user=", 15) == 0)
cfg->ldap_bind_user = argv[i] + 15;
if (strncmp (argv[i], "ldap_bind_password=", 19) == 0)
cfg->ldap_bind_password = argv[i] + 19;
if (strncmp (argv[i], "ldap_filter=", 12) == 0)
cfg->ldap_filter = argv[i] + 12;
if (strncmp (argv[i], "ldap_cacertfile=", 16) == 0)
cfg->ldap_cacertfile = argv[i] + 16;
if (strncmp (argv[i], "ldapdn=", 7) == 0) if (strncmp (argv[i], "ldapdn=", 7) == 0)
cfg->ldapdn = argv[i] + 7; cfg->ldapdn = argv[i] + 7;
if (strncmp (argv[i], "user_attr=", 10) == 0) if (strncmp (argv[i], "user_attr=", 10) == 0)
@ -705,6 +740,10 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
D (("authfile=%s", cfg->auth_file ? cfg->auth_file : "(null)")); D (("authfile=%s", cfg->auth_file ? cfg->auth_file : "(null)"));
D (("ldapserver=%s", cfg->ldapserver ? cfg->ldapserver : "(null)")); D (("ldapserver=%s", cfg->ldapserver ? cfg->ldapserver : "(null)"));
D (("ldap_uri=%s", cfg->ldap_uri ? cfg->ldap_uri : "(null)")); D (("ldap_uri=%s", cfg->ldap_uri ? cfg->ldap_uri : "(null)"));
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 (("ldap_cacertfile=%s", cfg->ldap_cacertfile ? cfg->ldap_cacertfile : "(null)"));
D (("ldapdn=%s", cfg->ldapdn ? cfg->ldapdn : "(null)")); D (("ldapdn=%s", cfg->ldapdn ? cfg->ldapdn : "(null)"));
D (("user_attr=%s", cfg->user_attr ? cfg->user_attr : "(null)")); D (("user_attr=%s", cfg->user_attr ? cfg->user_attr : "(null)"));
D (("yubi_attr=%s", cfg->yubi_attr ? cfg->yubi_attr : "(null)")); D (("yubi_attr=%s", cfg->yubi_attr ? cfg->yubi_attr : "(null)"));
@ -741,6 +780,7 @@ pam_sm_authenticate (pam_handle_t * pamh,
size_t templates = 0; size_t templates = 0;
char *urls[10]; char *urls[10];
char *tmpurl = NULL; char *tmpurl = NULL;
char *onlypasswd = NULL;
parse_cfg (flags, argc, argv, cfg); parse_cfg (flags, argc, argv, cfg);
@ -936,7 +976,7 @@ pam_sm_authenticate (pam_handle_t * pamh,
/* user entered their system password followed by generated OTP? */ /* user entered their system password followed by generated OTP? */
if (password_len > TOKEN_OTP_LEN + cfg->token_id_length) if (password_len > TOKEN_OTP_LEN + cfg->token_id_length)
{ {
char *onlypasswd = strdup (password); onlypasswd = strdup (password);
if (! onlypasswd) { if (! onlypasswd) {
retval = PAM_BUF_ERR; retval = PAM_BUF_ERR;
@ -949,7 +989,6 @@ pam_sm_authenticate (pam_handle_t * pamh,
"setting item PAM_AUTHTOK")); "setting item PAM_AUTHTOK"));
retval = pam_set_item (pamh, PAM_AUTHTOK, onlypasswd); retval = pam_set_item (pamh, PAM_AUTHTOK, onlypasswd);
free (onlypasswd);
if (retval != PAM_SUCCESS) if (retval != PAM_SUCCESS)
{ {
DBG (("set_item returned error: %s", pam_strerror (pamh, retval))); DBG (("set_item returned error: %s", pam_strerror (pamh, retval)));
@ -1008,6 +1047,8 @@ pam_sm_authenticate (pam_handle_t * pamh,
} }
done: done:
if (onlypasswd)
free(onlypasswd);
if (templates > 0) if (templates > 0)
{ {
size_t i; size_t i;
@ -1029,7 +1070,7 @@ done:
retval = PAM_SUCCESS; retval = PAM_SUCCESS;
} }
DBG (("done. [%s]", pam_strerror (pamh, retval))); DBG (("done. [%s]", pam_strerror (pamh, retval)));
pam_set_data (pamh, "yubico_setcred_return", (void*) (intptr_t) retval, NULL); pam_set_data (pamh, "yubico_setcred_return", (void*)(intptr_t)retval, NULL);
if (resp) if (resp)
{ {
@ -1047,16 +1088,55 @@ pam_sm_setcred (pam_handle_t * pamh, int flags, int argc, const char **argv)
return PAM_SUCCESS; return PAM_SUCCESS;
} }
PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
int retval;
int rc = pam_get_data(pamh, "yubico_setcred_return", (const void**)&retval);
if (rc == PAM_SUCCESS && retval == PAM_SUCCESS) {
D (("pam_sm_acct_mgmt returing PAM_SUCCESS"));
return PAM_SUCCESS;
}
D (("pam_sm_acct_mgmt returing PAM_AUTH_ERR:%d", rc));
return PAM_AUTH_ERR;
}
PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
D(("pam_sm_open_session"));
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_close_session(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
D(("pam_sm_close_session"));
return (PAM_SUCCESS);
}
PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
D(("pam_sm_chauthtok"));
return (PAM_SERVICE_ERR);
}
#ifdef PAM_STATIC #ifdef PAM_STATIC
struct pam_module _pam_yubico_modstruct = { struct pam_module _pam_yubico_modstruct = {
"pam_yubico", "pam_yubico",
pam_sm_authenticate, pam_sm_authenticate,
pam_sm_setcred, pam_sm_setcred,
NULL, pam_sm_acct_mgmt,
NULL, pam_sm_open_session,
NULL, pam_sm_close_session,
NULL pam_sm_chauthtok
}; };
#endif #endif

View File

@ -43,8 +43,9 @@ use constant RESULT_OK => {
}; };
my %objects = ( my %objects = (
'uid=foo,ou=users,dc=example,dc=com' => ['vvincredible'], 'base=uid=foo,ou=users,dc=example,dc=com' => {keys => ['vvincredible']},
'uid=test,ou=users,dc=example,dc=com' =>['cccccccfhcbe', 'ccccccbchvth'], 'base=uid=test,ou=users,dc=example,dc=com' => {keys => ['cccccccfhcbe', 'ccccccbchvth']},
'sub:base=:(uid=test)' => {keys => ['cccccccfhcbe', 'ccccccbchvth'], dn => 'uid=test,out=users,dc=example,dc=com'},
); );
sub bind { sub bind {
@ -56,14 +57,22 @@ sub bind {
sub search { sub search {
my $self = shift; my $self = shift;
my $reqData = shift; my $reqData = shift;
my $base = $reqData->{'baseObject'}; my $id;
my $id = $objects{$base}; my $base;
if($reqData->{'scope'} == 0) {
$base = $reqData->{'baseObject'};
$id = $objects{'base=' . $base};
} elsif($reqData->{'scope'} == 2) {
my $match = $reqData->{'filter'}->{'equalityMatch'};
$id = $objects{'sub:base=' . $reqData->{'baseObject'} . ':(' . $match->{'attributeDesc'} . '=' . $match->{'assertionValue'} . ')'};
$base = $id->{'dn'};
}
my @entries; my @entries;
if($id) { if($id) {
my $entry = Net::LDAP::Entry->new; my $entry = Net::LDAP::Entry->new;
$entry->dn($base); $entry->dn($base);
$entry->add(objectClass => [ "person" ]); $entry->add(objectClass => [ "person" ]);
$entry->add(yubiKeyId => $id); $entry->add(yubiKeyId => $id->{'keys'});
push @entries, $entry; push @entries, $entry;
} }
return RESULT_OK, @entries; return RESULT_OK, @entries;

View File

@ -63,7 +63,6 @@ static struct data {
static const char *ldap_cfg[] = { static const char *ldap_cfg[] = {
"id=1", "id=1",
"urllist=http://localhost:"YKVAL_PORT2"/wsapi/2/verify;http://localhost:"YKVAL_PORT1"/wsapi/2/verify", "urllist=http://localhost:"YKVAL_PORT2"/wsapi/2/verify;http://localhost:"YKVAL_PORT1"/wsapi/2/verify",
"authfile="AUTHFILE,
"ldap_uri=ldap://localhost:"LDAP_PORT, "ldap_uri=ldap://localhost:"LDAP_PORT,
"ldapdn=ou=users,dc=example,dc=com", "ldapdn=ou=users,dc=example,dc=com",
"user_attr=uid", "user_attr=uid",
@ -71,6 +70,15 @@ static const char *ldap_cfg[] = {
"debug" "debug"
}; };
static const char *ldap_cfg2[] = {
"id=1",
"urllist=http://localhost:"YKVAL_PORT1"/wsapi/2/verify;http://localhost:"YKVAL_PORT2"/wsapi/2/verify",
"ldap_uri=ldap://localhost:"LDAP_PORT,
"ldap_filter=(uid=%u)",
"yubi_attr=yubiKeyId",
"debug"
};
static const struct data *test_get_data(void *id) { static const struct data *test_get_data(void *id) {
return &_data[(long)id]; return &_data[(long)id];
} }
@ -212,6 +220,10 @@ static int test_authenticate_ldap2(void) {
return pam_sm_authenticate(4, 0, sizeof(ldap_cfg) / sizeof(char*), ldap_cfg); return pam_sm_authenticate(4, 0, sizeof(ldap_cfg) / sizeof(char*), ldap_cfg);
} }
static int test_authenticate_ldap3(void) {
return pam_sm_authenticate(4, 0, sizeof(ldap_cfg2) / sizeof(char*), ldap_cfg2);
}
static pid_t run_mock(const char *port, const char *type) { static pid_t run_mock(const char *port, const char *type) {
pid_t pid = fork(); pid_t pid = fork();
if(pid == 0) { if(pid == 0) {
@ -251,28 +263,32 @@ int main(void) {
ret = 5; ret = 5;
goto out; goto out;
} }
#ifdef HAVE_LIBLDAP if(test_authenticate3() != PAM_SUCCESS) {
if(test_authenticate_ldap1() != PAM_SUCCESS) {
ret = 6; ret = 6;
goto out; goto out;
} }
#ifdef HAVE_LIBLDAP
if(test_authenticate_ldap1() != PAM_SUCCESS) {
ret = 1001;
goto out;
}
if(test_authenticate_ldap_fail1() != PAM_USER_UNKNOWN) { if(test_authenticate_ldap_fail1() != PAM_USER_UNKNOWN) {
ret = 7; ret = 1002;
goto out; goto out;
} }
if(test_authenticate_ldap_fail2() != PAM_AUTH_ERR) { if(test_authenticate_ldap_fail2() != PAM_AUTH_ERR) {
ret = 8; ret = 1003;
goto out; goto out;
} }
if(test_authenticate_ldap2() != PAM_SUCCESS) { if(test_authenticate_ldap2() != PAM_SUCCESS) {
ret = 9; ret = 1004;
goto out;
}
if(test_authenticate_ldap3() != PAM_SUCCESS) {
ret = 1005;
goto out; goto out;
} }
#endif #endif
if(test_authenticate3() != PAM_SUCCESS) {
ret = 10;
goto out;
}
out: out:
kill(child, 9); kill(child, 9);

View File

@ -125,7 +125,27 @@ static void test_load_chalresp_state(void) {
#endif /* HAVE_CR */ #endif /* HAVE_CR */
static void test_filter_printf(void) {
assert(filter_result_len("meno %u", "doof", NULL) == 10);
assert(filter_result_len("meno %u %u", "doof", NULL) == 15);
assert(filter_result_len("%u meno %u", "doof", NULL) == 15);
assert(filter_result_len("%u me %u no %u", "doof", NULL) == 21);
assert(filter_result_len("meno %w %%u", "doof", NULL) == 14);
assert(filter_result_len("meno %w %%u meno", "doof", NULL) == 19);
assert(filter_result_len("meno ", "doof", NULL) == 6);
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) { int main (void) {
test_filter_printf();
test_get_user_cfgfile_path(); test_get_user_cfgfile_path();
test_check_user_token(); test_check_user_token();
#if HAVE_CR #if HAVE_CR

44
util.c
View File

@ -35,6 +35,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
@ -461,3 +464,44 @@ write_chalresp_state(FILE *f, CR_STATE *state)
return 0; return 0;
} }
#endif /* HAVE_CR */ #endif /* HAVE_CR */
size_t filter_result_len(const char *filter, const char *user, char *output) {
const char *part = NULL;
size_t result = 0;
do
{
size_t len;
part = strstr(filter, "%u");
if(part)
len = part - filter;
else
len = strlen(filter);
if (output)
{
strncpy(output, filter, len);
output += len;
}
result += len;
filter += len + 2;
if(part)
{
if(output)
{
strncpy(output, user, strlen(user));
output += strlen(user);
}
result += strlen(user);
}
}
while(part);
if(output)
*output = '\0';
return(result + 1);
}
char *filter_printf(const char *filter, const char *user) {
char *result = malloc(filter_result_len(filter, user, NULL));
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 */ #endif /* HAVE_CR */
size_t filter_result_len(const char *filter, const char *user, char *output);
char *filter_printf(const char *filter, const char *user);
#endif /* __PAM_YUBICO_UTIL_H_INCLUDED__ */ #endif /* __PAM_YUBICO_UTIL_H_INCLUDED__ */