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:
Daniel Stenberg 2009-05-29 00:08:00 +02:00
parent 8b1ec197b2
commit bc28d0146d
2 changed files with 148 additions and 77 deletions

View File

@ -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
* *

View File

@ -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);
} }