Made the server DH asynchronous.
It still needs testing and cleanup, it was done with less care than the client-side. The socket listening and connexion is still synchronous
Этот коммит содержится в:
родитель
ef5dc6cd2b
Коммит
84ec17964e
@ -245,6 +245,9 @@ int gettimeofday(struct timeval *__p, void *__t);
|
|||||||
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir);
|
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir);
|
||||||
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
|
int ssh_options_set_algo(ssh_session session, int algo, const char *list);
|
||||||
|
|
||||||
|
/* server.c */
|
||||||
|
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
||||||
|
|
||||||
/** Free memory space */
|
/** Free memory space */
|
||||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
|
||||||
|
|
||||||
|
@ -43,6 +43,12 @@ enum ssh_session_state_e {
|
|||||||
SSH_SESSION_STATE_ERROR
|
SSH_SESSION_STATE_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ssh_dh_state_e {
|
||||||
|
DH_STATE_INIT,
|
||||||
|
DH_STATE_INIT_SENT,
|
||||||
|
DH_STATE_NEWKEYS_SENT,
|
||||||
|
DH_STATE_FINISHED
|
||||||
|
};
|
||||||
|
|
||||||
struct ssh_session_struct {
|
struct ssh_session_struct {
|
||||||
struct error_struct error;
|
struct error_struct error;
|
||||||
|
102
libssh/client.c
102
libssh/client.c
@ -246,12 +246,7 @@ int ssh_send_banner(ssh_session session, int server) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ssh_dh_state_e {
|
|
||||||
DH_STATE_INIT,
|
|
||||||
DH_STATE_INIT_SENT,
|
|
||||||
DH_STATE_NEWKEYS_SENT,
|
|
||||||
DH_STATE_FINISHED
|
|
||||||
};
|
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
|
SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
|
||||||
ssh_string f = NULL;
|
ssh_string f = NULL;
|
||||||
@ -325,52 +320,57 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
|
|||||||
session->session_state,session->dh_handshake_state);
|
session->session_state,session->dh_handshake_state);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = make_sessionid(session);
|
if(session->server){
|
||||||
if (rc != SSH_OK) {
|
/* server things are done in server.c */
|
||||||
goto error;
|
session->dh_handshake_state=DH_STATE_FINISHED;
|
||||||
|
} else {
|
||||||
|
/* client */
|
||||||
|
rc = make_sessionid(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the cryptographic functions for the next crypto
|
||||||
|
* (it is needed for generate_session_keys for key lengths)
|
||||||
|
*/
|
||||||
|
if (crypt_set_algorithms(session)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generate_session_keys(session) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the host's signature. FIXME do it sooner */
|
||||||
|
signature = session->dh_server_signature;
|
||||||
|
session->dh_server_signature = NULL;
|
||||||
|
if (signature_verify(session, signature)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* forget it for now ... */
|
||||||
|
string_burn(signature);
|
||||||
|
string_free(signature);
|
||||||
|
signature=NULL;
|
||||||
|
/*
|
||||||
|
* Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
|
||||||
|
* current_crypto
|
||||||
|
*/
|
||||||
|
if (session->current_crypto) {
|
||||||
|
crypto_free(session->current_crypto);
|
||||||
|
session->current_crypto=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME later, include a function to change keys */
|
||||||
|
session->current_crypto = session->next_crypto;
|
||||||
|
|
||||||
|
session->next_crypto = crypto_new();
|
||||||
|
if (session->next_crypto == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the cryptographic functions for the next crypto
|
|
||||||
* (it is needed for generate_session_keys for key lengths)
|
|
||||||
*/
|
|
||||||
if (crypt_set_algorithms(session)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (generate_session_keys(session) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify the host's signature. FIXME do it sooner */
|
|
||||||
signature = session->dh_server_signature;
|
|
||||||
session->dh_server_signature = NULL;
|
|
||||||
if (signature_verify(session, signature)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* forget it for now ... */
|
|
||||||
string_burn(signature);
|
|
||||||
string_free(signature);
|
|
||||||
signature=NULL;
|
|
||||||
/*
|
|
||||||
* Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
|
|
||||||
* current_crypto
|
|
||||||
*/
|
|
||||||
if (session->current_crypto) {
|
|
||||||
crypto_free(session->current_crypto);
|
|
||||||
session->current_crypto=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME later, include a function to change keys */
|
|
||||||
session->current_crypto = session->next_crypto;
|
|
||||||
|
|
||||||
session->next_crypto = crypto_new();
|
|
||||||
if (session->next_crypto == NULL) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
session->dh_handshake_state = DH_STATE_FINISHED;
|
session->dh_handshake_state = DH_STATE_FINISHED;
|
||||||
ssh_connection_callback(session);
|
ssh_connection_callback(session);
|
||||||
return SSH_PACKET_USED;
|
return SSH_PACKET_USED;
|
||||||
|
@ -351,30 +351,45 @@ static int server_set_kex(ssh_session session) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dh_handshake_server(ssh_session session) {
|
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
|
||||||
ssh_string e;
|
ssh_string e;
|
||||||
ssh_string f;
|
(void)type;
|
||||||
ssh_string pubkey;
|
(void)user;enter_function();
|
||||||
ssh_string sign;
|
ssh_log(session,SSH_LOG_PACKET,"Received SSH_MSG_KEXDH_INIT");
|
||||||
ssh_public_key pub;
|
if(session->dh_handshake_state != DH_STATE_INIT){
|
||||||
ssh_private_key prv;
|
ssh_log(session,SSH_LOG_RARE,"Invalid state for SSH_MSG_KEXDH_INIT");
|
||||||
|
goto error;
|
||||||
if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
e = buffer_get_ssh_string(packet);
|
||||||
e = buffer_get_ssh_string(session->in_buffer);
|
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL, "No e number in client request");
|
ssh_set_error(session, SSH_FATAL, "No e number in client request");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (dh_import_e(session, e) < 0) {
|
if (dh_import_e(session, e) < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Cannot import e number");
|
ssh_set_error(session, SSH_FATAL, "Cannot import e number");
|
||||||
string_free(e);
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
return -1;
|
} else {
|
||||||
|
session->dh_handshake_state=DH_STATE_INIT_SENT;
|
||||||
}
|
}
|
||||||
string_free(e);
|
string_free(e);
|
||||||
|
|
||||||
|
error:
|
||||||
|
leave_function();
|
||||||
|
return SSH_PACKET_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dh_handshake_server(ssh_session session) {
|
||||||
|
ssh_string f;
|
||||||
|
ssh_string pubkey;
|
||||||
|
ssh_string sign;
|
||||||
|
ssh_public_key pub;
|
||||||
|
ssh_private_key prv;
|
||||||
|
/* waiting for SSH_MSG_KEXDH_INIT */
|
||||||
|
while(session->dh_handshake_state != DH_STATE_INIT_SENT){
|
||||||
|
ssh_handle_packets(session);
|
||||||
|
}
|
||||||
|
/* received SSH_MSG_KEXDH_INIT */
|
||||||
|
|
||||||
if (dh_generate_y(session) < 0) {
|
if (dh_generate_y(session) < 0) {
|
||||||
ssh_set_error(session, SSH_FATAL, "Could not create y number");
|
ssh_set_error(session, SSH_FATAL, "Could not create y number");
|
||||||
return -1;
|
return -1;
|
||||||
@ -458,7 +473,7 @@ static int dh_handshake_server(ssh_session session) {
|
|||||||
}
|
}
|
||||||
string_free(f);
|
string_free(f);
|
||||||
string_free(sign);
|
string_free(sign);
|
||||||
|
session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
|
||||||
if (packet_send(session) != SSH_OK) {
|
if (packet_send(session) != SSH_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -473,10 +488,8 @@ static int dh_handshake_server(ssh_session session) {
|
|||||||
}
|
}
|
||||||
ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
|
ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
|
||||||
|
|
||||||
if (packet_wait(session, SSH2_MSG_NEWKEYS, 1) != SSH_OK) {
|
while(session->dh_handshake_state != DH_STATE_FINISHED)
|
||||||
return -1;
|
ssh_handle_packets(session);
|
||||||
}
|
|
||||||
ssh_log(session, SSH_LOG_PACKET, "Got SSH_MSG_NEWKEYS");
|
|
||||||
|
|
||||||
if (generate_session_keys(session) < 0) {
|
if (generate_session_keys(session) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user