19
19
*
20
20
*/
21
21
22
+ #include <inttypes.h>
22
23
#include <stdio.h>
23
24
#include <stdlib.h>
24
25
#include <unistd.h>
@@ -534,18 +535,42 @@ static void release_vchan_port(int port, int expected_remote_id)
534
535
static int handle_cmdline_body_from_client (int fd , struct msg_header * hdr )
535
536
{
536
537
struct exec_params params ;
537
- int len = hdr -> len - sizeof ( params ) ;
538
- char buf [ len ] ;
538
+ uint32_t len ;
539
+ char * buf = NULL ;
539
540
int use_default_user = 0 ;
540
541
int i ;
541
542
543
+ if (hdr -> len <= sizeof (params )) {
544
+ LOG (ERROR , "Too-short packet received from client %d: "
545
+ "type %" PRIu32 ", len %" PRIu32 "(min %zu)" ,
546
+ fd , hdr -> type , hdr -> len , sizeof (params ) + 1 );
547
+ goto terminate ;
548
+ }
549
+ if (hdr -> len > MAX_QREXEC_CMD_LEN ) {
550
+ LOG (ERROR , "Too-long packet received from client %d: "
551
+ "type %" PRIu32 ", len %" PRIu32 "(max %lu)" ,
552
+ fd , hdr -> type , hdr -> len , MAX_QREXEC_CMD_LEN );
553
+ goto terminate ;
554
+ }
555
+ len = hdr -> len - sizeof (params );
556
+
557
+ buf = malloc (len );
558
+ if (buf == NULL ) {
559
+ PERROR ("malloc" );
560
+ goto terminate ;
561
+ }
562
+
542
563
if (!read_all (fd , & params , sizeof (params ))) {
543
- terminate_client (fd );
544
- return 0 ;
564
+ goto terminate ;
545
565
}
546
566
if (!read_all (fd , buf , len )) {
547
- terminate_client (fd );
548
- return 0 ;
567
+ goto terminate ;
568
+ }
569
+
570
+ if (buf [len - 1 ] != '\0' ) {
571
+ LOG (ERROR , "Client sent buffer of length %" PRIu32 " that is not "
572
+ "NUL-terminated" , len );
573
+ goto terminate ;
549
574
}
550
575
551
576
if (hdr -> type == MSG_SERVICE_CONNECT ) {
@@ -562,8 +587,7 @@ static int handle_cmdline_body_from_client(int fd, struct msg_header *hdr)
562
587
if (i > policy_pending_max ) {
563
588
LOG (ERROR , "Connection with ident %s not requested or already handled" ,
564
589
policy_pending [i ].params .ident );
565
- terminate_client (fd );
566
- return 0 ;
590
+ goto terminate ;
567
591
}
568
592
policy_pending [i ].response_sent = RESPONSE_ALLOW ;
569
593
}
@@ -574,29 +598,28 @@ static int handle_cmdline_body_from_client(int fd, struct msg_header *hdr)
574
598
params .connect_port = allocate_vchan_port (params .connect_domain );
575
599
if (params .connect_port <= 0 ) {
576
600
LOG (ERROR , "Failed to allocate new vchan port, too many clients?" );
577
- terminate_client (fd );
578
- return 0 ;
601
+ goto terminate ;
579
602
}
580
603
/* notify the client when this connection got terminated */
581
604
vchan_port_notify_client [params .connect_port - VCHAN_BASE_DATA_PORT ] = fd ;
582
605
client_params .connect_port = params .connect_port ;
583
606
client_params .connect_domain = remote_domain_id ;
584
607
hdr -> len = sizeof (client_params );
585
- if (!write_all (fd , hdr , sizeof (* hdr ))) {
586
- terminate_client (fd );
587
- release_vchan_port (params .connect_port , params .connect_domain );
588
- return 0 ;
589
- }
590
- if (!write_all (fd , & client_params , sizeof (client_params ))) {
608
+ if (!write_all (fd , hdr , sizeof (* hdr )) ||
609
+ !write_all (fd , & client_params , sizeof (client_params ))) {
591
610
terminate_client (fd );
592
611
release_vchan_port (params .connect_port , params .connect_domain );
612
+ free (buf );
593
613
return 0 ;
594
614
}
595
615
/* restore original len value */
596
616
hdr -> len = len + sizeof (params );
597
617
} else {
598
- assert (params .connect_port >= VCHAN_BASE_DATA_PORT );
599
- assert (params .connect_port < VCHAN_BASE_DATA_PORT + MAX_CLIENTS );
618
+ if (!((params .connect_port >= VCHAN_BASE_DATA_PORT ) &&
619
+ (params .connect_port < VCHAN_BASE_DATA_PORT + MAX_CLIENTS ))) {
620
+ LOG (ERROR , "Invalid connect port %" PRIu32 , params .connect_port );
621
+ goto terminate ;
622
+ }
600
623
}
601
624
602
625
if (!strncmp (buf , default_user_keyword , default_user_keyword_len_without_colon + 1 )) {
@@ -617,9 +640,14 @@ static int handle_cmdline_body_from_client(int fd, struct msg_header *hdr)
617
640
send_len ) != send_len )
618
641
handle_vchan_error ("send buf" );
619
642
} else
620
- if (libvchan_send (vchan , buf , len ) < len )
643
+ if (libvchan_send (vchan , buf , len ) < ( int ) len )
621
644
handle_vchan_error ("send buf" );
645
+ free (buf );
622
646
return 1 ;
647
+ terminate :
648
+ terminate_client (fd );
649
+ free (buf );
650
+ return 0 ;
623
651
}
624
652
625
653
static void handle_cmdline_message_from_client (int fd )
@@ -639,10 +667,11 @@ static void handle_cmdline_message_from_client(int fd)
639
667
return ;
640
668
}
641
669
642
- if (!handle_cmdline_body_from_client (fd , & hdr ))
670
+ if (!handle_cmdline_body_from_client (fd , & hdr )) {
643
671
// client disconnected while sending cmdline, above call already
644
672
// cleaned up client info
645
673
return ;
674
+ }
646
675
clients [fd ].state = CLIENT_RUNNING ;
647
676
}
648
677
0 commit comments