@@ -556,62 +556,88 @@ void loadidentityfile(const char* filename, int warnfail) {
556556
557557/* Fill out -i, -y, -W options that make sense for all
558558 * the intermediate processes */
559- static char * multihop_passthrough_args (void ) {
560- char * args = NULL ;
561- unsigned int len , total ;
559+ static char * * multihop_args (const char * argv0 , const char * prior_hops ) {
560+ /* null terminated array */
561+ char * * args = NULL ;
562+ size_t max_args = 14 , pos = 0 , len ;
562563#if DROPBEAR_CLI_PUBKEY_AUTH
563564 m_list_elem * iter ;
564565#endif
565- /* Sufficient space for non-string args */
566- len = 100 ;
567566
568- /* String arguments have arbitrary length, so determine space required */
569- if (cli_opts .proxycmd ) {
570- len += strlen (cli_opts .proxycmd );
571- }
572567#if DROPBEAR_CLI_PUBKEY_AUTH
573568 for (iter = cli_opts .privkeys -> first ; iter ; iter = iter -> next )
574569 {
575- sign_key * key = ( sign_key * ) iter -> item ;
576- len += 4 + strlen ( key -> filename ) ;
570+ /* "-i file" for each */
571+ max_args += 2 ;
577572 }
578573#endif
579574
580- args = m_malloc (len );
581- total = 0 ;
575+ args = m_malloc (sizeof ( char * ) * max_args );
576+ pos = 0 ;
582577
583- /* Create new argument string */
578+ args [pos ] = m_strdup (argv0 );
579+ pos ++ ;
584580
585581 if (cli_opts .quiet ) {
586- total += m_snprintf (args + total , len - total , "-q " );
582+ args [pos ] = m_strdup ("-q" );
583+ pos ++ ;
587584 }
588585
589586 if (cli_opts .no_hostkey_check ) {
590- total += m_snprintf (args + total , len - total , "-y -y " );
587+ args [pos ] = m_strdup ("-y" );
588+ pos ++ ;
589+ args [pos ] = m_strdup ("-y" );
590+ pos ++ ;
591591 } else if (cli_opts .always_accept_key ) {
592- total += m_snprintf (args + total , len - total , "-y " );
592+ args [pos ] = m_strdup ("-y" );
593+ pos ++ ;
593594 }
594595
595596 if (cli_opts .batch_mode ) {
596- total += m_snprintf (args + total , len - total , "-o BatchMode=yes " );
597+ args [pos ] = m_strdup ("-o" );
598+ pos ++ ;
599+ args [pos ] = m_strdup ("BatchMode=yes" );
600+ pos ++ ;
597601 }
598602
599603 if (cli_opts .proxycmd ) {
600- total += m_snprintf (args + total , len - total , "-J '%s' " , cli_opts .proxycmd );
604+ args [pos ] = m_strdup ("-J" );
605+ pos ++ ;
606+ args [pos ] = m_strdup (cli_opts .proxycmd );
607+ pos ++ ;
601608 }
602609
603610 if (opts .recv_window != DEFAULT_RECV_WINDOW ) {
604- total += m_snprintf (args + total , len - total , "-W %u " , opts .recv_window );
611+ args [pos ] = m_strdup ("-W" );
612+ pos ++ ;
613+ args [pos ] = m_malloc (11 );
614+ m_snprintf (args [pos ], 11 , "%u" , opts .recv_window );
615+ pos ++ ;
605616 }
606617
607618#if DROPBEAR_CLI_PUBKEY_AUTH
608619 for (iter = cli_opts .privkeys -> first ; iter ; iter = iter -> next )
609620 {
610621 sign_key * key = (sign_key * )iter -> item ;
611- total += m_snprintf (args + total , len - total , "-i %s " , key -> filename );
622+ args [pos ] = m_strdup ("-i" );
623+ pos ++ ;
624+ args [pos ] = m_strdup (key -> filename );
625+ pos ++ ;
612626 }
613627#endif /* DROPBEAR_CLI_PUBKEY_AUTH */
614628
629+ /* last hop */
630+ args [pos ] = m_strdup ("-B" );
631+ pos ++ ;
632+ len = strlen (cli_opts .remotehost ) + strlen (cli_opts .remoteport ) + 2 ;
633+ args [pos ] = m_malloc (len );
634+ snprintf (args [pos ], len , "%s:%s" , cli_opts .remotehost , cli_opts .remoteport );
635+ pos ++ ;
636+
637+ /* hostnames of prior hops */
638+ args [pos ] = m_strdup (prior_hops );
639+ pos ++ ;
640+
615641 return args ;
616642}
617643
@@ -626,15 +652,15 @@ static char* multihop_passthrough_args(void) {
626652 * etc for as many hosts as we want.
627653 *
628654 * Note that "-J" arguments aren't actually used, instead
629- * below sets cli_opts.proxycmd directly.
655+ * below sets cli_opts.proxyexec directly.
630656 *
631657 * Ports for hosts can be specified as host/port.
632658 */
633659static void parse_multihop_hostname (const char * orighostarg , const char * argv0 ) {
634660 char * userhostarg = NULL ;
635661 char * hostbuf = NULL ;
636662 char * last_hop = NULL ;
637- char * remainder = NULL ;
663+ char * prior_hops = NULL ;
638664
639665 /* both scp and rsync parse a user@host argument
640666 * and turn it into "-l user host". This breaks
@@ -652,39 +678,37 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0)
652678 }
653679 userhostarg = hostbuf ;
654680
681+ /* Split off any last hostname and use that as remotehost/remoteport.
682+ * That is used for authorized_keys checking etc */
655683 last_hop = strrchr (userhostarg , ',' );
656684 if (last_hop ) {
657685 if (last_hop == userhostarg ) {
658686 dropbear_exit ("Bad multi-hop hostnames" );
659687 }
660688 * last_hop = '\0' ;
661689 last_hop ++ ;
662- remainder = userhostarg ;
690+ prior_hops = userhostarg ;
663691 userhostarg = last_hop ;
664692 }
665693
694+ /* Update cli_opts.remotehost and cli_opts.remoteport */
666695 parse_hostname (userhostarg );
667696
668- if (last_hop ) {
669- /* Set up the proxycmd */
670- unsigned int cmd_len = 0 ;
671- char * passthrough_args = multihop_passthrough_args ();
672- cmd_len = strlen (argv0 ) + strlen (remainder )
673- + strlen (cli_opts .remotehost ) + strlen (cli_opts .remoteport )
674- + strlen (passthrough_args )
675- + 30 ;
676- /* replace proxycmd. old -J arguments have been copied
677- to passthrough_args */
678- cli_opts .proxycmd = m_realloc (cli_opts .proxycmd , cmd_len );
679- m_snprintf (cli_opts .proxycmd , cmd_len , "%s -B %s:%s %s %s" ,
680- argv0 , cli_opts .remotehost , cli_opts .remoteport ,
681- passthrough_args , remainder );
697+ /* Construct any multihop proxy command. Use proxyexec to
698+ * avoid worrying about shell escaping. */
699+ if (prior_hops ) {
700+ cli_opts .proxyexec = multihop_args (argv0 , prior_hops );
701+ /* Any -J argument has been copied to proxyexec */
702+ if (cli_opts .proxycmd ) {
703+ m_free (cli_opts .proxycmd );
704+ }
705+
682706#ifndef DISABLE_ZLIB
683- /* The stream will be incompressible since it's encrypted. */
707+ /* This outer stream will be incompressible since it's encrypted. */
684708 opts .allow_compress = 0 ;
685709#endif
686- m_free (passthrough_args );
687710 }
711+
688712 m_free (hostbuf );
689713}
690714#endif /* DROPBEAR_CLI_MULTIHOP */
0 commit comments