introducing libssh2_knownhost_read() that makes libssh2 read a single given
line const'ified a few args to libssh2_knownhost_add() as well
This commit is contained in:
parent
8b1ec197b2
commit
bc28d0146d
@ -717,8 +717,10 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session);
|
|||||||
#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18)
|
#define LIBSSH2_KNOWNHOST_KEY_SSHDSS (3<<18)
|
||||||
|
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts, char *host, char *salt,
|
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
char *key, size_t keylen, int typemask);
|
const char *host,
|
||||||
|
const char *salt,
|
||||||
|
const char *key, size_t keylen, int typemask);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_knownhost_check
|
* libssh2_knownhost_check
|
||||||
@ -777,6 +779,18 @@ libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
LIBSSH2_API void
|
LIBSSH2_API void
|
||||||
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
|
libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_read()
|
||||||
|
*
|
||||||
|
* Pass in a line of a file of 'type'. It makes libssh2 read this line.
|
||||||
|
*
|
||||||
|
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_read(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *line, size_t len, int type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_knownhost_readfile
|
* libssh2_knownhost_readfile
|
||||||
*
|
*
|
||||||
|
207
src/knownhost.c
207
src/knownhost.c
@ -97,8 +97,8 @@ libssh2_knownhost_init(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
char *host, char *salt,
|
const char *host, const char *salt,
|
||||||
char *key, size_t keylen,
|
const char *key, size_t keylen,
|
||||||
int typemask)
|
int typemask)
|
||||||
{
|
{
|
||||||
struct known_host *entry =
|
struct known_host *entry =
|
||||||
@ -151,6 +151,7 @@ libssh2_knownhost_add(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
if(!entry)
|
if(!entry)
|
||||||
goto error;
|
goto error;
|
||||||
memcpy(entry->key, key, keylen+1);
|
memcpy(entry->key, key, keylen+1);
|
||||||
|
entry->key[keylen]=0; /* force a terminating zero trailer */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* key is raw, we base64 encode it and store it as such */
|
/* key is raw, we base64 encode it and store it as such */
|
||||||
@ -359,52 +360,76 @@ libssh2_knownhost_free(LIBSSH2_KNOWNHOSTS *hosts)
|
|||||||
*
|
*
|
||||||
* Parse a single known_host line pre-split into host and key.
|
* Parse a single known_host line pre-split into host and key.
|
||||||
*
|
*
|
||||||
* Note: this function assumes that the 'host' pointer points into a temporary
|
|
||||||
* buffer as it will write to it.
|
|
||||||
*/
|
*/
|
||||||
static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
char *host, size_t hostlen,
|
const char *host, size_t hostlen,
|
||||||
char *key, size_t keylen)
|
const char *key, size_t keylen)
|
||||||
{
|
{
|
||||||
char *p;
|
const char *p;
|
||||||
char *salt = NULL;
|
const char *salt = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN;
|
int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN;
|
||||||
char *sep = NULL;
|
const char *sep = NULL;
|
||||||
|
size_t seplen = 0;
|
||||||
|
char saltbuf[32];
|
||||||
|
char hostbuf[256];
|
||||||
|
|
||||||
/* Figure out host format */
|
/* Figure out host format */
|
||||||
if(strncmp(host, "|1|", 3)) {
|
if((hostlen >2) && memcmp(host, "|1|", 3)) {
|
||||||
/* old style plain text: [name][,][ip-address]
|
/* old style plain text: [name][,][ip-address]
|
||||||
|
|
||||||
for the sake of simplicity, we add them as two hosts with the same
|
for the sake of simplicity, we add them as two hosts with the same
|
||||||
key
|
key
|
||||||
*/
|
*/
|
||||||
sep = strchr(host, ',');
|
size_t scan = hostlen;
|
||||||
|
|
||||||
|
while(scan && (*host != ',')) {
|
||||||
|
host++;
|
||||||
|
scan--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scan) {
|
||||||
|
sep = host+1;
|
||||||
|
seplen = scan-1;
|
||||||
|
hostlen -= scan; /* deduct what's left to scan from the first
|
||||||
|
host name */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* |1|[salt]|[hash] */
|
/* |1|[salt]|[hash] */
|
||||||
type = LIBSSH2_KNOWNHOST_TYPE_SHA1;
|
type = LIBSSH2_KNOWNHOST_TYPE_SHA1;
|
||||||
|
|
||||||
salt = &host[3]; /* skip the magic marker */
|
salt = &host[3]; /* skip the magic marker */
|
||||||
|
hostlen -= 3; /* deduct the marker */
|
||||||
|
|
||||||
/* this is where the salt starts, find the end of it */
|
/* this is where the salt starts, find the end of it */
|
||||||
for(p = salt; *p && (*p != '|'); p++)
|
for(p = salt; *p && (*p != '|'); p++)
|
||||||
;
|
;
|
||||||
|
|
||||||
if(*p=='|') {
|
if(*p=='|') {
|
||||||
char *hash = NULL;
|
const char *hash = NULL;
|
||||||
*p=0; /* terminate the salt string */
|
size_t saltlen = p - salt;
|
||||||
hash = p+1; /* the hash is after the separator */
|
if(saltlen >= (sizeof(saltbuf)-1))
|
||||||
|
return -1; /* weird salt length */
|
||||||
|
|
||||||
|
memcpy(saltbuf, salt, saltlen);
|
||||||
|
saltbuf[saltlen] = 0; /* zero terminate */
|
||||||
|
salt = saltbuf; /* point to the stack based buffer */
|
||||||
|
|
||||||
|
hash = p+1; /* the host hash is after the separator */
|
||||||
|
|
||||||
/* now make the host point to the hash */
|
/* now make the host point to the hash */
|
||||||
hostlen = strlen(hash);
|
|
||||||
host = hash;
|
host = hash;
|
||||||
|
hostlen -= saltlen+1; /* deduct the salt and separator */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(keylen < 20)
|
/* make some checks that the lenghts seem sensible */
|
||||||
|
if((keylen < 20) ||
|
||||||
|
(seplen >= sizeof(hostbuf)-1) ||
|
||||||
|
(hostlen >= sizeof(hostbuf)-1))
|
||||||
return -1; /* TODO: better return code */
|
return -1; /* TODO: better return code */
|
||||||
|
|
||||||
switch(key[0]) {
|
switch(key[0]) {
|
||||||
@ -425,7 +450,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
else if(!strncmp(key, "ssh-rsa", 7))
|
else if(!strncmp(key, "ssh-rsa", 7))
|
||||||
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||||
else
|
else
|
||||||
return -1; /* unknown */
|
return -1; /* unknown key type */
|
||||||
|
|
||||||
key += 7;
|
key += 7;
|
||||||
keylen -= 7;
|
keylen -= 7;
|
||||||
@ -442,30 +467,33 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(sep) {
|
if(sep) {
|
||||||
/* this is the second host after the comma, add this first */
|
/* The second host after the comma, add this first. Copy it to the
|
||||||
char *ipaddr;
|
temp buffer and zero terminate */
|
||||||
*sep++ = 0; /* zero terminate the first host name here */
|
memcpy(hostbuf, sep, seplen);
|
||||||
ipaddr = sep;
|
hostbuf[seplen]=0;
|
||||||
rc = libssh2_knownhost_add(hosts, ipaddr, salt, key, keylen,
|
|
||||||
|
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
|
||||||
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64);
|
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64);
|
||||||
if(rc)
|
if(rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = libssh2_knownhost_add(hosts, host, salt, key, keylen,
|
memcpy(hostbuf, host, hostlen);
|
||||||
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64);
|
hostbuf[hostlen]=0;
|
||||||
|
|
||||||
|
rc = libssh2_knownhost_add(hosts, hostbuf, salt, key, keylen,
|
||||||
|
type | LIBSSH2_KNOWNHOST_KEYENC_BASE64);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libssh2_knownhost_readfile
|
* libssh2_knownhost_read()
|
||||||
*
|
*
|
||||||
* Read hosts+key pairs from a given file.
|
* Pass in a line of a file of 'type'.
|
||||||
*
|
*
|
||||||
* Returns a negative value for error or number of successfully added hosts.
|
* LIBSSH2_KNOWNHOST_FILE_OPENSSH is the only supported type.
|
||||||
*
|
*
|
||||||
* Line format:
|
* OpenSSH line format:
|
||||||
*
|
*
|
||||||
* <host> <key>
|
* <host> <key>
|
||||||
*
|
*
|
||||||
@ -486,8 +514,80 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
* 'ssh-rsa' [base64-encoded-key]
|
* 'ssh-rsa' [base64-encoded-key]
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
LIBSSH2_API int
|
||||||
|
libssh2_knownhost_read(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
|
const char *line, size_t len, int type)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
const char *hostp;
|
||||||
|
const char *keyp;
|
||||||
|
size_t hostlen;
|
||||||
|
size_t keylen;
|
||||||
|
|
||||||
#define LIBSSH2_KNOWNHOST_FILE_OPENSSH 1
|
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||||
|
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
cp = line;
|
||||||
|
|
||||||
|
/* skip leading whitespaces */
|
||||||
|
while(len && ((*cp==' ') || (*cp == '\t'))) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!len || !*cp || (*cp == '#') || (*cp == '\n'))
|
||||||
|
/* comment or empty line */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* the host part starts here */
|
||||||
|
hostp = cp;
|
||||||
|
|
||||||
|
/* move over the host to the separator */
|
||||||
|
while(len && *cp && (*cp!=' ') && (*cp != '\t')) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostlen = cp - hostp;
|
||||||
|
|
||||||
|
/* the key starts after the whitespaces */
|
||||||
|
while(len && *cp && ((*cp==' ') || (*cp == '\t'))) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!*cp || !len)
|
||||||
|
/* illegal line */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
keyp = cp; /* the key starts here */
|
||||||
|
keylen = len;
|
||||||
|
|
||||||
|
/* check if the line (key) ends with a newline and if so kill it */
|
||||||
|
while(len && *cp && (*cp != '\n')) {
|
||||||
|
cp++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero terminate where the newline is */
|
||||||
|
if(*cp == '\n')
|
||||||
|
keylen--; /* don't include this in the count */
|
||||||
|
|
||||||
|
/* deal with this one host+key line */
|
||||||
|
if(hostline(hosts, hostp, hostlen, keyp, keylen))
|
||||||
|
return -1; /* failed */
|
||||||
|
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libssh2_knownhost_readfile
|
||||||
|
*
|
||||||
|
* Read hosts+key pairs from a given file.
|
||||||
|
*
|
||||||
|
* Returns a negative value for error or number of successfully added hosts.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
LIBSSH2_API int
|
LIBSSH2_API int
|
||||||
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||||
@ -502,53 +602,10 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
|||||||
|
|
||||||
file = fopen(filename, "r");
|
file = fopen(filename, "r");
|
||||||
if(file) {
|
if(file) {
|
||||||
char *cp;
|
|
||||||
char *hostp;
|
|
||||||
char *key;
|
|
||||||
size_t hostlen;
|
|
||||||
|
|
||||||
while(fgets(buf, sizeof(buf), file)) {
|
while(fgets(buf, sizeof(buf), file)) {
|
||||||
cp = buf;
|
if(libssh2_knownhost_read(hosts, buf, strlen(buf), type))
|
||||||
|
break;
|
||||||
/* skip leading whitespaces */
|
num++;
|
||||||
while((*cp==' ') || (*cp == '\t'))
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
if(!*cp || (*cp == '#') || (*cp == '\n'))
|
|
||||||
/* comment or empty line */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* the host part starts here */
|
|
||||||
hostp = cp;
|
|
||||||
|
|
||||||
/* move over the host to the separator */
|
|
||||||
while(*cp && (*cp!=' ') && (*cp != '\t'))
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
hostlen = cp - hostp;
|
|
||||||
|
|
||||||
*cp++ = 0; /* terminate the host string here */
|
|
||||||
|
|
||||||
/* the key starts after the whitespaces */
|
|
||||||
while(*cp && ((*cp==' ') || (*cp == '\t')))
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
if(!*cp)
|
|
||||||
/* illegal line */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
key = cp; /* the key starts here */
|
|
||||||
|
|
||||||
while(*cp && (*cp != '\n'))
|
|
||||||
cp++;
|
|
||||||
|
|
||||||
/* zero terminate where the newline is */
|
|
||||||
if(*cp == '\n')
|
|
||||||
*cp = 0;
|
|
||||||
|
|
||||||
/* deal with this one host+key line */
|
|
||||||
if(!hostline(hosts, hostp, hostlen, key, strlen(key)))
|
|
||||||
num++;
|
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user