@@ -343,18 +343,16 @@ static const char *ai_name(const struct addrinfo *ai)
343
343
/*
344
344
* Returns a connected socket() fd, or else die()s.
345
345
*/
346
- static int git_tcp_connect_sock (char * host , int flags )
346
+ static int git_tcp_connect_sock (const char * host , const char * port , int flags )
347
347
{
348
348
struct strbuf error_message = STRBUF_INIT ;
349
349
int sockfd = -1 ;
350
- const char * port = STR (DEFAULT_GIT_PORT );
351
350
struct addrinfo hints , * ai0 , * ai ;
352
351
int gai ;
353
352
int cnt = 0 ;
354
353
355
- get_host_and_port (& host , & port );
356
- if (!* port )
357
- port = "<none>" ;
354
+ if (!port )
355
+ port = STR (DEFAULT_GIT_PORT );
358
356
359
357
memset (& hints , 0 , sizeof (hints ));
360
358
if (flags & CONNECT_IPV4 )
@@ -411,19 +409,19 @@ static int git_tcp_connect_sock(char *host, int flags)
411
409
/*
412
410
* Returns a connected socket() fd, or else die()s.
413
411
*/
414
- static int git_tcp_connect_sock (char * host , int flags )
412
+ static int git_tcp_connect_sock (const char * host , const char * port , int flags )
415
413
{
416
414
struct strbuf error_message = STRBUF_INIT ;
417
415
int sockfd = -1 ;
418
- const char * port = STR (DEFAULT_GIT_PORT );
419
416
char * ep ;
420
417
struct hostent * he ;
421
418
struct sockaddr_in sa ;
422
419
char * * ap ;
423
420
unsigned int nport ;
424
421
int cnt ;
425
422
426
- get_host_and_port (& host , & port );
423
+ if (!port )
424
+ port = STR (DEFAULT_GIT_PORT );
427
425
428
426
if (flags & CONNECT_VERBOSE )
429
427
fprintf (stderr , "Looking up %s ... " , host );
@@ -482,9 +480,10 @@ static int git_tcp_connect_sock(char *host, int flags)
482
480
#endif /* NO_IPV6 */
483
481
484
482
485
- static void git_tcp_connect (int fd [2 ], char * host , int flags )
483
+ static void git_tcp_connect (int fd [2 ], const char * host , const char * port ,
484
+ int flags )
486
485
{
487
- int sockfd = git_tcp_connect_sock (host , flags );
486
+ int sockfd = git_tcp_connect_sock (host , port , flags );
488
487
489
488
fd [0 ] = sockfd ;
490
489
fd [1 ] = dup (sockfd );
@@ -550,18 +549,16 @@ static int git_use_proxy(const char *host)
550
549
return (git_proxy_command && * git_proxy_command );
551
550
}
552
551
553
- static struct child_process * git_proxy_connect (int fd [2 ], char * host )
552
+ static struct child_process * git_proxy_connect (int fd [2 ], const char * host ,
553
+ const char * port )
554
554
{
555
- const char * port = STR (DEFAULT_GIT_PORT );
556
555
struct child_process * proxy ;
557
556
558
- get_host_and_port (& host , & port );
559
-
560
557
proxy = xmalloc (sizeof (* proxy ));
561
558
child_process_init (proxy );
562
559
argv_array_push (& proxy -> args , git_proxy_command );
563
560
argv_array_push (& proxy -> args , host );
564
- argv_array_push (& proxy -> args , port );
561
+ argv_array_push (& proxy -> args , port ? port : STR ( DEFAULT_GIT_PORT ) );
565
562
proxy -> in = -1 ;
566
563
proxy -> out = -1 ;
567
564
if (start_command (proxy ))
@@ -591,11 +588,14 @@ static char *get_port(char *host)
591
588
* Extract protocol and relevant parts from the specified connection URL.
592
589
* The caller must free() the returned strings.
593
590
*/
594
- static enum protocol parse_connect_url (const char * url_orig , char * * ret_host ,
591
+ static enum protocol parse_connect_url (const char * url_orig , char * * ret_user ,
592
+ char * * ret_host , char * * ret_port ,
595
593
char * * ret_path )
596
594
{
597
595
char * url ;
598
596
char * host , * path ;
597
+ const char * user = NULL ;
598
+ const char * port = NULL ;
599
599
char * end ;
600
600
int separator = '/' ;
601
601
enum protocol protocol = PROTO_LOCAL ;
@@ -618,10 +618,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
618
618
}
619
619
}
620
620
621
- /*
622
- * Don't do destructive transforms as protocol code does
623
- * '[]' unwrapping in get_host_and_port()
624
- */
621
+ /* '[]' unwrapping is done in get_host_and_port() */
625
622
end = host_end (& host , 0 );
626
623
627
624
if (protocol == PROTO_LOCAL )
@@ -650,14 +647,40 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
650
647
path = xstrdup (path );
651
648
* end = '\0' ;
652
649
650
+ get_host_and_port (& host , & port );
651
+
652
+ if (* host ) {
653
+ /*
654
+ * At this point, the host part may look like user@host:port.
655
+ * As the `user` portion tends to be less strict than
656
+ * `host:port`, we first put it out of the equation: since a
657
+ * hostname cannot contain a '@', we start from the last '@'
658
+ * in the string.
659
+ */
660
+ char * end_user = strrchr (host , '@' );
661
+ if (end_user ) {
662
+ * end_user = '\0' ;
663
+ user = host ;
664
+ host = end_user + 1 ;
665
+ }
666
+ }
667
+ /*
668
+ * get_host_and_port does not return a port in the [host:port]:path
669
+ * case. In that case, it is called with "[host:port]" and returns
670
+ * "host:port" and NULL. To support this undocumented legacy
671
+ * (for ssh only) we still need to split the port.
672
+ */
673
+ if (!port && protocol == PROTO_SSH )
674
+ port = get_port (host );
675
+
676
+ * ret_user = user ? xstrdup (user ) : NULL ;
653
677
* ret_host = xstrdup (host );
678
+ * ret_port = port ? xstrdup (port ) : NULL ;
654
679
* ret_path = path ;
655
680
free (url );
656
681
return protocol ;
657
682
}
658
683
659
- static struct child_process no_fork = CHILD_PROCESS_INIT ;
660
-
661
684
static const char * get_ssh_command (void )
662
685
{
663
686
const char * ssh ;
@@ -671,6 +694,63 @@ static const char *get_ssh_command(void)
671
694
return NULL ;
672
695
}
673
696
697
+ static int prepare_ssh_command (struct argv_array * cmd , const char * user ,
698
+ const char * host , const char * port , int flags )
699
+ {
700
+ const char * ssh ;
701
+ int putty = 0 , tortoiseplink = 0 , use_shell = 1 ;
702
+ transport_check_allowed ("ssh" );
703
+
704
+ ssh = get_ssh_command ();
705
+ if (!ssh ) {
706
+ const char * base ;
707
+ char * ssh_dup ;
708
+
709
+ /*
710
+ * GIT_SSH is the no-shell version of
711
+ * GIT_SSH_COMMAND (and must remain so for
712
+ * historical compatibility).
713
+ */
714
+ use_shell = 0 ;
715
+
716
+ ssh = getenv ("GIT_SSH" );
717
+ if (!ssh )
718
+ ssh = "ssh" ;
719
+
720
+ ssh_dup = xstrdup (ssh );
721
+ base = basename (ssh_dup );
722
+
723
+ tortoiseplink = !strcasecmp (base , "tortoiseplink" ) ||
724
+ !strcasecmp (base , "tortoiseplink.exe" );
725
+ putty = tortoiseplink ||
726
+ !strcasecmp (base , "plink" ) ||
727
+ !strcasecmp (base , "plink.exe" );
728
+
729
+ free (ssh_dup );
730
+ }
731
+
732
+ argv_array_push (cmd , ssh );
733
+ if (flags & CONNECT_IPV4 )
734
+ argv_array_push (cmd , "-4" );
735
+ else if (flags & CONNECT_IPV6 )
736
+ argv_array_push (cmd , "-6" );
737
+ if (tortoiseplink )
738
+ argv_array_push (cmd , "-batch" );
739
+ if (port ) {
740
+ /* P is for PuTTY, p is for OpenSSH */
741
+ argv_array_push (cmd , putty ? "-P" : "-p" );
742
+ argv_array_push (cmd , port );
743
+ }
744
+ if (user )
745
+ argv_array_pushf (cmd , "%s@%s" , user , host );
746
+ else
747
+ argv_array_push (cmd , host );
748
+
749
+ return use_shell ;
750
+ }
751
+
752
+ static struct child_process no_fork = CHILD_PROCESS_INIT ;
753
+
674
754
/*
675
755
* This returns a dummy child_process if the transport protocol does not
676
756
* need fork(2), or a struct child_process object if it does. Once done,
@@ -685,7 +765,7 @@ static const char *get_ssh_command(void)
685
765
struct child_process * git_connect (int fd [2 ], const char * url ,
686
766
const char * prog , int flags )
687
767
{
688
- char * hostandport , * path ;
768
+ char * user , * host , * port , * path ;
689
769
struct child_process * conn = & no_fork ;
690
770
enum protocol protocol ;
691
771
struct strbuf cmd = STRBUF_INIT ;
@@ -695,11 +775,13 @@ struct child_process *git_connect(int fd[2], const char *url,
695
775
*/
696
776
signal (SIGCHLD , SIG_DFL );
697
777
698
- protocol = parse_connect_url (url , & hostandport , & path );
699
- if (( flags & CONNECT_DIAG_URL ) && ( protocol != PROTO_SSH ) ) {
778
+ protocol = parse_connect_url (url , & user , & host , & port , & path );
779
+ if (flags & CONNECT_DIAG_URL ) {
700
780
printf ("Diag: url=%s\n" , url ? url : "NULL" );
701
781
printf ("Diag: protocol=%s\n" , prot_name (protocol ));
702
- printf ("Diag: hostandport=%s\n" , hostandport ? hostandport : "NULL" );
782
+ printf ("Diag: user=%s\n" , user ? user : "NULL" );
783
+ printf ("Diag: host=%s\n" , host ? host : "NULL" );
784
+ printf ("Diag: port=%s\n" , port ? port : "NONE" );
703
785
printf ("Diag: path=%s\n" , path ? path : "NULL" );
704
786
conn = NULL ;
705
787
} else if (protocol == PROTO_GIT ) {
@@ -708,21 +790,38 @@ struct child_process *git_connect(int fd[2], const char *url,
708
790
* connect, unless the user has overridden us in
709
791
* the environment.
710
792
*/
711
- char * target_host = getenv ("GIT_OVERRIDE_VIRTUAL_HOST" );
712
- if (target_host )
713
- target_host = xstrdup (target_host );
714
- else
715
- target_host = xstrdup (hostandport );
793
+ struct strbuf target_host = STRBUF_INIT ;
794
+ struct strbuf virtual_host = STRBUF_INIT ;
795
+ const char * colon = strchr (host , ':' );
796
+ char * override_vhost = getenv ("GIT_OVERRIDE_VIRTUAL_HOST" );
797
+
798
+ if (user )
799
+ die ("user@host is not allowed in git:// urls" );
800
+
801
+ /* If the host contains a colon (ipv6 address), it needs to
802
+ * be enclosed with square brackets. */
803
+ if (colon )
804
+ strbuf_addch (& target_host , '[' );
805
+ strbuf_addstr (& target_host , host );
806
+ if (colon )
807
+ strbuf_addch (& target_host , ']' );
808
+ if (port ) {
809
+ strbuf_addch (& target_host , ':' );
810
+ strbuf_addstr (& target_host , port );
811
+ }
812
+
813
+ strbuf_addstr (& virtual_host , override_vhost ? override_vhost
814
+ : target_host .buf );
716
815
717
816
transport_check_allowed ("git" );
718
817
719
818
/* These underlying connection commands die() if they
720
819
* cannot connect.
721
820
*/
722
- if (git_use_proxy (hostandport ))
723
- conn = git_proxy_connect (fd , hostandport );
821
+ if (git_use_proxy (target_host . buf ))
822
+ conn = git_proxy_connect (fd , host , port );
724
823
else
725
- git_tcp_connect (fd , hostandport , flags );
824
+ git_tcp_connect (fd , host , port , flags );
726
825
/*
727
826
* Separate original protocol components prog and path
728
827
* from extended host header with a NUL byte.
@@ -733,8 +832,9 @@ struct child_process *git_connect(int fd[2], const char *url,
733
832
packet_write (fd [1 ],
734
833
"%s %s%chost=%s%c" ,
735
834
prog , path , 0 ,
736
- target_host , 0 );
737
- free (target_host );
835
+ virtual_host .buf , 0 );
836
+ strbuf_release (& virtual_host );
837
+ strbuf_release (& target_host );
738
838
} else {
739
839
conn = xmalloc (sizeof (* conn ));
740
840
child_process_init (conn );
@@ -745,74 +845,12 @@ struct child_process *git_connect(int fd[2], const char *url,
745
845
746
846
/* remove repo-local variables from the environment */
747
847
conn -> env = local_repo_env ;
748
- conn -> use_shell = 1 ;
749
848
conn -> in = conn -> out = -1 ;
750
849
if (protocol == PROTO_SSH ) {
751
- const char * ssh ;
752
- int putty = 0 , tortoiseplink = 0 ;
753
- char * ssh_host = hostandport ;
754
- const char * port = NULL ;
755
- transport_check_allowed ("ssh" );
756
- get_host_and_port (& ssh_host , & port );
757
-
758
- if (!port )
759
- port = get_port (ssh_host );
760
-
761
- if (flags & CONNECT_DIAG_URL ) {
762
- printf ("Diag: url=%s\n" , url ? url : "NULL" );
763
- printf ("Diag: protocol=%s\n" , prot_name (protocol ));
764
- printf ("Diag: userandhost=%s\n" , ssh_host ? ssh_host : "NULL" );
765
- printf ("Diag: port=%s\n" , port ? port : "NONE" );
766
- printf ("Diag: path=%s\n" , path ? path : "NULL" );
767
-
768
- free (hostandport );
769
- free (path );
770
- free (conn );
771
- return NULL ;
772
- }
773
-
774
- ssh = get_ssh_command ();
775
- if (!ssh ) {
776
- const char * base ;
777
- char * ssh_dup ;
778
-
779
- /*
780
- * GIT_SSH is the no-shell version of
781
- * GIT_SSH_COMMAND (and must remain so for
782
- * historical compatibility).
783
- */
784
- conn -> use_shell = 0 ;
785
-
786
- ssh = getenv ("GIT_SSH" );
787
- if (!ssh )
788
- ssh = "ssh" ;
789
-
790
- ssh_dup = xstrdup (ssh );
791
- base = basename (ssh_dup );
792
-
793
- tortoiseplink = !strcasecmp (base , "tortoiseplink" ) ||
794
- !strcasecmp (base , "tortoiseplink.exe" );
795
- putty = tortoiseplink ||
796
- !strcasecmp (base , "plink" ) ||
797
- !strcasecmp (base , "plink.exe" );
798
-
799
- free (ssh_dup );
800
- }
801
-
802
- argv_array_push (& conn -> args , ssh );
803
- if (flags & CONNECT_IPV4 )
804
- argv_array_push (& conn -> args , "-4" );
805
- else if (flags & CONNECT_IPV6 )
806
- argv_array_push (& conn -> args , "-6" );
807
- if (tortoiseplink )
808
- argv_array_push (& conn -> args , "-batch" );
809
- if (port ) {
810
- /* P is for PuTTY, p is for OpenSSH */
811
- argv_array_push (& conn -> args , putty ? "-P" : "-p" );
812
- argv_array_push (& conn -> args , port );
813
- }
814
- argv_array_push (& conn -> args , ssh_host );
850
+ conn -> use_shell = prepare_ssh_command (
851
+ & conn -> args , user , host , port , flags );
815
852
} else {
853
+ conn -> use_shell = 1 ;
816
854
transport_check_allowed ("file" );
817
855
}
818
856
argv_array_push (& conn -> args , cmd .buf );
@@ -824,7 +862,9 @@ struct child_process *git_connect(int fd[2], const char *url,
824
862
fd [1 ] = conn -> in ; /* write to child's stdin */
825
863
strbuf_release (& cmd );
826
864
}
827
- free (hostandport );
865
+ free (user );
866
+ free (host );
867
+ free (port );
828
868
free (path );
829
869
return conn ;
830
870
}
0 commit comments