19
19
*
20
20
*/
21
21
22
+ #include <limits.h>
22
23
#include <sys/socket.h>
23
24
#include <sys/un.h>
24
25
#include <stdio.h>
@@ -415,44 +416,47 @@ _Noreturn static void usage(const char *const name)
415
416
" -w timeout - override default connection timeout of 5s (set 0 for no timeout)\n"
416
417
" -k - kill the domain right before exiting\n"
417
418
" --socket-dir=PATH - directory for qrexec socket, default: %s\n" ,
418
- name , QREXEC_DAEMON_SOCKET_DIR );
419
+ name ? name : "qrexec-client" , QREXEC_DAEMON_SOCKET_DIR );
419
420
exit (1 );
420
421
}
421
422
423
+ static int parse_int (const char * str , const char * msg ) {
424
+ long value ;
425
+ char * end = (char * )str ;
426
+
427
+ if (str [0 ] < '0' || str [0 ] > '9' )
428
+ errx (1 , "%s '%s' does not start with an ASCII digit" , msg , str );
429
+ errno = 0 ;
430
+ value = strtol (str , & end , 0 );
431
+ if (* end != '\0' )
432
+ errx (1 , "trailing junk '%s' after %s" , end , msg );
433
+ if (errno == 0 && (value < 0 || value > INT_MAX ))
434
+ errno = ERANGE ;
435
+ if (errno )
436
+ err (1 , "invalid %s '%s': strtol" , msg , str );
437
+ return (int )value ;
438
+ }
439
+
422
440
static void parse_connect (char * str , char * * request_id ,
423
441
char * * src_domain_name , int * src_domain_id )
424
442
{
425
- int i = 0 ;
426
- char * token = NULL ;
427
- char * separators = "," ;
428
-
429
- token = strtok (str , separators );
430
- while (token )
431
- {
432
- switch (i )
433
- {
434
- case 0 :
435
- * request_id = token ;
436
- if (strlen (* request_id ) >= sizeof (struct service_params )) {
437
- fprintf (stderr , "Invalid -c parameter (request_id too long, max %lu)\n" ,
438
- sizeof (struct service_params )-1 );
439
- exit (1 );
440
- }
441
- break ;
442
- case 1 :
443
- * src_domain_name = token ;
444
- break ;
445
- case 2 :
446
- * src_domain_id = atoi (token );
447
- break ;
448
- default :
449
- goto bad_c_param ;
450
- }
451
- token = strtok (NULL , separators );
452
- i ++ ;
453
- }
454
- if (i == 3 )
455
- return ;
443
+ char * token ;
444
+
445
+ token = strchr (str , ',' );
446
+ if (token == NULL )
447
+ goto bad_c_param ;
448
+ if ((size_t )(token - str ) >= sizeof (struct service_params ))
449
+ errx (1 , "Invalid -c parameter (request_id too long, max %zu)\n" ,
450
+ sizeof (struct service_params )-1 );
451
+ * token = 0 ;
452
+ * request_id = str ;
453
+ * src_domain_name = token + 1 ;
454
+ token = strchr (* src_domain_name , ',' );
455
+ if (token == NULL )
456
+ goto bad_c_param ;
457
+ * token = 0 ;
458
+ * src_domain_id = parse_int (token + 1 , "source domain ID" );
459
+ return ;
456
460
bad_c_param :
457
461
fprintf (stderr , "Invalid -c parameter (should be: \"-c request_id,src_domain_name,src_domain_id\")\n" );
458
462
exit (1 );
@@ -547,6 +551,11 @@ int main(int argc, char **argv)
547
551
int prepare_ret ;
548
552
bool kill = false;
549
553
554
+ if (argc < 3 ) {
555
+ // certainly too few arguments
556
+ usage (argv [0 ]);
557
+ }
558
+
550
559
setup_logging ("qrexec-client" );
551
560
552
561
while ((opt = getopt_long (argc , argv , "hd:l:eEc:tTw:Wk" , longopts , NULL )) != -1 ) {
@@ -564,6 +573,10 @@ int main(int argc, char **argv)
564
573
exit_with_code = 0 ;
565
574
break ;
566
575
case 'c' :
576
+ if (request_id != NULL ) {
577
+ warnx ("ERROR: -c passed more than once" );
578
+ usage (argv [0 ]);
579
+ }
567
580
parse_connect (optarg , & request_id , & src_domain_name , & src_domain_id );
568
581
is_service = 1 ;
569
582
break ;
@@ -574,7 +587,7 @@ int main(int argc, char **argv)
574
587
replace_chars_stderr = 1 ;
575
588
break ;
576
589
case 'w' :
577
- connection_timeout = atoi (optarg );
590
+ connection_timeout = parse_int (optarg , "connection timeout" );
578
591
break ;
579
592
case 'W' :
580
593
wait_connection_end = 1 ;
0 commit comments