version 1.202, 2015/04/24 06:26:49 |
version 1.203, 2015/05/15 05:44:21 |
|
|
#include <limits.h> |
#include <limits.h> |
#include <time.h> |
#include <time.h> |
#include <unistd.h> |
#include <unistd.h> |
|
#include <util.h> |
|
|
#include "key.h" /* XXX for typedef */ |
#include "key.h" /* XXX for typedef */ |
#include "buffer.h" /* XXX for typedef */ |
#include "buffer.h" /* XXX for typedef */ |
|
|
char socket_dir[PATH_MAX]; |
char socket_dir[PATH_MAX]; |
|
|
/* locking */ |
/* locking */ |
|
#define LOCK_SIZE 32 |
|
#define LOCK_SALT_SIZE 16 |
|
#define LOCK_ROUNDS 1 |
int locked = 0; |
int locked = 0; |
char *lock_passwd = NULL; |
char lock_passwd[LOCK_SIZE]; |
|
char lock_salt[LOCK_SALT_SIZE]; |
|
|
extern char *__progname; |
extern char *__progname; |
|
|
|
|
static void |
static void |
process_lock_agent(SocketEntry *e, int lock) |
process_lock_agent(SocketEntry *e, int lock) |
{ |
{ |
int r, success = 0; |
int r, success = 0, delay; |
char *passwd; |
char *passwd, passwdhash[LOCK_SIZE]; |
|
static u_int fail_count = 0; |
|
size_t pwlen; |
|
|
if ((r = sshbuf_get_cstring(e->request, &passwd, NULL)) != 0) |
if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0) |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { |
if (pwlen == 0) { |
locked = 0; |
debug("empty password not supported"); |
explicit_bzero(lock_passwd, strlen(lock_passwd)); |
} else if (locked && !lock) { |
free(lock_passwd); |
if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), |
lock_passwd = NULL; |
passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0) |
success = 1; |
fatal("bcrypt_pbkdf"); |
|
if (timingsafe_bcmp(passwdhash, lock_passwd, LOCK_SIZE) == 0) { |
|
debug("agent unlocked"); |
|
locked = 0; |
|
fail_count = 0; |
|
explicit_bzero(lock_passwd, sizeof(lock_passwd)); |
|
success = 1; |
|
} else { |
|
/* delay in 0.1s increments up to 10s */ |
|
if (fail_count < 100) |
|
fail_count++; |
|
delay = 100000 * fail_count; |
|
debug("unlock failed, delaying %0.1lf seconds", |
|
(double)delay/1000000); |
|
usleep(delay); |
|
} |
|
explicit_bzero(passwdhash, sizeof(passwdhash)); |
} else if (!locked && lock) { |
} else if (!locked && lock) { |
|
debug("agent locked"); |
locked = 1; |
locked = 1; |
lock_passwd = xstrdup(passwd); |
arc4random_buf(lock_salt, sizeof(lock_salt)); |
|
if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), |
|
lock_passwd, sizeof(lock_passwd), LOCK_ROUNDS) < 0) |
|
fatal("bcrypt_pbkdf"); |
success = 1; |
success = 1; |
} |
} |
explicit_bzero(passwd, strlen(passwd)); |
explicit_bzero(passwd, pwlen); |
free(passwd); |
free(passwd); |
send_status(e, success); |
send_status(e, success); |
} |
} |