mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-12 03:00:26 +09:00
same changes, SSH1 (reading only).
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@50 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
114
libssh/packet.c
114
libssh/packet.c
@@ -58,7 +58,6 @@ static int completeread(int fd, void *buffer, int len){
|
|||||||
|
|
||||||
static int socket_read(SSH_SESSION *session,int len){
|
static int socket_read(SSH_SESSION *session,int len){
|
||||||
int except, can_write;
|
int except, can_write;
|
||||||
int ret;
|
|
||||||
int to_read;
|
int to_read;
|
||||||
int r;
|
int r;
|
||||||
char *buf;
|
char *buf;
|
||||||
@@ -70,11 +69,11 @@ static int socket_read(SSH_SESSION *session,int len){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
if(session->blocking){
|
if(session->blocking){
|
||||||
buf=malloc(to_read);
|
buf=malloc(to_read);
|
||||||
ret=completeread(session->fd,buf,to_read);
|
r=completeread(session->fd,buf,to_read);
|
||||||
session->data_to_read=0;
|
session->data_to_read=0;
|
||||||
if(ret==SSH_ERROR || ret ==0){
|
if(r==SSH_ERROR || r ==0){
|
||||||
ssh_set_error(session,SSH_FATAL,
|
ssh_set_error(session,SSH_FATAL,
|
||||||
(ret==0)?"Connection closed by remote host" : "Error reading socket");
|
(r==0)?"Connection closed by remote host" : "Error reading socket");
|
||||||
close(session->fd);
|
close(session->fd);
|
||||||
session->fd=-1;
|
session->fd=-1;
|
||||||
session->data_except=1;
|
session->data_except=1;
|
||||||
@@ -95,7 +94,7 @@ static int socket_read(SSH_SESSION *session,int len){
|
|||||||
r=read(session->fd,buffer,sizeof(buffer));
|
r=read(session->fd,buffer,sizeof(buffer));
|
||||||
if(r<=0){
|
if(r<=0){
|
||||||
ssh_set_error(session,SSH_FATAL,
|
ssh_set_error(session,SSH_FATAL,
|
||||||
(ret==0)?"Connection closed by remote host" : "Error reading socket");
|
(r==0)?"Connection closed by remote host" : "Error reading socket");
|
||||||
close(session->fd);
|
close(session->fd);
|
||||||
session->fd=-1;
|
session->fd=-1;
|
||||||
session->data_except=1;
|
session->data_except=1;
|
||||||
@@ -114,7 +113,6 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
void *packet=NULL;
|
void *packet=NULL;
|
||||||
unsigned char mac[30];
|
unsigned char mac[30];
|
||||||
char buffer[16];
|
char buffer[16];
|
||||||
int be_read,i;
|
|
||||||
int to_be_read;
|
int to_be_read;
|
||||||
int ret;
|
int ret;
|
||||||
u8 padding;
|
u8 padding;
|
||||||
@@ -167,7 +165,8 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
}
|
}
|
||||||
if(session->current_crypto){
|
if(session->current_crypto){
|
||||||
/* decrypt the rest of the packet (blocksize bytes already have been decrypted */
|
/* decrypt the rest of the packet (blocksize bytes already have been decrypted */
|
||||||
packet_decrypt(session,buffer_get(session->in_buffer)+blocksize,buffer_get_len(session->in_buffer)-blocksize);
|
packet_decrypt(session,buffer_get(session->in_buffer)+blocksize,
|
||||||
|
buffer_get_len(session->in_buffer)-blocksize);
|
||||||
memcpy(mac,buffer_get_rest(session->in_socket_buffer),macsize);
|
memcpy(mac,buffer_get_rest(session->in_socket_buffer),macsize);
|
||||||
buffer_pass_bytes(session->in_socket_buffer,macsize);
|
buffer_pass_bytes(session->in_socket_buffer,macsize);
|
||||||
if(packet_hmac_verify(session,session->in_buffer,mac)){
|
if(packet_hmac_verify(session,session->in_buffer,mac)){
|
||||||
@@ -175,16 +174,20 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer_pass_bytes(session->in_buffer,sizeof(u32)); /*pass the size which has been processed before*/
|
buffer_pass_bytes(session->in_buffer,sizeof(u32));
|
||||||
|
/*pass the size which has been processed before*/
|
||||||
if(!buffer_get_u8(session->in_buffer,&padding)){
|
if(!buffer_get_u8(session->in_buffer,&padding)){
|
||||||
ssh_set_error(session,SSH_FATAL,"Packet too short to read padding");
|
ssh_set_error(session,SSH_FATAL,"Packet too short to read padding");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n",padding,buffer_get_rest_len(session->in_buffer));
|
ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n",
|
||||||
|
padding,buffer_get_rest_len(session->in_buffer));
|
||||||
if(padding > buffer_get_rest_len(session->in_buffer)){
|
if(padding > buffer_get_rest_len(session->in_buffer)){
|
||||||
ssh_set_error(session,SSH_FATAL,"invalid padding: %d (%d resting)",padding,buffer_get_rest_len(session->in_buffer));
|
ssh_set_error(session,SSH_FATAL,"invalid padding: %d (%d resting)",
|
||||||
|
padding,buffer_get_rest_len(session->in_buffer));
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("incrimined packet",buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
ssh_print_hexa("incrimined packet",
|
||||||
|
buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
||||||
#endif
|
#endif
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -209,69 +212,49 @@ static int packet_read2(SSH_SESSION *session){
|
|||||||
static int packet_read1(SSH_SESSION *session){
|
static int packet_read1(SSH_SESSION *session){
|
||||||
u32 len;
|
u32 len;
|
||||||
void *packet=NULL;
|
void *packet=NULL;
|
||||||
// char buffer[16];
|
int ret;
|
||||||
int be_read,i;
|
|
||||||
int to_be_read;
|
int to_be_read;
|
||||||
u32 padding;
|
u32 padding;
|
||||||
u32 crc;
|
u32 crc;
|
||||||
ssh_say(3,"packet_read1()\n");
|
ssh_say(3,"packet_read1()\n");
|
||||||
// unsigned int blocksize=8;
|
|
||||||
session->data_to_read=0; /* clear the dataavailable flag */
|
|
||||||
if(!session->alive || session->data_except)
|
if(!session->alive || session->data_except)
|
||||||
return -1; // the error message was already set
|
return SSH_ERROR; // the error message was already set
|
||||||
|
switch (session->packet_state){
|
||||||
|
case PACKET_STATE_INIT:
|
||||||
memset(&session->in_packet,0,sizeof(PACKET));
|
memset(&session->in_packet,0,sizeof(PACKET));
|
||||||
if(session->in_buffer)
|
if(session->in_buffer)
|
||||||
buffer_free(session->in_buffer);
|
buffer_reinit(session->in_buffer);
|
||||||
|
else
|
||||||
session->in_buffer=buffer_new();
|
session->in_buffer=buffer_new();
|
||||||
|
ret=socket_read(session,sizeof(u32));
|
||||||
be_read=completeread(session->fd,&len,sizeof(u32));
|
if(ret!=SSH_OK)
|
||||||
if(be_read!=sizeof(u32)){
|
return ret; // could be SSH_AGAIN
|
||||||
if(be_read<=0){
|
buffer_get_u32(session->in_socket_buffer,&len);
|
||||||
session->alive=0;
|
/* be_read=completeread(session->fd,&len,sizeof(u32)); */
|
||||||
session->data_except=1;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,
|
|
||||||
(be_read==0)?"Connection closed by remote host" : "Error reading socket");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): asked %d bytes, received %d",sizeof(u32),be_read);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* len is not encrypted */
|
/* len is not encrypted */
|
||||||
len=ntohl(len);
|
len=ntohl(len);
|
||||||
|
|
||||||
if(len> MAX_PACKET_LEN){
|
if(len> MAX_PACKET_LEN){
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%uld %.8lx)",len,len);
|
ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%uld %.8lx)",len,len);
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
ssh_say(3,"%d bytes packet\n",len);
|
ssh_say(3,"%d bytes packet\n",len);
|
||||||
|
session->in_packet.len=len;
|
||||||
|
session->packet_state=PACKET_STATE_SIZEREAD;
|
||||||
|
case PACKET_STATE_SIZEREAD:
|
||||||
|
len=session->in_packet.len;
|
||||||
/* 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;
|
||||||
/* handle the case in which the whole packet size = blocksize */
|
/* it is *not* possible that to_be_read be < 8. */
|
||||||
if(to_be_read !=0){
|
ret=socket_read(session,to_be_read);
|
||||||
|
if(ret != SSH_OK)
|
||||||
|
return ret; // can be SSH_ERROR or SSH_AGAIN
|
||||||
packet=malloc(to_be_read);
|
packet=malloc(to_be_read);
|
||||||
i=completeread(session->fd,packet,to_be_read);
|
memcpy(packet,buffer_get_rest(session->in_socket_buffer),to_be_read);
|
||||||
if(i<=0){
|
buffer_pass_bytes(session->in_socket_buffer,to_be_read);
|
||||||
session->alive=0;
|
|
||||||
session->data_except=1;
|
|
||||||
close(session->fd);
|
|
||||||
session->fd=-1;
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Server closed connection");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(i!=to_be_read){
|
|
||||||
free(packet);
|
|
||||||
packet=NULL;
|
|
||||||
ssh_say(3,"Read only %d, wanted %d\n",i,to_be_read);
|
|
||||||
ssh_set_error(session,SSH_FATAL,"read_packet(): read only %d, wanted %d",i,to_be_read);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssh_say(3,"Read a %d bytes packet\n",len);
|
|
||||||
buffer_add_data(session->in_buffer,packet,to_be_read);
|
buffer_add_data(session->in_buffer,packet,to_be_read);
|
||||||
free(packet);
|
free(packet);
|
||||||
}
|
|
||||||
#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));
|
||||||
@@ -283,13 +266,14 @@ static int packet_read1(SSH_SESSION *session){
|
|||||||
packet_decrypt(session,buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
packet_decrypt(session,buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("read packet decrypted:",buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
ssh_print_hexa("read packet decrypted:",
|
||||||
|
buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
|
||||||
#endif
|
#endif
|
||||||
ssh_say(3,"%d bytes padding\n",padding);
|
ssh_say(3,"%d bytes padding\n",padding);
|
||||||
if((len+padding) != buffer_get_rest_len(session->in_buffer) || (len+padding) < sizeof(u32)){
|
if((len+padding) != buffer_get_rest_len(session->in_buffer) || (len+padding) < sizeof(u32)){
|
||||||
ssh_say(2,"no crc32 in packet\n");
|
ssh_say(2,"no crc32 in packet\n");
|
||||||
ssh_set_error(session,SSH_FATAL,"no crc32 in packet");
|
ssh_set_error(session,SSH_FATAL,"no crc32 in packet");
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(&crc,buffer_get_rest(session->in_buffer)+(len+padding)-sizeof(u32),
|
memcpy(&crc,buffer_get_rest(session->in_buffer)+(len+padding)-sizeof(u32),
|
||||||
sizeof(u32));
|
sizeof(u32));
|
||||||
@@ -304,7 +288,7 @@ ssh_print_hexa("read packet decrypted:",buffer_get(session->in_buffer),buffer_ge
|
|||||||
ssh_set_error(session,SSH_FATAL,"invalid crc32 : expected %.8lx, "
|
ssh_set_error(session,SSH_FATAL,"invalid crc32 : expected %.8lx, "
|
||||||
"got %.8lx",crc,
|
"got %.8lx",crc,
|
||||||
ssh_crc32(buffer_get_rest(session->in_buffer),len+padding-sizeof(u32)) );
|
ssh_crc32(buffer_get_rest(session->in_buffer),len+padding-sizeof(u32)) );
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
buffer_pass_bytes(session->in_buffer,padding); /*pass the padding*/
|
buffer_pass_bytes(session->in_buffer,padding); /*pass the padding*/
|
||||||
ssh_say(3,"the packet is valid\n");
|
ssh_say(3,"the packet is valid\n");
|
||||||
@@ -316,7 +300,11 @@ ssh_print_hexa("read packet decrypted:",buffer_get(session->in_buffer),buffer_ge
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
session->recv_seq++;
|
session->recv_seq++;
|
||||||
return 0;
|
session->packet_state=PACKET_STATE_INIT;
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
ssh_set_error(session,SSH_FATAL,"Invalid state into packet_read2() : %d",session->packet_state);
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SSH1 */
|
#endif /* HAVE_SSH1 */
|
||||||
@@ -357,6 +345,8 @@ static int atomic_write(int fd, void *buffer, int len){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* when doing a nonblocking write, you should issue the packet_write only once, then
|
||||||
|
* do packet_nonblocking_flush() until you get a SSH_OK or a SSH_ERROR */
|
||||||
int packet_nonblocking_flush(SSH_SESSION *session){
|
int packet_nonblocking_flush(SSH_SESSION *session){
|
||||||
int except, can_write;
|
int except, can_write;
|
||||||
int w;
|
int w;
|
||||||
@@ -364,6 +354,7 @@ int packet_nonblocking_flush(SSH_SESSION *session){
|
|||||||
while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){
|
while(session->data_to_write && buffer_get_rest_len(session->out_socket_buffer)>0){
|
||||||
w=write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
w=write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
||||||
buffer_get_rest_len(session->out_socket_buffer));
|
buffer_get_rest_len(session->out_socket_buffer));
|
||||||
|
session->data_to_write=0;
|
||||||
if(w<0){
|
if(w<0){
|
||||||
session->data_to_write=0;
|
session->data_to_write=0;
|
||||||
session->data_except=1;
|
session->data_except=1;
|
||||||
@@ -375,13 +366,16 @@ int packet_nonblocking_flush(SSH_SESSION *session){
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
buffer_pass_bytes(session->out_socket_buffer,w);
|
buffer_pass_bytes(session->out_socket_buffer,w);
|
||||||
|
/* refresh the socket status */
|
||||||
|
ssh_fd_poll(session,&can_write,&except);
|
||||||
}
|
}
|
||||||
if(buffer_get_rest_len(session->out_socket_buffer)>0)
|
if(buffer_get_rest_len(session->out_socket_buffer)>0)
|
||||||
return SSH_AGAIN; /* there is data pending */
|
return SSH_AGAIN; /* there is data pending */
|
||||||
return SSH_OK; // all data written
|
return SSH_OK; // all data written
|
||||||
}
|
}
|
||||||
|
|
||||||
int packet_flush(SSH_SESSION *session){
|
/* blocking packet flush */
|
||||||
|
int packet_blocking_flush(SSH_SESSION *session){
|
||||||
if(atomic_write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
if(atomic_write(session->fd,buffer_get_rest(session->out_socket_buffer),
|
||||||
buffer_get_rest_len(session->out_socket_buffer))){
|
buffer_get_rest_len(session->out_socket_buffer))){
|
||||||
session->data_to_write=0;
|
session->data_to_write=0;
|
||||||
@@ -408,7 +402,7 @@ static int socket_write(SSH_SESSION *session){
|
|||||||
if(!session->blocking){
|
if(!session->blocking){
|
||||||
return packet_nonblocking_flush(session);
|
return packet_nonblocking_flush(session);
|
||||||
} else
|
} else
|
||||||
return packet_flush(session);
|
return packet_blocking_flush(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int packet_send2(SSH_SESSION *session){
|
static int packet_send2(SSH_SESSION *session){
|
||||||
|
|||||||
Reference in New Issue
Block a user