libssh2_session_supported_algs: added

This commit is contained in:
Jernej Kovacic 2011-10-25 23:50:44 +02:00 committed by Daniel Stenberg
parent c0974e5ca3
commit f4e5ca2f14
4 changed files with 174 additions and 1 deletions

View File

@ -112,6 +112,7 @@ dist_man_MANS = \
libssh2_session_set_blocking.3 \
libssh2_session_set_timeout.3 \
libssh2_session_startup.3 \
libssh2_session_supported_algs.3 \
libssh2_sftp_close.3 \
libssh2_sftp_close_handle.3 \
libssh2_sftp_closedir.3 \

View File

@ -0,0 +1,48 @@
.TH libssh2_session_supported_algs 3 "23 Oct 2011" "libssh2 1.3.1" "libssh2 manual"
.SH NAME
libssh2_session_supported_algs - get list of supported algorithms
.SH SYNOPSIS
.nf
#include <libssh2.h>
int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
int method_type,
const char*** algs);
.SH DESCRIPTION
\fIsession\fP - An instance of initialized LIBSSH2_SESSION (the function will
use its pointer to the memory allocation function). \fImethod_type\fP - Method
type. See .BR \fIlibssh2_session_method_pref(3)\fP. \fIalgs\fP - Address of a
pointer that will point to an array af returned algorithms
Get a list of supported algorithms for the given \fImethod_type\fP. The
method_type parameter is equivalent to method_type in
\fIlibssh2_session_method_pref(3)\fP. If successful, the function will
allocate the appropriate amount of memory. When not needed anymore, it must be
deallocated by calling \fIlibssh2_free(3)\fP. When this function is
unsuccessful, this must not be done.
In order to get a list of all supported compression algorithms,
libssh2_session_flag(session, LIBSSH2_FLAG_COMPRESS, 1) must be called before
calling this function, otherwise only "none" will be returned.
If successful, the function will allocate and fill the array with supported
algorithms (the same names as defined in RFC 4253). The array is not NULL
terminated.
.SH RETURN VALUE
On success, a number of returned algorithms (i.e a positive number will be
returned). In case of a failure, an error code (a negative number, see below)
is returned. 0 should never be returned.
.SH ERRORS
\fILIBSSH2_ERROR_BAD_USE\fP - Invalid address of algs.
\fILIBSSH2_ERROR_METHOD_NOT_SUPPORTED\fP - Unknown method type.
\fILIBSSH2_ERROR_INVAL\fP - Internal error (normally should not occur).
\fILIBSSH2_ERROR_ALLOC\fP - Allocation of memory failed.
.SH AVAILABILITY
Added in 1.3.1
.SH SEE ALSO
.BR libssh2_session_methods(3),
.BR libssh2_session_method_pref(3)
.BR libssh2_free(3)

View File

@ -441,6 +441,20 @@ LIBSSH2_API void libssh2_exit(void);
*/
LIBSSH2_API void libssh2_free(LIBSSH2_SESSION *session, void *ptr);
/*
* libssh2_session_supported_algs()
*
* Fills algs with a list of supported acryptographic algorithms. Returns a
* non-negative number (number of supported algorithms) on success or a
* negative number (an eror code) on failure.
*
* NOTE: on success, algs must be deallocated (by calling libssh2_free) when
* not needed anymore
*/
LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
int method_type,
const char*** algs);
/* Session API */
LIBSSH2_API LIBSSH2_SESSION *
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
@ -1027,7 +1041,7 @@ libssh2_knownhost_get(LIBSSH2_KNOWNHOSTS *hosts,
struct libssh2_agent_publickey {
unsigned int magic; /* magic stored by the library */
void *node; /* handle to the internal representation of key */
void *node; /* handle to the internal representation of key */
unsigned char *blob; /* public key blob */
size_t blob_len; /* length of the public key blob */
char *comment; /* comment in printable format */

110
src/kex.c
View File

@ -1896,3 +1896,113 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
return 0;
}
/*
* libssh2_session_supported_algs()
* returns a number of returned algorithms (a positive number) on success,
* a negative number on failure
*/
LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
int method_type,
const char*** algs)
{
unsigned int i;
unsigned int j;
unsigned int ialg;
const LIBSSH2_COMMON_METHOD **mlist;
/* to prevent coredumps due to dereferencing of NULL */
if (NULL == algs)
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"algs must not be NULL");
switch (method_type) {
case LIBSSH2_METHOD_KEX:
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
break;
case LIBSSH2_METHOD_HOSTKEY:
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods();
break;
case LIBSSH2_METHOD_CRYPT_CS:
case LIBSSH2_METHOD_CRYPT_SC:
mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_MAC_CS:
case LIBSSH2_METHOD_MAC_SC:
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_mac_methods();
break;
case LIBSSH2_METHOD_COMP_CS:
case LIBSSH2_METHOD_COMP_SC:
mlist = (const LIBSSH2_COMMON_METHOD **) _libssh2_comp_methods(session);
break;
default:
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
"Unknown method type");
} /* switch */
/* weird situation */
if (NULL==mlist)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
/*
mlist is looped through twice. The first time to find the number od
supported algorithms (needed to allocate the proper size of array) and
the second time to actually copy the pointers. Typically this function
will not be called often (typically at the beginning of a session) and
the number of algorithms (i.e. niumber of iterations in one loop) will
not be high (typically it will not exceed 20) for quite a long time.
So double looping really shouldn't be an issue and it is definitely a
better solution than reallocation several times.
*/
/* count the number of supported algorithms */
for ( i=0, ialg=0; NULL!=mlist[i]; i++) {
/* do not count fields with NULL name */
if (mlist[i]->name)
ialg++;
}
/* weird situation, no algorithm found */
if (0==ialg)
return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
"No algorithm found");
/* allocate buffer */
*algs = (const char**) LIBSSH2_ALLOC(session, ialg*sizeof(const char*));
if ( NULL==*algs ) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Memory allocation failed");
}
/* Past this point *algs must be deallocated in case of an error!! */
/* copy non-NULL pointers only */
for ( i=0, j=0; NULL!=mlist[i] && j<ialg; i++ ) {
if ( NULL==mlist[i]->name ){
/* maybe a weird situation but if it occurs, do not include NULL
pointers */
continue;
}
/* note that [] has higher priority than * (dereferencing) */
(*algs)[j++] = mlist[i]->name;
}
/* correct number of pointers copied? (test the code above) */
if ( j!=ialg ) {
/* deallocate buffer */
LIBSSH2_FREE(session, *algs);
*algs = NULL;
return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
"Internal error");
}
return ialg;
}