From f4e5ca2f1444f9db50886640ac03e7825d5a5f2e Mon Sep 17 00:00:00 2001 From: Jernej Kovacic Date: Tue, 25 Oct 2011 23:50:44 +0200 Subject: [PATCH] libssh2_session_supported_algs: added --- docs/Makefile.am | 1 + docs/libssh2_session_supported_algs.3 | 48 +++++++++++ include/libssh2.h | 16 +++- src/kex.c | 110 ++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 docs/libssh2_session_supported_algs.3 diff --git a/docs/Makefile.am b/docs/Makefile.am index bcd9faa..58dc6c8 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -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 \ diff --git a/docs/libssh2_session_supported_algs.3 b/docs/libssh2_session_supported_algs.3 new file mode 100644 index 0000000..ec54246 --- /dev/null +++ b/docs/libssh2_session_supported_algs.3 @@ -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 + +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) diff --git a/include/libssh2.h b/include/libssh2.h index 8dc547c..65182cf 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -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 */ diff --git a/src/kex.c b/src/kex.c index d26b5f3..6d2e31e 100644 --- a/src/kex.c +++ b/src/kex.c @@ -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] && jname ){ + /* 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; +}