introducing libssh2_knownhost_writeline() and some cleanups to use more
defined error codes instead of the simplified -1 previously used a little too much here
Этот коммит содержится в:
родитель
82bdd12a8b
Коммит
1afbbf4507
@ -350,6 +350,7 @@ typedef struct _LIBSSH2_POLLFD {
|
||||
#define LIBSSH2_ERROR_INVALID_POLL_TYPE -35
|
||||
#define LIBSSH2_ERROR_PUBLICKEY_PROTOCOL -36
|
||||
#define LIBSSH2_ERROR_EAGAIN -37
|
||||
#define LIBSSH2_ERROR_BUFFER_TOO_SMALL -38
|
||||
|
||||
/* Session API */
|
||||
LIBSSH2_API LIBSSH2_SESSION *
|
||||
@ -808,6 +809,25 @@ LIBSSH2_API int
|
||||
libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *filename, int type);
|
||||
|
||||
/*
|
||||
* libssh2_knownhost_writeline()
|
||||
*
|
||||
* Ask libssh2 to convert a known host to an output line for storage.
|
||||
*
|
||||
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||
* output buffer is too small to hold the desired output.
|
||||
*
|
||||
* This implementation currently only knows one 'type' (openssh), all others
|
||||
* are reserved for future use.
|
||||
*
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct libssh2_knownhost *known,
|
||||
char *buffer, size_t buflen,
|
||||
size_t *outlen, /* the amount of written data */
|
||||
int type);
|
||||
|
||||
/*
|
||||
* libssh2_knownhost_writefile
|
||||
*
|
||||
|
182
src/knownhost.c
182
src/knownhost.c
@ -319,7 +319,7 @@ libssh2_knownhost_del(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct known_host *node;
|
||||
if(!entry || (entry->magic != KNOWNHOST_MAGIC))
|
||||
/* check that this was retrieved the right way or get out */
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
|
||||
/* get the internal node pointer */
|
||||
node = entry->node;
|
||||
@ -410,7 +410,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *hash = NULL;
|
||||
size_t saltlen = p - salt;
|
||||
if(saltlen >= (sizeof(saltbuf)-1))
|
||||
return -1; /* weird salt length */
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* weird length */
|
||||
|
||||
memcpy(saltbuf, salt, saltlen);
|
||||
saltbuf[saltlen] = 0; /* zero terminate */
|
||||
@ -430,7 +430,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
if((keylen < 20) ||
|
||||
(seplen >= sizeof(hostbuf)-1) ||
|
||||
(hostlen >= sizeof(hostbuf)-1))
|
||||
return -1; /* TODO: better return code */
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||
|
||||
switch(key[0]) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
@ -450,7 +450,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
else if(!strncmp(key, "ssh-rsa", 7))
|
||||
type |= LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||
else
|
||||
return -1; /* unknown key type */
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED; /* unknown key type */
|
||||
|
||||
key += 7;
|
||||
keylen -= 7;
|
||||
@ -463,7 +463,7 @@ static int hostline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
break;
|
||||
|
||||
default: /* unknown key format */
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if(sep) {
|
||||
@ -523,6 +523,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
const char *keyp;
|
||||
size_t hostlen;
|
||||
size_t keylen;
|
||||
int rc;
|
||||
|
||||
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||
@ -537,7 +538,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
|
||||
if(!len || !*cp || (*cp == '#') || (*cp == '\n'))
|
||||
/* comment or empty line */
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_NONE;
|
||||
|
||||
/* the host part starts here */
|
||||
hostp = cp;
|
||||
@ -558,7 +559,7 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
|
||||
if(!*cp || !len)
|
||||
/* illegal line */
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||
|
||||
keyp = cp; /* the key starts here */
|
||||
keylen = len;
|
||||
@ -574,10 +575,11 @@ libssh2_knownhost_readline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
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 */
|
||||
rc = hostline(hosts, hostp, hostlen, keyp, keylen);
|
||||
if(rc)
|
||||
return rc; /* failed */
|
||||
|
||||
return 0; /* success */
|
||||
return LIBSSH2_ERROR_NONE; /* success */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -610,10 +612,118 @@ libssh2_knownhost_readfile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
fclose(file);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
return LIBSSH2_ERROR_FILE;
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* knownhost_writeline()
|
||||
*
|
||||
* Ask libssh2 to convert a known host to an output line for storage.
|
||||
*
|
||||
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||
* output buffer is too small to hold the desired output. The 'outlen' field
|
||||
* will then contain the size libssh2 wanted to store, which then is the
|
||||
* smallest sufficient buffer it would require.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct known_host *node,
|
||||
char *buf, size_t buflen,
|
||||
size_t *outlen, int type)
|
||||
{
|
||||
int rc = LIBSSH2_ERROR_NONE;
|
||||
int tindex;
|
||||
const char *keytypes[4]={
|
||||
"", /* not used */
|
||||
"", /* this type has no name in the file */
|
||||
" ssh-rsa",
|
||||
" ssh-dss"
|
||||
};
|
||||
const char *keytype;
|
||||
size_t nlen;
|
||||
|
||||
/* we only support this single file type for now, bail out on all other
|
||||
attempts */
|
||||
if(type != LIBSSH2_KNOWNHOST_FILE_OPENSSH)
|
||||
return LIBSSH2_ERROR_METHOD_NOT_SUPPORTED;
|
||||
|
||||
tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >>
|
||||
LIBSSH2_KNOWNHOST_KEY_SHIFT;
|
||||
|
||||
/* set the string used in the file */
|
||||
keytype = keytypes[tindex];
|
||||
|
||||
if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
|
||||
LIBSSH2_KNOWNHOST_TYPE_SHA1) {
|
||||
char *namealloc;
|
||||
char *saltalloc;
|
||||
nlen = _libssh2_base64_encode(hosts->session, node->name,
|
||||
node->name_len, &namealloc);
|
||||
if(!nlen)
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
|
||||
nlen = _libssh2_base64_encode(hosts->session,
|
||||
node->salt, node->salt_len,
|
||||
&saltalloc);
|
||||
if(!nlen) {
|
||||
free(namealloc);
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
nlen = strlen(saltalloc) + strlen(namealloc) + strlen(keytype) +
|
||||
strlen(node->key) + 7; /* |1| + | + ' ' + \n + \0 = 7 */
|
||||
|
||||
if(nlen <= buflen)
|
||||
sprintf(buf, "|1|%s|%s%s %s\n", saltalloc, namealloc, keytype,
|
||||
node->key);
|
||||
else
|
||||
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
|
||||
|
||||
free(namealloc);
|
||||
free(saltalloc);
|
||||
}
|
||||
else {
|
||||
nlen = strlen(node->name) + strlen(keytype) + strlen(node->key) + 3;
|
||||
/* ' ' + '\n' + \0 = 3 */
|
||||
if(nlen < buflen)
|
||||
/* these types have the plain name */
|
||||
sprintf(buf, "%s%s %s\n", node->name, keytype, node->key);
|
||||
else
|
||||
rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*outlen = nlen;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_knownhost_writeline()
|
||||
*
|
||||
* Ask libssh2 to convert a known host to an output line for storage.
|
||||
*
|
||||
* Note that this function returns LIBSSH2_ERROR_BUFFER_TOO_SMALL if the given
|
||||
* output buffer is too small to hold the desired output.
|
||||
*/
|
||||
LIBSSH2_API int
|
||||
libssh2_knownhost_writeline(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct libssh2_knownhost *known,
|
||||
char *buffer, size_t buflen,
|
||||
size_t *outlen, /* the amount of written data */
|
||||
int type)
|
||||
{
|
||||
struct known_host *node;
|
||||
|
||||
if(known->magic != KNOWNHOST_MAGIC)
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
|
||||
node = known->node;
|
||||
|
||||
return knownhost_writeline(hosts, node, buffer, buflen, outlen, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* libssh2_knownhost_writefile()
|
||||
*
|
||||
@ -626,6 +736,7 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
struct known_host *node;
|
||||
FILE *file;
|
||||
int rc = LIBSSH2_ERROR_NONE;
|
||||
char buffer[2048];
|
||||
|
||||
/* we only support this single file type for now, bail out on all other
|
||||
attempts */
|
||||
@ -639,48 +750,19 @@ libssh2_knownhost_writefile(LIBSSH2_KNOWNHOSTS *hosts,
|
||||
for(node = _libssh2_list_first(&hosts->head);
|
||||
node;
|
||||
node= _libssh2_list_next(&node->node) ) {
|
||||
int tindex = (node->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) >>
|
||||
LIBSSH2_KNOWNHOST_KEY_SHIFT;
|
||||
size_t wrote;
|
||||
size_t nwrote;
|
||||
rc = knownhost_writeline(hosts, node, buffer, sizeof(buffer), &wrote,
|
||||
type);
|
||||
if(rc)
|
||||
break;
|
||||
|
||||
const char *types[4]={
|
||||
"", /* not used */
|
||||
"", /* this type has no name in the file */
|
||||
" ssh-rsa",
|
||||
" ssh-dss"
|
||||
};
|
||||
|
||||
/* set the string used in the file */
|
||||
const char *type = types[tindex];
|
||||
|
||||
if((node->typemask & LIBSSH2_KNOWNHOST_TYPE_MASK) ==
|
||||
LIBSSH2_KNOWNHOST_TYPE_SHA1) {
|
||||
char *namealloc;
|
||||
char *saltalloc;
|
||||
size_t nlen = _libssh2_base64_encode(hosts->session,
|
||||
node->name, node->name_len,
|
||||
&namealloc);
|
||||
if(!nlen) {
|
||||
rc = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
|
||||
nwrote = fwrite(buffer, 1, wrote, file);
|
||||
if(nwrote != wrote) {
|
||||
/* failed to write the whole thing, bail out */
|
||||
rc = LIBSSH2_ERROR_FILE;
|
||||
break;
|
||||
}
|
||||
nlen = _libssh2_base64_encode(hosts->session,
|
||||
node->salt, node->salt_len,
|
||||
&saltalloc);
|
||||
if(!nlen) {
|
||||
rc = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
|
||||
free(namealloc);
|
||||
break;
|
||||
}
|
||||
fprintf(file, "|1|%s|%s%s %s\n", saltalloc, namealloc, type,
|
||||
node->key);
|
||||
free(namealloc);
|
||||
free(saltalloc);
|
||||
}
|
||||
else {
|
||||
/* these types have the plain name */
|
||||
fprintf(file, "%s%s %s\n", node->name, type, node->key);
|
||||
}
|
||||
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user