mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 18:50:28 +09:00
Made ssh_packet_read asynchronous
Normally that's all that was needed into making SSH1 compliant with the new API. Beware, I have only implemented it, not actually tested it.
This commit is contained in:
@@ -43,21 +43,17 @@ enum ssh_packet_state_e {
|
|||||||
int packet_send(ssh_session session);
|
int packet_send(ssh_session session);
|
||||||
|
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
int packet_read(ssh_session session);
|
|
||||||
int packet_send1(ssh_session session) ;
|
int packet_send1(ssh_session session) ;
|
||||||
void ssh_packet_set_default_callbacks1(ssh_session session);
|
void ssh_packet_set_default_callbacks1(ssh_session session);
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_disconnect1);
|
SSH_PACKET_CALLBACK(ssh_packet_disconnect1);
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_smsg_success1);
|
SSH_PACKET_CALLBACK(ssh_packet_smsg_success1);
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1);
|
SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1);
|
||||||
|
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int packet_translate(ssh_session session);
|
int packet_translate(ssh_session session);
|
||||||
/* TODO: remove it when packet_wait is stripped out from libssh */
|
|
||||||
#ifdef WITH_SSH1
|
|
||||||
//int packet_wait(ssh_session session,int type,int blocking);
|
|
||||||
#endif
|
|
||||||
int packet_flush(ssh_session session, int enforce_blocking);
|
int packet_flush(ssh_session session, int enforce_blocking);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -587,7 +587,10 @@ void ssh_connection_callback(ssh_session session){
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* from now, the packet layer is handling incoming packets */
|
/* from now, the packet layer is handling incoming packets */
|
||||||
session->socket_callbacks.data=ssh_packet_socket_callback;
|
if(session->version==2)
|
||||||
|
session->socket_callbacks.data=ssh_packet_socket_callback;
|
||||||
|
else
|
||||||
|
session->socket_callbacks.data=ssh_packet_socket_callback1;
|
||||||
ssh_packet_set_default_callbacks(session);
|
ssh_packet_set_default_callbacks(session);
|
||||||
ssh_send_banner(session, 0);
|
ssh_send_banner(session, 0);
|
||||||
set_status(session, 0.5);
|
set_status(session, 0.5);
|
||||||
|
|||||||
@@ -358,7 +358,9 @@ error:
|
|||||||
leave_function();
|
leave_function();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @parse the "Type" header field of a packet and updates the session
|
||||||
|
*/
|
||||||
int packet_translate(ssh_session session) {
|
int packet_translate(ssh_session session) {
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
|
|||||||
@@ -80,23 +80,27 @@ void ssh_packet_set_default_callbacks1(ssh_session session){
|
|||||||
ssh_packet_set_callbacks(session, &session->default_packet_callbacks);
|
ssh_packet_set_callbacks(session, &session->default_packet_callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a slightly modified packet_read2() for SSH-1 protocol
|
|
||||||
* TODO: should be transformed in an asynchronous socket callback
|
/** @internal
|
||||||
|
* @handles a data received event. It then calls the handlers for the different packet types
|
||||||
|
* or and exception handler callback. Adapted for SSH-1 packets.
|
||||||
|
* @param user pointer to current ssh_session
|
||||||
|
* @param data pointer to the data received
|
||||||
|
* @len length of data received. It might not be enough for a complete packet
|
||||||
|
* @returns number of bytes read and processed.
|
||||||
*/
|
*/
|
||||||
int packet_read(ssh_session session) {
|
|
||||||
|
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user) {
|
||||||
void *packet = NULL;
|
void *packet = NULL;
|
||||||
int rc = SSH_ERROR;
|
int rc = SSH_ERROR;
|
||||||
int to_be_read;
|
int to_be_read;
|
||||||
|
size_t processed=0;
|
||||||
uint32_t padding;
|
uint32_t padding;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
ssh_session session=(ssh_session)user;
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
if(!session->alive) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (session->packet_state){
|
switch (session->packet_state){
|
||||||
case PACKET_STATE_INIT:
|
case PACKET_STATE_INIT:
|
||||||
memset(&session->in_packet, 0, sizeof(PACKET));
|
memset(&session->in_packet, 0, sizeof(PACKET));
|
||||||
@@ -111,12 +115,13 @@ int packet_read(ssh_session session) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* must have at least enough bytes for size */
|
||||||
rc = ssh_socket_read(session->socket, &len, sizeof(uint32_t));
|
if(receivedlen < sizeof(uint32_t)){
|
||||||
if (rc != SSH_OK) {
|
leave_function();
|
||||||
goto error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
memcpy(&len,data,sizeof(uint32_t));
|
||||||
|
processed += sizeof(uint32_t);
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
|
|
||||||
/* len is not encrypted */
|
/* len is not encrypted */
|
||||||
@@ -136,27 +141,20 @@ int packet_read(ssh_session session) {
|
|||||||
/* SSH-1 has a fixed padding lenght */
|
/* SSH-1 has a fixed padding lenght */
|
||||||
padding = 8 - (len % 8);
|
padding = 8 - (len % 8);
|
||||||
to_be_read = len + padding;
|
to_be_read = len + padding;
|
||||||
|
if(to_be_read + processed > receivedlen){
|
||||||
|
/* wait for rest of packet */
|
||||||
|
leave_function();
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
/* it is _not_ possible that to_be_read be < 8. */
|
/* it is _not_ possible that to_be_read be < 8. */
|
||||||
packet = malloc(to_be_read);
|
packet = (char *)data + processed;
|
||||||
if (packet == NULL) {
|
|
||||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_socket_read(session->socket, packet, to_be_read);
|
|
||||||
if(rc != SSH_OK) {
|
|
||||||
SAFE_FREE(packet);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = SSH_ERROR;
|
rc = SSH_ERROR;
|
||||||
|
|
||||||
if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
|
if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
|
||||||
SAFE_FREE(packet);
|
SAFE_FREE(packet);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
SAFE_FREE(packet);
|
processed += to_be_read;
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("read packet:", buffer_get(session->in_buffer),
|
ssh_print_hexa("read packet:", buffer_get(session->in_buffer),
|
||||||
buffer_get_len(session->in_buffer));
|
buffer_get_len(session->in_buffer));
|
||||||
@@ -216,18 +214,31 @@ int packet_read(ssh_session session) {
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
session->recv_seq++;
|
session->recv_seq++;
|
||||||
session->packet_state=PACKET_STATE_INIT;
|
/* We don't want to rewrite a new packet while still executing the packet callbacks */
|
||||||
|
session->packet_state = PACKET_STATE_PROCESSING;
|
||||||
|
packet_translate(session);
|
||||||
|
/* execute callbacks */
|
||||||
|
ssh_packet_process(session, session->in_packet.type);
|
||||||
|
session->packet_state = PACKET_STATE_INIT;
|
||||||
|
if(processed < receivedlen){
|
||||||
|
/* Handle a potential packet left in socket buffer */
|
||||||
|
ssh_log(session,SSH_LOG_PACKET,"Processing %" PRIdS " bytes left in socket buffer",
|
||||||
|
receivedlen-processed);
|
||||||
|
rc = ssh_packet_socket_callback1((char *)data + processed,
|
||||||
|
receivedlen - processed,user);
|
||||||
|
processed += rc;
|
||||||
|
}
|
||||||
leave_function();
|
leave_function();
|
||||||
return SSH_OK;
|
return processed;
|
||||||
} /* switch */
|
case PACKET_STATE_PROCESSING:
|
||||||
|
ssh_log(session, SSH_LOG_RARE, "Nested packet processing. Delaying.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_set_error(session, SSH_FATAL,
|
|
||||||
"Invalid state into packet_read1(): %d",
|
|
||||||
session->packet_state);
|
|
||||||
error:
|
error:
|
||||||
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
leave_function();
|
leave_function();
|
||||||
return rc;
|
return processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user