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:
parent
165837c085
commit
566bea77ea
4
README
4
README
@ -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
|
||||
-----------
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
312
src/kex.c
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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 = "";
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
Loading…
x
Reference in New Issue
Block a user