Add libssh2_session_method_pref() and libssh2_session_methods().

Specify methods to be used and retreive what methods were negotiated.
This commit is contained in:
Sara Golemon 2004-12-09 22:10:07 +00:00
parent 165837c085
commit 566bea77ea
5 changed files with 385 additions and 42 deletions

4
README
View File

@ -22,6 +22,10 @@ Version 0.2
Added libssh2_session_callback_set() for setting ignore/debug/disconnect/macerror callbacks
Added libssh2_session_method_pref() to selectively set methods and method preferences.
Added libssh2_session_methods() to determine what methods were negotiated.
Version 0.1
-----------

View File

@ -43,7 +43,7 @@
#include <sys/stat.h>
#define LIBSSH2_VERSION "0.1"
#define LIBSSH2_APINO 200412091107
#define LIBSSH2_APINO 200412091407
/* Part of every banner, user specified or not */
#define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION
@ -140,6 +140,18 @@
#define LIBSSH2_CALLBACK_DISCONNECT 2
#define LIBSSH2_CALLBACK_MACERROR 3
/* libssh2_session_method_pref() constants */
#define LIBSSH2_METHOD_KEX 0
#define LIBSSH2_METHOD_HOSTKEY 1
#define LIBSSH2_METHOD_CRYPT_CS 2
#define LIBSSH2_METHOD_CRYPT_SC 3
#define LIBSSH2_METHOD_MAC_CS 4
#define LIBSSH2_METHOD_MAC_SC 5
#define LIBSSH2_METHOD_COMP_CS 6
#define LIBSSH2_METHOD_COMP_SC 7
#define LIBSSH2_METHOD_LANG_CS 8
#define LIBSSH2_METHOD_LANG_SC 9
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL;
@ -214,6 +226,13 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session);
LIBSSH2_API char *libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type);
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, char *prefs);
LIBSSH2_API void libssh2_session_methods(LIBSSH2_SESSION *session, char **kex, char **hostkey,
char **crypt_cs, char **crypt_sc,
char **mac_cs, char **mac_sc,
char **comp_cs, char **comp_sc,
char **lang_cs, char **lang_sc);
/* Userauth API */
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len);
LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session);

View File

@ -135,9 +135,10 @@ typedef struct _libssh2_endpoint_data {
void *comp_abstract;
/* Method Preferences -- NULL yields "load order" */
LIBSSH2_CRYPT_METHOD **crypt_prefs;
LIBSSH2_MAC_METHOD **mac_prefs;
LIBSSH2_COMP_METHOD **comp_prefs;
char *crypt_prefs;
char *mac_prefs;
char *comp_prefs;
char *lang_prefs;
} libssh2_endpoint_data;
struct _LIBSSH2_SESSION {
@ -154,8 +155,8 @@ struct _LIBSSH2_SESSION {
LIBSSH2_MACERROR_FUNC((*macerror));
/* Method preferences -- NULL yields "load order" */
LIBSSH2_KEX_METHOD **kex_prefs;
LIBSSH2_HOSTKEY_METHOD **hostkey_prefs;
char *kex_prefs;
char *hostkey_prefs;
int exchanging_keys;
int newkeys;

312
src/kex.c
View File

@ -671,16 +671,16 @@ static size_t libssh2_kex_method_list(unsigned char *buf, size_t list_strlen, LI
}
/* }}} */
#define LIBSSH2_METHOD_PREFS \
LIBSSH2_KEX_METHOD **kex_prefs = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods; \
LIBSSH2_HOSTKEY_METHOD **hostkey_prefs = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods(); \
LIBSSH2_CRYPT_METHOD **crypt_cs_prefs = session->local.crypt_prefs ? session->local.crypt_prefs : libssh2_crypt_methods(); \
LIBSSH2_CRYPT_METHOD **crypt_sc_prefs = session->remote.crypt_prefs ? session->remote.crypt_prefs : libssh2_crypt_methods(); \
LIBSSH2_COMP_METHOD **comp_cs_prefs = session->local.comp_prefs ? session->local.comp_prefs : libssh2_comp_methods(); \
LIBSSH2_COMP_METHOD **comp_sc_prefs = session->remote.comp_prefs ? session->remote.comp_prefs : libssh2_comp_methods(); \
LIBSSH2_MAC_METHOD **mac_cs_prefs = session->local.mac_prefs ? session->local.mac_prefs : libssh2_mac_methods(); \
LIBSSH2_MAC_METHOD **mac_sc_prefs = session->remote.mac_prefs ? session->remote.mac_prefs : libssh2_mac_methods();
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) ((prefvar) ? strlen(prefvar) : libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
if (prefvar) { \
libssh2_htonu32((buf), (prefvarlen)); \
buf += 4; \
memcpy((buf), (prefvar), (prefvarlen)); \
buf += (prefvarlen); \
} else { \
buf += libssh2_kex_method_list((buf), (prefvarlen), (LIBSSH2_COMMON_METHOD**)(defaultvar)); \
}
/* {{{ libssh2_kexinit
* Send SSH_MSG_KEXINIT packet
@ -694,18 +694,17 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
size_t mac_cs_len, mac_sc_len;
size_t lang_cs_len, lang_sc_len;
unsigned char *data, *s;
LIBSSH2_METHOD_PREFS
kex_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)kex_prefs);
hostkey_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)hostkey_prefs);
crypt_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
crypt_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
mac_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
mac_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
comp_cs_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
comp_sc_len = libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
lang_cs_len = 0; /* No langs in this version */
lang_sc_len = 0; /* No langs in this version */
kex_len = LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
hostkey_len = LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs, libssh2_hostkey_methods());
crypt_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs, libssh2_crypt_methods());
crypt_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs, libssh2_crypt_methods());
mac_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs, libssh2_mac_methods());
mac_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs, libssh2_mac_methods());
comp_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs, libssh2_comp_methods());
comp_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs, libssh2_comp_methods());
lang_cs_len = LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
lang_sc_len = LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL);
data_len += kex_len + hostkey_len + \
crypt_cs_len + crypt_sc_len + \
@ -726,16 +725,16 @@ static int libssh2_kexinit(LIBSSH2_SESSION *session)
s += 16;
/* Ennumerating through these lists twice is probably (certainly?) inefficient from a CPU standpoint, but it saves multiple malloc/realloc calls */
s += libssh2_kex_method_list(s, kex_len, (LIBSSH2_COMMON_METHOD**)kex_prefs);
s += libssh2_kex_method_list(s, hostkey_len, (LIBSSH2_COMMON_METHOD**)hostkey_prefs);
s += libssh2_kex_method_list(s, crypt_cs_len, (LIBSSH2_COMMON_METHOD**)crypt_cs_prefs);
s += libssh2_kex_method_list(s, crypt_sc_len, (LIBSSH2_COMMON_METHOD**)crypt_sc_prefs);
s += libssh2_kex_method_list(s, mac_cs_len, (LIBSSH2_COMMON_METHOD**)mac_cs_prefs);
s += libssh2_kex_method_list(s, mac_sc_len, (LIBSSH2_COMMON_METHOD**)mac_sc_prefs);
s += libssh2_kex_method_list(s, comp_cs_len, (LIBSSH2_COMMON_METHOD**)comp_cs_prefs);
s += libssh2_kex_method_list(s, comp_sc_len, (LIBSSH2_COMMON_METHOD**)comp_sc_prefs);
s += libssh2_kex_method_list(s, lang_cs_len, NULL);
s += libssh2_kex_method_list(s, lang_sc_len, NULL);
LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs, libssh2_kex_methods);
LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs, libssh2_hostkey_methods());
LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs, libssh2_crypt_methods());
LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs, libssh2_crypt_methods());
LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs, libssh2_mac_methods());
LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs, libssh2_mac_methods());
LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs, libssh2_comp_methods());
LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs, libssh2_comp_methods());
LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs, NULL);
LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs, NULL);
/* No optimistic KEX packet follows */
/* Deal with optimistic packets
@ -803,14 +802,61 @@ static unsigned char *libssh2_kex_agree_instr(unsigned char *haystack, unsigned
}
/* }}} */
/* {{{ libssh2_get_method_by_name
*/
static LIBSSH2_COMMON_METHOD *libssh2_get_method_by_name(char *name, int name_len, LIBSSH2_COMMON_METHOD **methodlist)
{
while (*methodlist) {
if ((strlen((*methodlist)->name) == name_len) &&
(strncmp((*methodlist)->name, name, name_len) == 0)) {
return *methodlist;
}
methodlist++;
}
return NULL;
}
/* }}} */
/* {{{ libssh2_kex_agree_hostkey
* Agree on a Hostkey which works with this kex
*/
static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex_flags, unsigned char *hostkey, unsigned long hostkey_len)
{
LIBSSH2_HOSTKEY_METHOD **hostkeyp = session->hostkey_prefs ? session->hostkey_prefs : libssh2_hostkey_methods();
LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
unsigned char *s;
if (session->hostkey_prefs) {
s = session->hostkey_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
LIBSSH2_HOSTKEY_METHOD *method = (LIBSSH2_HOSTKEY_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)hostkeyp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
(method->encrypt)) {
/* Either this hostkey can do encryption or this kex just doesn't require it */
if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) == 0) ||
(method->sig_verify)) {
/* Either this hostkey can do signing or this kex just doesn't require it */
session->hostkey = method;
return 0;
}
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*hostkeyp)->name) {
s = libssh2_kex_agree_instr(hostkey, hostkey_len, (*hostkeyp)->name, strlen((*hostkeyp)->name));
if (s) {
@ -839,9 +885,37 @@ static int libssh2_kex_agree_hostkey(LIBSSH2_SESSION *session, unsigned long kex
static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char *kex, unsigned long kex_len,
unsigned char *hostkey, unsigned long hostkey_len)
{
LIBSSH2_KEX_METHOD **kexp = session->kex_prefs ? session->kex_prefs : libssh2_kex_methods;
LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
unsigned char *s;
if (session->kex_prefs) {
s = session->kex_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(kex, kex_len, s, method_len)) {
LIBSSH2_KEX_METHOD *method = (LIBSSH2_KEX_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)kexp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
/* We've agreed on a key exchange method,
* Can we agree on a hostkey that works with this kex?
*/
if (libssh2_kex_agree_hostkey(session, method->flags, hostkey, hostkey_len) == 0) {
session->kex = method;
return 0;
}
}
s = p ? p + 1 : NULL;
}
return -1;
}
while (*kexp && (*kexp)->name) {
s = libssh2_kex_agree_instr(kex, kex_len, (*kexp)->name, strlen((*kexp)->name));
if (s) {
@ -864,9 +938,33 @@ static int libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION *session, unsigned char
*/
static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *crypt, unsigned long crypt_len)
{
LIBSSH2_CRYPT_METHOD **cryptp = endpoint->crypt_prefs ? endpoint->crypt_prefs : libssh2_crypt_methods();
LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
unsigned char *s;
if (endpoint->crypt_prefs) {
s = endpoint->crypt_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
LIBSSH2_CRYPT_METHOD *method = (LIBSSH2_CRYPT_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)cryptp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->crypt = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*cryptp)->name) {
s = libssh2_kex_agree_instr(crypt, crypt_len, (*cryptp)->name, strlen((*cryptp)->name));
if (s) {
@ -885,9 +983,33 @@ static int libssh2_kex_agree_crypt(LIBSSH2_SESSION *session, libssh2_endpoint_da
*/
static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *mac, unsigned long mac_len)
{
LIBSSH2_MAC_METHOD **macp = endpoint->mac_prefs ? endpoint->mac_prefs : libssh2_mac_methods();
LIBSSH2_MAC_METHOD **macp = libssh2_mac_methods();
unsigned char *s;
if (endpoint->mac_prefs) {
s = endpoint->mac_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
LIBSSH2_MAC_METHOD *method = (LIBSSH2_MAC_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)macp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->mac = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*macp)->name) {
s = libssh2_kex_agree_instr(mac, mac_len, (*macp)->name, strlen((*macp)->name));
if (s) {
@ -906,9 +1028,33 @@ static int libssh2_kex_agree_mac(LIBSSH2_SESSION *session, libssh2_endpoint_data
*/
static int libssh2_kex_agree_comp(LIBSSH2_SESSION *session, libssh2_endpoint_data *endpoint, unsigned char *comp, unsigned long comp_len)
{
LIBSSH2_COMP_METHOD **compp = endpoint->comp_prefs ? endpoint->comp_prefs : libssh2_comp_methods();
LIBSSH2_COMP_METHOD **compp = libssh2_comp_methods();
unsigned char *s;
if (endpoint->comp_prefs) {
s = endpoint->comp_prefs;
while (s && *s) {
unsigned char *p = strchr(s, ',');
int method_len = (p ? (p - s) : strlen(s));
if (libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
LIBSSH2_COMP_METHOD *method = (LIBSSH2_COMP_METHOD*)libssh2_get_method_by_name(s, method_len, (LIBSSH2_COMMON_METHOD**)compp);
if (!method) {
/* Invalid method -- Should never be reached */
return -1;
}
endpoint->comp = method;
return 0;
}
s = p ? p + 1 : NULL;
}
return -1;
}
while ((*compp)->name) {
s = libssh2_kex_agree_instr(comp, comp_len, (*compp)->name, strlen((*compp)->name));
if (s) {
@ -1054,3 +1200,97 @@ int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange) /* session->f
}
/* }}} */
/* {{{ libssh2_session_method_pref
* Set preferred method
*/
LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method_type, char *prefs)
{
char **prefvar, *s, *newprefs;
int prefs_len = strlen(prefs);
LIBSSH2_COMMON_METHOD **mlist;
switch (method_type) {
case LIBSSH2_METHOD_KEX:
prefvar = &session->kex_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_kex_methods;
break;
case LIBSSH2_METHOD_HOSTKEY:
prefvar = &session->hostkey_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_hostkey_methods();
break;
case LIBSSH2_METHOD_CRYPT_CS:
prefvar = &session->local.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_CRYPT_SC:
prefvar = &session->remote.crypt_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_crypt_methods();
break;
case LIBSSH2_METHOD_MAC_CS:
prefvar = &session->local.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_MAC_SC:
prefvar = &session->remote.mac_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_mac_methods();
break;
case LIBSSH2_METHOD_COMP_CS:
prefvar = &session->local.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_COMP_SC:
prefvar = &session->remote.comp_prefs;
mlist = (LIBSSH2_COMMON_METHOD**)libssh2_comp_methods();
break;
case LIBSSH2_METHOD_LANG_CS:
prefvar = &session->local.lang_prefs;
mlist = NULL;
break;
case LIBSSH2_METHOD_LANG_SC:
prefvar = &session->remote.lang_prefs;
mlist = NULL;
break;
default:
return -1;
}
s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
if (!newprefs) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocated space for method preferences", 0);
return -1;
}
memcpy(s, prefs, prefs_len + 1);
while (s && *s) {
char *p = strchr(s, ',');
int method_len = p ? (p - s) : strlen(s);
if (!libssh2_get_method_by_name(s, method_len, mlist)) {
/* Strip out unsupported method */
if (p) {
memcpy(s, p + 1, strlen(s) - method_len);
} else {
if (s > newprefs) {
*(--s) = '\0';
} else {
*s = '\0';
}
}
}
s = p ? (p + 1) : NULL;
}
if (strlen(newprefs) == 0) {
LIBSSH2_FREE(session, newprefs);
return -1;
}
if (*prefvar) {
LIBSSH2_FREE(session, *prefvar);
}
*prefvar = newprefs;
return 0;
}
/* }}} */

View File

@ -338,6 +338,7 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
}
}
/* Free banner(s) */
if (session->remote.banner) {
LIBSSH2_FREE(session, session->remote.banner);
}
@ -345,6 +346,40 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
LIBSSH2_FREE(session, session->local.banner);
}
/* Free preference(s) */
if (session->kex_prefs) {
LIBSSH2_FREE(session, session->kex_prefs);
}
if (session->hostkey_prefs) {
LIBSSH2_FREE(session, session->hostkey_prefs);
}
if (session->local.crypt_prefs) {
LIBSSH2_FREE(session, session->local.crypt_prefs);
}
if (session->local.mac_prefs) {
LIBSSH2_FREE(session, session->local.mac_prefs);
}
if (session->local.comp_prefs) {
LIBSSH2_FREE(session, session->local.comp_prefs);
}
if (session->local.lang_prefs) {
LIBSSH2_FREE(session, session->local.lang_prefs);
}
if (session->remote.crypt_prefs) {
LIBSSH2_FREE(session, session->remote.crypt_prefs);
}
if (session->remote.mac_prefs) {
LIBSSH2_FREE(session, session->remote.mac_prefs);
}
if (session->remote.comp_prefs) {
LIBSSH2_FREE(session, session->remote.comp_prefs);
}
if (session->remote.lang_prefs) {
LIBSSH2_FREE(session, session->remote.lang_prefs);
}
/* Cleanup any remaining packets */
while (session->packets.head) {
LIBSSH2_PACKET *tmp = session->packets.head;
@ -405,3 +440,47 @@ LIBSSH2_API void libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int rea
}
}
/* }}} */
/* {{{ libssh2_session_methods
* Return the currently active methods
* NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string regardless of actual negotiation
* Strings should NOT be freed
*/
LIBSSH2_API void libssh2_session_methods(LIBSSH2_SESSION *session, char **kex, char **hostkey,
char **crypt_cs, char **crypt_sc,
char **mac_cs, char **mac_sc,
char **comp_cs, char **comp_sc,
char **lang_cs, char **lang_sc)
{
if (kex) {
*kex = session->kex->name;
}
if (hostkey) {
*hostkey = session->hostkey->name;
}
if (crypt_cs) {
*crypt_cs = session->local.crypt->name;
}
if (crypt_sc) {
*crypt_sc = session->remote.crypt->name;
}
if (mac_cs) {
*mac_cs = session->local.mac->name;
}
if (mac_sc) {
*mac_sc = session->remote.mac->name;
}
if (comp_cs) {
*comp_cs = session->local.comp->name;
}
if (comp_sc) {
*comp_sc = session->remote.comp->name;
}
if (lang_cs) {
*lang_cs = "";
}
if (lang_sc) {
*lang_sc = "";
}
}
/* }}} */