mirror of
https://github.com/Yubico/yubico-pam.git
synced 2024-12-01 15:24:12 +01:00
Support challenge-response files outside user's home directory.
Having the challege-response data inside the home directory won't work very well if the YubiKey is to unlock an ecryptfs encrypted home directory.
This commit is contained in:
parent
d9ee08b97f
commit
68cdb39132
70
pam_yubico.c
70
pam_yubico.c
@ -1,5 +1,5 @@
|
|||||||
/* Written by Simon Josefsson <simon@yubico.com>.
|
/* Written by Simon Josefsson <simon@yubico.com>.
|
||||||
* Copyright (c) 2006, 2007, 2008, 2009, 2010 Yubico AB
|
* Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 Yubico AB
|
||||||
* Copyright (c) 2011 Tollef Fog Heen <tfheen@err.no>
|
* Copyright (c) 2011 Tollef Fog Heen <tfheen@err.no>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@ -380,6 +380,7 @@ struct cfg
|
|||||||
char *yubi_attr;
|
char *yubi_attr;
|
||||||
int token_id_length;
|
int token_id_length;
|
||||||
enum key_mode mode;
|
enum key_mode mode;
|
||||||
|
char *chalresp_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fill buf with len/2 bytes of random data (hex-encoded) */
|
/* Fill buf with len/2 bytes of random data (hex-encoded) */
|
||||||
@ -402,12 +403,49 @@ static int generate_challenge(char *buf, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
do_challenge_response(const char *username)
|
get_user_challenge_file(struct cfg *cfg, const char *username, char **fn)
|
||||||
{
|
{
|
||||||
/* Getting file from user home directory, i.e. ~/.yubico/challenge.
|
/* Getting file from user home directory, i.e. ~/.yubico/challenge, or
|
||||||
Format is hex(challenge):hex(response):slot num */
|
* from a system wide directory.
|
||||||
|
*
|
||||||
|
* Format is hex(challenge):hex(response):slot num
|
||||||
|
*/
|
||||||
struct passwd *p;
|
struct passwd *p;
|
||||||
|
char *userfile;
|
||||||
|
|
||||||
|
if (cfg->chalresp_path) {
|
||||||
|
if (asprintf (&userfile, "%s/%s", cfg->chalresp_path, username) >= 0)
|
||||||
|
*fn = userfile;
|
||||||
|
return (userfile >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The challenge to use is located in a file in the user's home directory,
|
||||||
|
* which therefor can't be encrypted.
|
||||||
|
*/
|
||||||
|
#define USERFILE "/.yubico/challenge"
|
||||||
|
|
||||||
|
p = getpwnam (username);
|
||||||
|
if (!p)
|
||||||
|
goto out;
|
||||||
|
userfile = malloc ((p->pw_dir ? strlen (p->pw_dir) : 0)
|
||||||
|
+ strlen (USERFILE) + 1);
|
||||||
|
if (!userfile)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
strcpy (userfile, p->pw_dir);
|
||||||
|
strcat (userfile, USERFILE);
|
||||||
|
|
||||||
|
*fn = userfile;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_challenge_response(struct cfg *cfg, const char *username)
|
||||||
|
{
|
||||||
char *userfile = NULL;
|
char *userfile = NULL;
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
char challenge_hex[64], expected_response[64];
|
char challenge_hex[64], expected_response[64];
|
||||||
@ -426,18 +464,14 @@ do_challenge_response(const char *username)
|
|||||||
ret = PAM_AUTH_ERR;
|
ret = PAM_AUTH_ERR;
|
||||||
flags |= YK_FLAG_MAYBLOCK;
|
flags |= YK_FLAG_MAYBLOCK;
|
||||||
|
|
||||||
#define USERFILE "/.yubico/challenge"
|
if (! get_user_challenge_file (cfg, username, &userfile)) {
|
||||||
|
D(("Failed getting user challenge file for user %s", username));
|
||||||
p = getpwnam (username);
|
|
||||||
if (!p)
|
|
||||||
goto out;
|
|
||||||
userfile = malloc ((p->pw_dir ? strlen (p->pw_dir) : 0)
|
|
||||||
+ strlen (USERFILE) + 1);
|
|
||||||
if (!userfile)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy (userfile, p->pw_dir);
|
D(("Loading challenge from file %s", userfile));
|
||||||
strcat (userfile, USERFILE);
|
|
||||||
|
/* XXX should drop root privileges before opening file in user's home directory */
|
||||||
f = fopen(userfile, "r+");
|
f = fopen(userfile, "r+");
|
||||||
if (! f)
|
if (! f)
|
||||||
goto out;
|
goto out;
|
||||||
@ -538,6 +572,7 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
|
|||||||
cfg->yubi_attr = NULL;
|
cfg->yubi_attr = NULL;
|
||||||
cfg->token_id_length = DEFAULT_TOKEN_ID_LEN;
|
cfg->token_id_length = DEFAULT_TOKEN_ID_LEN;
|
||||||
cfg->mode = CLIENT;
|
cfg->mode = CLIENT;
|
||||||
|
cfg->chalresp_path = NULL;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
@ -577,6 +612,8 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
|
|||||||
cfg->mode = CHRESP;
|
cfg->mode = CHRESP;
|
||||||
if (strcmp (argv[i], "mode=client") == 0)
|
if (strcmp (argv[i], "mode=client") == 0)
|
||||||
cfg->mode = CLIENT;
|
cfg->mode = CLIENT;
|
||||||
|
if (strncmp (argv[i], "chalresp_path=", 14) == 0)
|
||||||
|
cfg->chalresp_path = (char *) argv[i] + 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg->debug)
|
if (cfg->debug)
|
||||||
@ -602,6 +639,7 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
|
|||||||
D (("capath=%s", cfg->capath ? cfg->capath : "(null)"));
|
D (("capath=%s", cfg->capath ? cfg->capath : "(null)"));
|
||||||
D (("token_id_length=%d", cfg->token_id_length));
|
D (("token_id_length=%d", cfg->token_id_length));
|
||||||
D (("mode=%s", cfg->mode == CLIENT ? "client" : "chresp" ));
|
D (("mode=%s", cfg->mode == CLIENT ? "client" : "chresp" ));
|
||||||
|
D (("chalresp_path=%d", cfg->chalresp_path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +675,7 @@ pam_sm_authenticate (pam_handle_t * pamh,
|
|||||||
DBG (("get user returned: %s", user));
|
DBG (("get user returned: %s", user));
|
||||||
|
|
||||||
if (cfg.mode == CHRESP) {
|
if (cfg.mode == CHRESP) {
|
||||||
return do_challenge_response(user);
|
return do_challenge_response(&cfg, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.try_first_pass || cfg.use_first_pass)
|
if (cfg.try_first_pass || cfg.use_first_pass)
|
||||||
|
Loading…
Reference in New Issue
Block a user