1
0
mirror of https://github.com/Yubico/yubico-pam.git synced 2025-01-19 07:52:23 +01:00

Move more challenge-response code to util.c.

This commit is contained in:
Fredrik Thulin 2011-03-17 15:04:29 +01:00 committed by Tollef Fog Heen
parent c557249503
commit 721866df0b
3 changed files with 145 additions and 38 deletions

View File

@ -64,10 +64,6 @@
# endif
#endif
#include <ykclient.h>
#include <ykcore.h>
#include <ykdef.h>
#ifdef HAVE_LIBLDAP
/* Some functions like ldap_init, ldap_simple_bind_s, ldap_unbind are
deprecated but still available. We will drop support for 'ldapserver'
@ -400,8 +396,8 @@ do_challenge_response(struct cfg *cfg, const char *username)
{
char *userfile = NULL, *tmpfile = NULL;
FILE *f = NULL;
char challenge[CR_CHALLENGE_SIZE + 1];
char challenge_hex[sizeof(challenge) * 2 + 1], expected_response[CR_RESPONSE_SIZE * 2 + 1];
unsigned char challenge[CR_CHALLENGE_SIZE + 1];
unsigned char challenge_hex[sizeof(challenge) * 2 + 1], expected_response[CR_RESPONSE_SIZE * 2 + 1];
int r, slot, ret, fd;
unsigned char response[CR_RESPONSE_SIZE + 16]; /* Need some extra bytes in this read buffer */
@ -447,38 +443,39 @@ do_challenge_response(struct cfg *cfg, const char *username)
goto out;
}
yubikey_hex_decode(challenge, challenge_hex, strlen(challenge_hex));
len = strlen(challenge_hex) / 2;
if (slot == 1) {
yk_cmd = SLOT_CHAL_HMAC1;
} else if (slot == 2) {
yk_cmd = SLOT_CHAL_HMAC2;
} else {
if (slot != 1 && slot != 2) {
D(("Invalid slot input : %i", slot));
}
if (!yk_init())
if (! init_yubikey(&yk)) {
D(("Failed initializing YubiKey"));
goto out;
}
if (!(yk = yk_open_first_key()))
if (! check_firmware_version(yk, false, true)) {
D(("YubiKey does not support Challenge-Response (version 2.2 required)"));
goto out;
}
if (!yk_write_to_key(yk, yk_cmd, challenge, len))
goto out;
yubikey_hex_decode(challenge, challenge_hex, sizeof(challenge));
len = strlen(challenge_hex) / 2;
if (! yk_read_response_from_key(yk, slot, flags,
&response, sizeof(response),
CR_RESPONSE_SIZE,
&response_len))
if (! challenge_response(yk, slot, challenge, len, true, flags, false,
response, sizeof(response), &response_len)) {
D(("Challenge-response FAILED"));
goto out;
/* response read includes some extra bytes (CRC etc.) */
if (response_len > CR_RESPONSE_SIZE)
response_len = CR_RESPONSE_SIZE;
}
/*
* Check YubiKey response against the expected response
*/
yubikey_hex_encode(response_hex, (char *)response, response_len);
if (strcmp(response_hex, expected_response) == 0) {
ret = PAM_SUCCESS;
} else {
D(("Unexpected C/R response : %s", response_hex));
D(("Unexpected C/R response : %s != %s", response_hex, expected_response));
ret = PAM_AUTH_ERR;
goto out;
}
@ -490,22 +487,19 @@ do_challenge_response(struct cfg *cfg, const char *username)
goto out;
}
if (!yk_write_to_key(yk, yk_cmd, challenge, CR_CHALLENGE_SIZE))
if (! challenge_response(yk, slot, challenge, CR_CHALLENGE_SIZE, true, flags, false,
response, sizeof(response), &response_len)) {
D(("Second challenge-response FAILED"));
goto out;
if (! yk_read_response_from_key(yk, slot, flags,
&response, sizeof(response),
CR_RESPONSE_SIZE,
&response_len))
goto out;
/* response read includes some extra bytes (CRC etc.) */
if (response_len > CR_RESPONSE_SIZE)
response_len = CR_RESPONSE_SIZE;
}
/* the yk_* functions leave 'junk' in errno */
errno = 0;
/*
* Write the challenge and response we will expect the next time to the state file.
*/
memset(challenge_hex, 0, sizeof(challenge_hex));
memset(response_hex, 0, sizeof(response_hex));
yubikey_hex_encode(challenge_hex, (char *)challenge, CR_CHALLENGE_SIZE);

105
util.c
View File

@ -39,8 +39,13 @@
#include "util.h"
#include <ykclient.h>
#include <ykcore.h>
#include <ykstatus.h>
#include <ykdef.h>
/* Fill buf with len bytes of random data */
static int generate_random(char *buf, int len)
int generate_random(char *buf, int len)
{
FILE *u;
int i, res;
@ -59,7 +64,7 @@ static int generate_random(char *buf, int len)
int
get_user_cfgfile_path(const char *common_path, const char *filename, const char *username, char **fn)
{
/* Getting file from user home directory, i.e. ~/.yubico/challenge, or
/* Getting file from user home directory, e.g. ~/.yubico/challenge, or
* from a system wide directory.
*
* Format is hex(challenge):hex(response):slot num
@ -83,3 +88,99 @@ get_user_cfgfile_path(const char *common_path, const char *filename, const char
*fn = userfile;
return (userfile >= 0);
}
int
check_firmware_version(YK_KEY *yk, bool verbose, bool quiet)
{
YK_STATUS *st = ykds_alloc();
if (!yk_get_status(yk, st)) {
free(st);
return 0;
}
if (verbose) {
printf("Firmware version %d.%d.%d\n",
ykds_version_major(st),
ykds_version_minor(st),
ykds_version_build(st));
fflush(stdout);
}
if (ykds_version_major(st) < 2 ||
ykds_version_minor(st) < 2) {
if (! quiet)
fprintf(stderr, "Challenge-response not supported before YubiKey 2.2.\n");
free(st);
return 0;
}
free(st);
return 1;
}
int
init_yubikey(YK_KEY **yk)
{
if (!yk_init())
return 0;
if (!(*yk = yk_open_first_key()))
return 0;
return 1;
}
int challenge_response(YK_KEY *yk, int slot,
unsigned char *challenge, unsigned int len,
bool hmac, unsigned int flags, bool verbose,
unsigned char *response, int res_size, int *res_len)
{
int yk_cmd;
unsigned int response_len = 0;
unsigned int expect_bytes = 0;
if (res_size < sizeof(64 + 16))
return 0;
memset(response, 0, sizeof(response));
if (verbose) {
fprintf(stderr, "Sending %i bytes %s challenge to slot %i\n", len, (hmac == true)?"HMAC":"Yubico", slot);
//_yk_hexdump(challenge, len);
}
switch(slot) {
case 1:
yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_OTP1;
break;
case 2:
yk_cmd = (hmac == true) ? SLOT_CHAL_HMAC2 : SLOT_CHAL_OTP2;
break;
}
if (!yk_write_to_key(yk, yk_cmd, challenge, len))
return 0;
if (verbose) {
fprintf(stderr, "Reading response...\n");
}
/* HMAC responses are 160 bits, Yubico 128 */
expect_bytes = (hmac == true) ? 20 : 16;
if (! yk_read_response_from_key(yk, slot, flags,
response, res_size,
expect_bytes,
&response_len))
return 0;
if (hmac && response_len > 20)
response_len = 20;
if (! hmac && response_len > 16)
response_len = 16;
*res_len = response_len;
return 1;
}

12
util.h
View File

@ -31,5 +31,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ykclient.h>
#include <ykcore.h>
#include <ykstatus.h>
#include <ykdef.h>
int generate_random(char *buf, int len);
int get_user_cfgfile_path(const char *common_path, const char *filename, const char *username, char **fn);
int init_yubikey(YK_KEY **yk);
int check_firmware_version(YK_KEY *yk, bool verbose, bool quiet);
int challenge_response(YK_KEY *yk, int slot,
unsigned char *challenge, unsigned int len,
bool hmac, unsigned int flags, bool verbose,
unsigned char *response, int res_size, int *res_len);