mirror of
https://github.com/clearml/dropbear
synced 2025-03-09 21:41:07 +00:00
merge of 3b1edf7489e1de452e30aaaec37d647db44e4328
and 6cdb6b2c0e0e0a600eeb5975e499c9303fe2d4d4 --HG-- extra : convert_revision : 6bf41e419b773e153b574b15005ab1e498643400
This commit is contained in:
commit
41f5e21044
@ -10,7 +10,7 @@
|
||||
# This makefile is quite evil.
|
||||
|
||||
ifndef PROGRAMS
|
||||
PROGRAMS=dropbear dbclient dropbearkey dropbearmulti
|
||||
PROGRAMS=dropbear dbclient dropbearkey dropbearkey
|
||||
endif
|
||||
|
||||
LTC=libtomcrypt/libtomcrypt.a
|
||||
@ -27,7 +27,8 @@ SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
|
||||
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o
|
||||
|
||||
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-service.o cli-runopts.o cli-chansession.o
|
||||
cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
|
||||
cli-authpubkey.o
|
||||
|
||||
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
|
||||
common-channel.o common-chansession.o termcodes.o loginrec.o \
|
||||
|
137
cli-kex.c
137
cli-kex.c
@ -37,6 +37,8 @@
|
||||
#include "signkey.h"
|
||||
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
|
||||
#define MAX_KNOWNHOSTS_LINE 4500
|
||||
|
||||
void send_msg_kexdh_init() {
|
||||
|
||||
@ -58,14 +60,22 @@ void recv_msg_kexdh_reply() {
|
||||
|
||||
mp_int dh_f;
|
||||
sign_key *hostkey = NULL;
|
||||
int type, keylen;
|
||||
unsigned int type, keybloblen;
|
||||
unsigned char* keyblob = NULL;
|
||||
|
||||
|
||||
TRACE(("enter recv_msg_kexdh_reply"));
|
||||
type = ses.newkeys->algo_hostkey;
|
||||
TRACE(("type is %d", type));
|
||||
|
||||
hostkey = new_sign_key();
|
||||
keylen = buf_getint(ses.payload);
|
||||
keybloblen = buf_getint(ses.payload);
|
||||
|
||||
keyblob = buf_getptr(ses.payload, keybloblen);
|
||||
if (!ses.kexstate.donefirstkex) {
|
||||
/* Only makes sense the first time */
|
||||
checkhostkey(keyblob, keybloblen);
|
||||
}
|
||||
|
||||
if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) {
|
||||
TRACE(("failed getting pubkey"));
|
||||
@ -86,9 +96,6 @@ void recv_msg_kexdh_reply() {
|
||||
dropbear_exit("Bad hostkey signature");
|
||||
}
|
||||
|
||||
/* XXX TODO */
|
||||
dropbear_log(LOG_WARNING,"Not checking hostkey fingerprint for the moment");
|
||||
|
||||
sign_key_free(hostkey);
|
||||
hostkey = NULL;
|
||||
|
||||
@ -96,3 +103,123 @@ void recv_msg_kexdh_reply() {
|
||||
ses.requirenext = SSH_MSG_NEWKEYS;
|
||||
TRACE(("leave recv_msg_kexdh_init"));
|
||||
}
|
||||
|
||||
static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
char* fp = NULL;
|
||||
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n",
|
||||
cli_opts.remotehost,
|
||||
fp);
|
||||
|
||||
if (getc(stdin) == 'y') {
|
||||
m_free(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("Didn't validate host key");
|
||||
}
|
||||
|
||||
static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
char * filename = NULL;
|
||||
FILE *hostsfile = NULL;
|
||||
struct passwd *pw = NULL;
|
||||
unsigned int len, hostlen;
|
||||
const char *algoname = NULL;
|
||||
buffer * line = NULL;
|
||||
int ret;
|
||||
|
||||
pw = getpwuid(getuid());
|
||||
|
||||
if (pw == NULL) {
|
||||
dropbear_exit("Failed to get homedir");
|
||||
}
|
||||
|
||||
len = strlen(pw->pw_dir);
|
||||
filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh", pw->pw_dir);
|
||||
/* Check that ~/.ssh exists - easiest way is just to mkdir */
|
||||
if (mkdir(filename, S_IRWXU) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
goto out; /* only get here on success */
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(filename, len+18, "%s/.ssh/known_hosts", pw->pw_dir);
|
||||
hostsfile = fopen(filename, "r+");
|
||||
if (hostsfile == NULL) {
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
goto out; /* We only get here on success */
|
||||
}
|
||||
|
||||
line = buf_new(MAX_KNOWNHOSTS_LINE);
|
||||
hostlen = strlen(cli_opts.remotehost);
|
||||
|
||||
do {
|
||||
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
|
||||
TRACE(("failed reading line: prob EOF"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* The line is too short to be sensible */
|
||||
/* "30" is 'enough to hold ssh-dss plus the spaces, ie so we don't
|
||||
* buf_getfoo() past the end and die horribly - the base64 parsing
|
||||
* code is what tiptoes up to the end nicely */
|
||||
if (line->len < (hostlen+30) ) {
|
||||
TRACE(("line is too short to be sensible"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare hostnames */
|
||||
if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen),
|
||||
hostlen) != 0) {
|
||||
TRACE(("hosts don't match"));
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_incrpos(line, hostlen);
|
||||
if (buf_getbyte(line) != ' ') {
|
||||
/* there wasn't a space after the hostname, something dodgy */
|
||||
TRACE(("missing space afte matching hostname"));
|
||||
continue;
|
||||
}
|
||||
|
||||
algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &len);
|
||||
if ( strncmp(buf_getptr(line, len), algoname, len) != 0) {
|
||||
TRACE(("algo doesn't match"));
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_incrpos(line, len);
|
||||
if (buf_getbyte(line) != ' ') {
|
||||
TRACE(("missing space after algo"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now we're at the interesting hostkey */
|
||||
ret = cmp_base64_key(keyblob, keybloblen, algoname, len, line);
|
||||
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
/* Good matching key */
|
||||
TRACE(("good matching key"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The keys didn't match. eep. */
|
||||
} while (1); /* keep going 'til something happens */
|
||||
|
||||
/* Key doesn't exist yet */
|
||||
ask_to_confirm(keyblob, keybloblen);
|
||||
/* If we get here, they said yes */
|
||||
|
||||
out:
|
||||
if (hostsfile != NULL) {
|
||||
fclose(hostsfile);
|
||||
}
|
||||
m_free(filename);
|
||||
buf_free(line);
|
||||
}
|
||||
|
@ -43,10 +43,10 @@ static void printhelp() {
|
||||
"Usage: %s [options] user@host\n"
|
||||
"Options are:\n"
|
||||
"-p <remoteport>\n"
|
||||
"-t Allocate a pty"
|
||||
"-T Don't allocate a pty"
|
||||
"-t Allocate a pty\n"
|
||||
"-T Don't allocate a pty\n"
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
"-i <identityfile> (multiple allowed)"
|
||||
"-i <identityfile> (multiple allowed)\n"
|
||||
#endif
|
||||
,DROPBEAR_VERSION, cli_opts.progname);
|
||||
}
|
||||
|
46
dbutil.c
46
dbutil.c
@ -320,6 +320,52 @@ int buf_readfile(buffer* buf, const char* filename) {
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
/* get a line from the file into buffer in the style expected for an
|
||||
* authkeys file.
|
||||
* Will return DROPBEAR_SUCCESS if data is read, or DROPBEAR_FAILURE on EOF.*/
|
||||
/* Only used for ~/.ssh/known_hosts and ~/.ssh/authorized_keys */
|
||||
#if defined(DROPBEAR_CLIENT) || defined(DROPBEAR_PUBKEY_AUTH)
|
||||
int buf_getline(buffer * line, FILE * authfile) {
|
||||
|
||||
int c = EOF;
|
||||
|
||||
TRACE(("enter buf_getline"));
|
||||
|
||||
buf_setpos(line, 0);
|
||||
buf_setlen(line, 0);
|
||||
|
||||
while (line->pos < line->size) {
|
||||
|
||||
c = fgetc(authfile); /*getc() is weird with some uClibc systems*/
|
||||
if (c == EOF || c == '\n' || c == '\r') {
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf_putbyte(line, (unsigned char)c);
|
||||
}
|
||||
|
||||
TRACE(("leave getauthline: line too long"));
|
||||
/* We return success, but the line length will be zeroed - ie we just
|
||||
* ignore that line */
|
||||
buf_setlen(line, 0);
|
||||
|
||||
out:
|
||||
|
||||
buf_setpos(line, 0);
|
||||
|
||||
/* if we didn't read anything before EOF or error, exit */
|
||||
if (c == EOF && line->pos == 0) {
|
||||
TRACE(("leave getauthline: failure"));
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
TRACE(("leave getauthline: success"));
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
TRACE(("leave buf_getline"));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* loop until the socket is closed (in case of EINTR) or
|
||||
* we get and error.
|
||||
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
||||
|
1
dbutil.h
1
dbutil.h
@ -49,6 +49,7 @@ int connect_remote(const char* remotehost, const char* remoteport,
|
||||
int nonblocking, char ** errstring);
|
||||
char* getaddrhostname(struct sockaddr * addr);
|
||||
int buf_readfile(buffer* buf, const char* filename);
|
||||
int buf_getline(buffer * line, FILE * authfile);
|
||||
|
||||
int m_close(int fd);
|
||||
void * m_malloc(size_t size);
|
||||
|
@ -301,6 +301,10 @@
|
||||
#define USING_LISTENERS
|
||||
#endif
|
||||
|
||||
#if defined(DROPBEAR_CLIENT) || defined(DROPBEAR_PUBKEY_AUTH)
|
||||
#define DROPBEAR_KEY_LINES /* ie we're using authorized_keys or known_hosts */
|
||||
#endif
|
||||
|
||||
/* We use dropbear_client and dropbear_server as shortcuts to avoid redundant
|
||||
* code, if we're just compiling as client or server */
|
||||
#if defined(DROPBEAR_SERVER) && defined(DROPBEAR_CLIENT)
|
||||
|
84
signkey.c
84
signkey.c
@ -272,25 +272,20 @@ static char hexdig(unsigned char x) {
|
||||
/* Since we're not sure if we'll have md5 or sha1, we present both.
|
||||
* MD5 is used in preference, but sha1 could still be useful */
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
static char * sign_key_md5_fingerprint(sign_key *key, int type) {
|
||||
static char * sign_key_md5_fingerprint(unsigned char* keyblob,
|
||||
unsigned int keybloblen) {
|
||||
|
||||
char * ret;
|
||||
hash_state hs;
|
||||
buffer *pubkeys;
|
||||
unsigned char hash[MD5_HASH_SIZE];
|
||||
unsigned int h, i;
|
||||
unsigned int buflen;
|
||||
|
||||
md5_init(&hs);
|
||||
|
||||
pubkeys = buf_new(1000);
|
||||
buf_put_pub_key(pubkeys, key, type);
|
||||
/* skip the size int of the string - this is a bit messy */
|
||||
buf_setpos(pubkeys, 4);
|
||||
md5_process(&hs, buf_getptr(pubkeys, pubkeys->len-pubkeys->pos),
|
||||
pubkeys->len-pubkeys->pos);
|
||||
md5_process(&hs, keyblob, keybloblen);
|
||||
|
||||
buf_free(pubkeys);
|
||||
md5_done(&hs, hash);
|
||||
|
||||
/* "md5 hexfingerprinthere\0", each hex digit is "AB:" etc */
|
||||
@ -311,25 +306,20 @@ static char * sign_key_md5_fingerprint(sign_key *key, int type) {
|
||||
}
|
||||
|
||||
#else /* use SHA1 rather than MD5 for fingerprint */
|
||||
static char * sign_key_sha1_fingerprint(sign_key *key, int type) {
|
||||
static char * sign_key_sha1_fingerprint(unsigned char* keyblob,
|
||||
unsigned int keybloblen) {
|
||||
|
||||
char * ret;
|
||||
hash_state hs;
|
||||
buffer *pubkeys;
|
||||
unsigned char hash[SHA1_HASH_SIZE];
|
||||
unsigned int h, i;
|
||||
unsigned int buflen;
|
||||
|
||||
sha1_init(&hs);
|
||||
|
||||
pubkeys = buf_new(1000);
|
||||
buf_put_pub_key(pubkeys, key, type);
|
||||
buf_setpos(pubkeys, 4);
|
||||
/* skip the size int of the string - this is a bit messy */
|
||||
sha1_process(&hs, buf_getptr(pubkeys, pubkeys->len-pubkeys->pos),
|
||||
pubkeys->len-pubkeys->pos);
|
||||
sha1_process(&hs, keyblob, keybloblen);
|
||||
|
||||
buf_free(pubkeys);
|
||||
sha1_done(&hs, hash);
|
||||
|
||||
/* "sha1 hexfingerprinthere\0", each hex digit is "AB:" etc */
|
||||
@ -352,12 +342,12 @@ static char * sign_key_sha1_fingerprint(sign_key *key, int type) {
|
||||
|
||||
/* This will return a freshly malloced string, containing a fingerprint
|
||||
* in either sha1 or md5 */
|
||||
char * sign_key_fingerprint(sign_key *key, int type) {
|
||||
char * sign_key_fingerprint(unsigned char* keyblob, unsigned int keybloblen) {
|
||||
|
||||
#ifdef DROPBEAR_MD5_HMAC
|
||||
return sign_key_md5_fingerprint(key, type);
|
||||
return sign_key_md5_fingerprint(keyblob, keybloblen);
|
||||
#else
|
||||
return sign_key_sha1_fingerprint(key, type);
|
||||
return sign_key_sha1_fingerprint(keyblob, keybloblen);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -427,3 +417,59 @@ int buf_verify(buffer * buf, sign_key *key, const unsigned char *data,
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||
|
||||
#ifdef DROPBEAR_KEY_LINES /* ie we're using authorized_keys or known_hosts */
|
||||
|
||||
/* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE when given a buffer containing
|
||||
* a key, a key, and a type. The buffer is positioned at the start of the
|
||||
* base64 data, and contains no trailing data */
|
||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
const unsigned char* algoname, unsigned int algolen,
|
||||
buffer * line) {
|
||||
|
||||
buffer * decodekey = NULL;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
unsigned int len, filealgolen;
|
||||
unsigned long decodekeylen;
|
||||
unsigned char* filealgo = NULL;
|
||||
|
||||
/* now we have the actual data */
|
||||
len = line->len - line->pos;
|
||||
decodekeylen = len * 2; /* big to be safe */
|
||||
decodekey = buf_new(decodekeylen);
|
||||
|
||||
if (base64_decode(buf_getptr(line, len), len,
|
||||
buf_getwriteptr(decodekey, decodekey->size),
|
||||
&decodekeylen) != CRYPT_OK) {
|
||||
TRACE(("checkpubkey: base64 decode failed"));
|
||||
goto out;
|
||||
}
|
||||
TRACE(("checkpubkey: base64_decode success"));
|
||||
buf_incrlen(decodekey, decodekeylen);
|
||||
|
||||
/* compare the keys */
|
||||
if ( ( decodekeylen != keybloblen )
|
||||
|| memcmp( buf_getptr(decodekey, decodekey->len),
|
||||
keyblob, decodekey->len) != 0) {
|
||||
TRACE(("checkpubkey: compare failed"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ... and also check that the algo specified and the algo in the key
|
||||
* itself match */
|
||||
filealgolen = buf_getint(decodekey);
|
||||
filealgo = buf_getptr(decodekey, filealgolen);
|
||||
if (filealgolen != algolen || memcmp(filealgo, algoname, algolen) != 0) {
|
||||
TRACE(("checkpubkey: algo match failed"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* All checks passed */
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
|
||||
out:
|
||||
buf_free(decodekey);
|
||||
decodekey = NULL;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -54,7 +54,10 @@ void buf_put_sign(buffer* buf, sign_key *key, int type,
|
||||
#ifdef DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_verify(buffer * buf, sign_key *key, const unsigned char *data,
|
||||
unsigned int len);
|
||||
char * sign_key_fingerprint(sign_key *key, int type);
|
||||
char * sign_key_fingerprint(unsigned char* keyblob, unsigned int keybloblen);
|
||||
#endif
|
||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
const unsigned char* algoname, unsigned int algolen,
|
||||
buffer * line);
|
||||
|
||||
#endif /* _SIGNKEY_H_ */
|
||||
|
@ -50,7 +50,7 @@ void svr_auth_password() {
|
||||
passwdcrypt = ses.authstate.pw->pw_passwd;
|
||||
#ifdef HAVE_SHADOW_H
|
||||
/* get the shadow password if possible */
|
||||
spasswd = getspnam(ses.authstate.pw->pw_name);
|
||||
spasswd = getspnam(ses.authstate.printableuser);
|
||||
if (spasswd != NULL && spasswd->sp_pwdp != NULL) {
|
||||
passwdcrypt = spasswd->sp_pwdp;
|
||||
}
|
||||
@ -87,6 +87,8 @@ void svr_auth_password() {
|
||||
|
||||
/* the first bytes of passwdcrypt are the salt */
|
||||
testcrypt = crypt((char*)password, passwdcrypt);
|
||||
m_burn(password, passwordlen);
|
||||
m_free(password);
|
||||
|
||||
if (strcmp(testcrypt, passwdcrypt) == 0) {
|
||||
/* successful authentication */
|
||||
@ -101,8 +103,6 @@ void svr_auth_password() {
|
||||
send_msg_userauth_failure(0, 1);
|
||||
}
|
||||
|
||||
m_burn(password, passwordlen);
|
||||
m_free(password);
|
||||
}
|
||||
|
||||
#endif /* DROPBEAR_PASSWORD_AUTH */
|
||||
|
@ -38,7 +38,7 @@
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
|
||||
#define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */
|
||||
#define MAX_AUTHKEYS_LINE 1000 /* max length of a line in authkeys */
|
||||
#define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */
|
||||
|
||||
static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
unsigned char* keyblob, unsigned int keybloblen);
|
||||
@ -46,7 +46,6 @@ static int checkpubkeyperms();
|
||||
static void send_msg_userauth_pk_ok(unsigned char* algo, unsigned int algolen,
|
||||
unsigned char* keyblob, unsigned int keybloblen);
|
||||
static int checkfileperm(char * filename);
|
||||
static int getauthline(buffer * line, FILE * authfile);
|
||||
|
||||
/* process a pubkey auth request, sending success or failure message as
|
||||
* appropriate */
|
||||
@ -102,7 +101,7 @@ void svr_auth_pubkey() {
|
||||
buf_setpos(signbuf, 0);
|
||||
|
||||
/* ... and finally verify the signature */
|
||||
fp = sign_key_fingerprint(key, type);
|
||||
fp = sign_key_fingerprint(keyblob, keybloblen);
|
||||
if (buf_verify(ses.payload, key, buf_getptr(signbuf, signbuf->len),
|
||||
signbuf->len) == DROPBEAR_SUCCESS) {
|
||||
dropbear_log(LOG_NOTICE,
|
||||
@ -160,10 +159,6 @@ static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
char * filename = NULL;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
buffer * line = NULL;
|
||||
buffer * decodekey = NULL;
|
||||
unsigned long decodekeylen;
|
||||
unsigned char* filealgo = NULL;
|
||||
unsigned int filealgolen;
|
||||
unsigned int len, pos;
|
||||
|
||||
TRACE(("enter checkpubkey"));
|
||||
@ -202,14 +197,8 @@ static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
|
||||
/* iterate through the lines */
|
||||
do {
|
||||
/* free reused vars */
|
||||
if (decodekey) {
|
||||
buf_free(decodekey);
|
||||
decodekey = NULL;
|
||||
}
|
||||
m_free(filealgo);
|
||||
|
||||
if (getauthline(line, authfile) == DROPBEAR_FAILURE) {
|
||||
if (buf_getline(line, authfile) == DROPBEAR_FAILURE) {
|
||||
/* EOF reached */
|
||||
TRACE(("checkpubkey: authorized_keys EOF reached"));
|
||||
break;
|
||||
@ -243,38 +232,12 @@ static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
|
||||
TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len));
|
||||
|
||||
/* now we have the actual data */
|
||||
decodekeylen = (line->len - line->pos) * 2;
|
||||
decodekey = buf_new(decodekeylen);
|
||||
if (base64_decode(buf_getptr(line, line->len - line->pos),
|
||||
line->len - line->pos,
|
||||
buf_getwriteptr(decodekey, decodekey->size),
|
||||
&decodekeylen) != CRYPT_OK) {
|
||||
TRACE(("checkpubkey: base64 decode failed"));
|
||||
continue;
|
||||
}
|
||||
TRACE(("checkpubkey: base64_decode success"));
|
||||
buf_incrlen(decodekey, decodekeylen);
|
||||
|
||||
/* compare the keys */
|
||||
if (decodekeylen != keybloblen || memcmp(
|
||||
buf_getptr(decodekey, decodekey->len),
|
||||
keyblob, decodekey->len) != 0) {
|
||||
TRACE(("checkpubkey: compare failed"));
|
||||
continue;
|
||||
ret = cmp_base64_key(keyblob, keybloblen, algo, algolen, line);
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* and also check that the algo specified and the algo in the key
|
||||
* itself match */
|
||||
filealgo = buf_getstring(decodekey, &filealgolen);
|
||||
if (filealgolen != algolen || memcmp(filealgo, algo, algolen) != 0) {
|
||||
TRACE(("checkpubkey: algo match failed"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* now we know this key is good */
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
break;
|
||||
/* We continue to the next line otherwise */
|
||||
|
||||
} while (1);
|
||||
|
||||
@ -285,53 +248,11 @@ out:
|
||||
if (line) {
|
||||
buf_free(line);
|
||||
}
|
||||
if (decodekey) {
|
||||
buf_free(decodekey);
|
||||
}
|
||||
m_free(filename);
|
||||
m_free(filealgo);
|
||||
TRACE(("leave checkpubkey: ret=%d", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get a line from the file into buffer in the style expected for an
|
||||
* authkeys file.
|
||||
* Will return DROPBEAR_SUCCESS if data is read, or DROPBEAR_FAILURE on EOF.*/
|
||||
static int getauthline(buffer * line, FILE * authfile) {
|
||||
|
||||
int c = EOF;
|
||||
|
||||
TRACE(("enter getauthline"));
|
||||
|
||||
buf_setpos(line, 0);
|
||||
buf_setlen(line, 0);
|
||||
|
||||
while (line->pos < line->size) {
|
||||
c = fgetc(authfile); /*getc() is weird with some uClibc systems*/
|
||||
if (c == EOF || c == '\n' || c == '\r') {
|
||||
goto out;
|
||||
}
|
||||
buf_putbyte(line, (unsigned char)c);
|
||||
}
|
||||
|
||||
TRACE(("leave getauthline: line too long"));
|
||||
return DROPBEAR_FAILURE;
|
||||
|
||||
out:
|
||||
|
||||
buf_setpos(line, 0);
|
||||
|
||||
/* if we didn't read anything before EOF or error, exit */
|
||||
if (c == EOF && line->pos == 0) {
|
||||
TRACE(("leave getauthline: failure"));
|
||||
return DROPBEAR_FAILURE;
|
||||
} else {
|
||||
TRACE(("leave getauthline: success"));
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
TRACE(("leave getauthline"));
|
||||
}
|
||||
|
||||
/* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok,
|
||||
* DROPBEAR_FAILURE otherwise.
|
||||
|
Loading…
Reference in New Issue
Block a user