@@ -363,18 +363,16 @@ static const char *ai_name(const struct addrinfo *ai)
363
363
/*
364
364
* Returns a connected socket() fd, or else die()s.
365
365
*/
366
- static int git_tcp_connect_sock (char * host , int flags )
366
+ static int git_tcp_connect_sock (const char * host , const char * port , int flags )
367
367
{
368
368
struct strbuf error_message = STRBUF_INIT ;
369
369
int sockfd = -1 ;
370
- const char * port = STR (DEFAULT_GIT_PORT );
371
370
struct addrinfo hints , * ai0 , * ai ;
372
371
int gai ;
373
372
int cnt = 0 ;
374
373
375
- get_host_and_port (& host , & port );
376
- if (!* port )
377
- port = "<none>" ;
374
+ if (!port )
375
+ port = STR (DEFAULT_GIT_PORT );
378
376
379
377
memset (& hints , 0 , sizeof (hints ));
380
378
if (flags & CONNECT_IPV4 )
@@ -431,19 +429,19 @@ static int git_tcp_connect_sock(char *host, int flags)
431
429
/*
432
430
* Returns a connected socket() fd, or else die()s.
433
431
*/
434
- static int git_tcp_connect_sock (char * host , int flags )
432
+ static int git_tcp_connect_sock (const char * host , const char * port , int flags )
435
433
{
436
434
struct strbuf error_message = STRBUF_INIT ;
437
435
int sockfd = -1 ;
438
- const char * port = STR (DEFAULT_GIT_PORT );
439
436
char * ep ;
440
437
struct hostent * he ;
441
438
struct sockaddr_in sa ;
442
439
char * * ap ;
443
440
unsigned int nport ;
444
441
int cnt ;
445
442
446
- get_host_and_port (& host , & port );
443
+ if (!port )
444
+ port = STR (DEFAULT_GIT_PORT );
447
445
448
446
if (flags & CONNECT_VERBOSE )
449
447
fprintf (stderr , "Looking up %s ... " , host );
@@ -502,9 +500,10 @@ static int git_tcp_connect_sock(char *host, int flags)
502
500
#endif /* NO_IPV6 */
503
501
504
502
505
- static void git_tcp_connect (int fd [2 ], char * host , int flags )
503
+ static void git_tcp_connect (int fd [2 ], const char * host , const char * port ,
504
+ int flags )
506
505
{
507
- int sockfd = git_tcp_connect_sock (host , flags );
506
+ int sockfd = git_tcp_connect_sock (host , port , flags );
508
507
509
508
fd [0 ] = sockfd ;
510
509
fd [1 ] = dup (sockfd );
@@ -570,18 +569,16 @@ static int git_use_proxy(const char *host)
570
569
return (git_proxy_command && * git_proxy_command );
571
570
}
572
571
573
- static struct child_process * git_proxy_connect (int fd [2 ], char * host )
572
+ static struct child_process * git_proxy_connect (int fd [2 ], const char * host ,
573
+ const char * port )
574
574
{
575
- const char * port = STR (DEFAULT_GIT_PORT );
576
575
struct child_process * proxy ;
577
576
578
- get_host_and_port (& host , & port );
579
-
580
577
proxy = xmalloc (sizeof (* proxy ));
581
578
child_process_init (proxy );
582
579
argv_array_push (& proxy -> args , git_proxy_command );
583
580
argv_array_push (& proxy -> args , host );
584
- argv_array_push (& proxy -> args , port );
581
+ argv_array_push (& proxy -> args , port ? port : STR ( DEFAULT_GIT_PORT ) );
585
582
proxy -> in = -1 ;
586
583
proxy -> out = -1 ;
587
584
if (start_command (proxy ))
@@ -611,11 +608,14 @@ static char *get_port(char *host)
611
608
* Extract protocol and relevant parts from the specified connection URL.
612
609
* The caller must free() the returned strings.
613
610
*/
614
- static enum protocol parse_connect_url (const char * url_orig , char * * ret_host ,
611
+ static enum protocol parse_connect_url (const char * url_orig , char * * ret_user ,
612
+ char * * ret_host , char * * ret_port ,
615
613
char * * ret_path )
616
614
{
617
615
char * url ;
618
616
char * host , * path ;
617
+ const char * user = NULL ;
618
+ const char * port = NULL ;
619
619
char * end ;
620
620
int separator = '/' ;
621
621
enum protocol protocol = PROTO_LOCAL ;
@@ -638,10 +638,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
638
638
}
639
639
}
640
640
641
- /*
642
- * Don't do destructive transforms as protocol code does
643
- * '[]' unwrapping in get_host_and_port()
644
- */
641
+ /* '[]' unwrapping is done in get_host_and_port() */
645
642
end = host_end (& host , 0 );
646
643
647
644
if (protocol == PROTO_LOCAL )
@@ -670,14 +667,40 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
670
667
path = xstrdup (path );
671
668
* end = '\0' ;
672
669
670
+ get_host_and_port (& host , & port );
671
+
672
+ if (* host ) {
673
+ /*
674
+ * At this point, the host part may look like user@host:port.
675
+ * As the `user` portion tends to be less strict than
676
+ * `host:port`, we first put it out of the equation: since a
677
+ * hostname cannot contain a '@', we start from the last '@'
678
+ * in the string.
679
+ */
680
+ char * end_user = strrchr (host , '@' );
681
+ if (end_user ) {
682
+ * end_user = '\0' ;
683
+ user = host ;
684
+ host = end_user + 1 ;
685
+ }
686
+ }
687
+ /*
688
+ * get_host_and_port does not return a port in the [host:port]:path
689
+ * case. In that case, it is called with "[host:port]" and returns
690
+ * "host:port" and NULL. To support this undocumented legacy
691
+ * (for ssh only) we still need to split the port.
692
+ */
693
+ if (!port && protocol == PROTO_SSH )
694
+ port = get_port (host );
695
+
696
+ * ret_user = user ? xstrdup (user ) : NULL ;
673
697
* ret_host = xstrdup (host );
698
+ * ret_port = port ? xstrdup (port ) : NULL ;
674
699
* ret_path = path ;
675
700
free (url );
676
701
return protocol ;
677
702
}
678
703
679
- static struct child_process no_fork = CHILD_PROCESS_INIT ;
680
-
681
704
static const char * get_ssh_command (void )
682
705
{
683
706
const char * ssh ;
@@ -691,6 +714,63 @@ static const char *get_ssh_command(void)
691
714
return NULL ;
692
715
}
693
716
717
+ static int prepare_ssh_command (struct argv_array * cmd , const char * user ,
718
+ const char * host , const char * port , int flags )
719
+ {
720
+ const char * ssh ;
721
+ int putty = 0 , tortoiseplink = 0 , use_shell = 1 ;
722
+ transport_check_allowed ("ssh" );
723
+
724
+ ssh = get_ssh_command ();
725
+ if (!ssh ) {
726
+ const char * base ;
727
+ char * ssh_dup ;
728
+
729
+ /*
730
+ * GIT_SSH is the no-shell version of
731
+ * GIT_SSH_COMMAND (and must remain so for
732
+ * historical compatibility).
733
+ */
734
+ use_shell = 0 ;
735
+
736
+ ssh = getenv ("GIT_SSH" );
737
+ if (!ssh )
738
+ ssh = "ssh" ;
739
+
740
+ ssh_dup = xstrdup (ssh );
741
+ base = basename (ssh_dup );
742
+
743
+ tortoiseplink = !strcasecmp (base , "tortoiseplink" ) ||
744
+ !strcasecmp (base , "tortoiseplink.exe" );
745
+ putty = tortoiseplink ||
746
+ !strcasecmp (base , "plink" ) ||
747
+ !strcasecmp (base , "plink.exe" );
748
+
749
+ free (ssh_dup );
750
+ }
751
+
752
+ argv_array_push (cmd , ssh );
753
+ if (flags & CONNECT_IPV4 )
754
+ argv_array_push (cmd , "-4" );
755
+ else if (flags & CONNECT_IPV6 )
756
+ argv_array_push (cmd , "-6" );
757
+ if (tortoiseplink )
758
+ argv_array_push (cmd , "-batch" );
759
+ if (port ) {
760
+ /* P is for PuTTY, p is for OpenSSH */
761
+ argv_array_push (cmd , putty ? "-P" : "-p" );
762
+ argv_array_push (cmd , port );
763
+ }
764
+ if (user )
765
+ argv_array_pushf (cmd , "%s@%s" , user , host );
766
+ else
767
+ argv_array_push (cmd , host );
768
+
769
+ return use_shell ;
770
+ }
771
+
772
+ static struct child_process no_fork = CHILD_PROCESS_INIT ;
773
+
694
774
/*
695
775
* This returns a dummy child_process if the transport protocol does not
696
776
* need fork(2), or a struct child_process object if it does. Once done,
@@ -705,7 +785,7 @@ static const char *get_ssh_command(void)
705
785
struct child_process * git_connect (int fd [2 ], const char * url ,
706
786
const char * prog , int flags )
707
787
{
708
- char * hostandport , * path ;
788
+ char * user , * host , * port , * path ;
709
789
struct child_process * conn = & no_fork ;
710
790
enum protocol protocol ;
711
791
struct strbuf cmd = STRBUF_INIT ;
@@ -715,11 +795,13 @@ struct child_process *git_connect(int fd[2], const char *url,
715
795
*/
716
796
signal (SIGCHLD , SIG_DFL );
717
797
718
- protocol = parse_connect_url (url , & hostandport , & path );
719
- if (( flags & CONNECT_DIAG_URL ) && ( protocol != PROTO_SSH ) ) {
798
+ protocol = parse_connect_url (url , & user , & host , & port , & path );
799
+ if (flags & CONNECT_DIAG_URL ) {
720
800
printf ("Diag: url=%s\n" , url ? url : "NULL" );
721
801
printf ("Diag: protocol=%s\n" , prot_name (protocol ));
722
- printf ("Diag: hostandport=%s\n" , hostandport ? hostandport : "NULL" );
802
+ printf ("Diag: user=%s\n" , user ? user : "NULL" );
803
+ printf ("Diag: host=%s\n" , host ? host : "NULL" );
804
+ printf ("Diag: port=%s\n" , port ? port : "NONE" );
723
805
printf ("Diag: path=%s\n" , path ? path : "NULL" );
724
806
conn = NULL ;
725
807
} else if (protocol == PROTO_GIT ) {
@@ -728,21 +810,38 @@ struct child_process *git_connect(int fd[2], const char *url,
728
810
* connect, unless the user has overridden us in
729
811
* the environment.
730
812
*/
731
- char * target_host = getenv ("GIT_OVERRIDE_VIRTUAL_HOST" );
732
- if (target_host )
733
- target_host = xstrdup (target_host );
734
- else
735
- target_host = xstrdup (hostandport );
813
+ struct strbuf target_host = STRBUF_INIT ;
814
+ struct strbuf virtual_host = STRBUF_INIT ;
815
+ const char * colon = strchr (host , ':' );
816
+ char * override_vhost = getenv ("GIT_OVERRIDE_VIRTUAL_HOST" );
817
+
818
+ if (user )
819
+ die ("user@host is not allowed in git:// urls" );
820
+
821
+ /* If the host contains a colon (ipv6 address), it needs to
822
+ * be enclosed with square brackets. */
823
+ if (colon )
824
+ strbuf_addch (& target_host , '[' );
825
+ strbuf_addstr (& target_host , host );
826
+ if (colon )
827
+ strbuf_addch (& target_host , ']' );
828
+ if (port ) {
829
+ strbuf_addch (& target_host , ':' );
830
+ strbuf_addstr (& target_host , port );
831
+ }
832
+
833
+ strbuf_addstr (& virtual_host , override_vhost ? override_vhost
834
+ : target_host .buf );
736
835
737
836
transport_check_allowed ("git" );
738
837
739
838
/* These underlying connection commands die() if they
740
839
* cannot connect.
741
840
*/
742
- if (git_use_proxy (hostandport ))
743
- conn = git_proxy_connect (fd , hostandport );
841
+ if (git_use_proxy (target_host . buf ))
842
+ conn = git_proxy_connect (fd , host , port );
744
843
else
745
- git_tcp_connect (fd , hostandport , flags );
844
+ git_tcp_connect (fd , host , port , flags );
746
845
/*
747
846
* Separate original protocol components prog and path
748
847
* from extended host header with a NUL byte.
@@ -753,8 +852,9 @@ struct child_process *git_connect(int fd[2], const char *url,
753
852
packet_write_fmt (fd [1 ],
754
853
"%s %s%chost=%s%c" ,
755
854
prog , path , 0 ,
756
- target_host , 0 );
757
- free (target_host );
855
+ virtual_host .buf , 0 );
856
+ strbuf_release (& virtual_host );
857
+ strbuf_release (& target_host );
758
858
} else {
759
859
conn = xmalloc (sizeof (* conn ));
760
860
child_process_init (conn );
@@ -765,74 +865,12 @@ struct child_process *git_connect(int fd[2], const char *url,
765
865
766
866
/* remove repo-local variables from the environment */
767
867
conn -> env = local_repo_env ;
768
- conn -> use_shell = 1 ;
769
868
conn -> in = conn -> out = -1 ;
770
869
if (protocol == PROTO_SSH ) {
771
- const char * ssh ;
772
- int putty = 0 , tortoiseplink = 0 ;
773
- char * ssh_host = hostandport ;
774
- const char * port = NULL ;
775
- transport_check_allowed ("ssh" );
776
- get_host_and_port (& ssh_host , & port );
777
-
778
- if (!port )
779
- port = get_port (ssh_host );
780
-
781
- if (flags & CONNECT_DIAG_URL ) {
782
- printf ("Diag: url=%s\n" , url ? url : "NULL" );
783
- printf ("Diag: protocol=%s\n" , prot_name (protocol ));
784
- printf ("Diag: userandhost=%s\n" , ssh_host ? ssh_host : "NULL" );
785
- printf ("Diag: port=%s\n" , port ? port : "NONE" );
786
- printf ("Diag: path=%s\n" , path ? path : "NULL" );
787
-
788
- free (hostandport );
789
- free (path );
790
- free (conn );
791
- return NULL ;
792
- }
793
-
794
- ssh = get_ssh_command ();
795
- if (!ssh ) {
796
- const char * base ;
797
- char * ssh_dup ;
798
-
799
- /*
800
- * GIT_SSH is the no-shell version of
801
- * GIT_SSH_COMMAND (and must remain so for
802
- * historical compatibility).
803
- */
804
- conn -> use_shell = 0 ;
805
-
806
- ssh = getenv ("GIT_SSH" );
807
- if (!ssh )
808
- ssh = "ssh" ;
809
-
810
- ssh_dup = xstrdup (ssh );
811
- base = basename (ssh_dup );
812
-
813
- tortoiseplink = !strcasecmp (base , "tortoiseplink" ) ||
814
- !strcasecmp (base , "tortoiseplink.exe" );
815
- putty = tortoiseplink ||
816
- !strcasecmp (base , "plink" ) ||
817
- !strcasecmp (base , "plink.exe" );
818
-
819
- free (ssh_dup );
820
- }
821
-
822
- argv_array_push (& conn -> args , ssh );
823
- if (flags & CONNECT_IPV4 )
824
- argv_array_push (& conn -> args , "-4" );
825
- else if (flags & CONNECT_IPV6 )
826
- argv_array_push (& conn -> args , "-6" );
827
- if (tortoiseplink )
828
- argv_array_push (& conn -> args , "-batch" );
829
- if (port ) {
830
- /* P is for PuTTY, p is for OpenSSH */
831
- argv_array_push (& conn -> args , putty ? "-P" : "-p" );
832
- argv_array_push (& conn -> args , port );
833
- }
834
- argv_array_push (& conn -> args , ssh_host );
870
+ conn -> use_shell = prepare_ssh_command (
871
+ & conn -> args , user , host , port , flags );
835
872
} else {
873
+ conn -> use_shell = 1 ;
836
874
transport_check_allowed ("file" );
837
875
}
838
876
argv_array_push (& conn -> args , cmd .buf );
@@ -844,7 +882,9 @@ struct child_process *git_connect(int fd[2], const char *url,
844
882
fd [1 ] = conn -> in ; /* write to child's stdin */
845
883
strbuf_release (& cmd );
846
884
}
847
- free (hostandport );
885
+ free (user );
886
+ free (host );
887
+ free (port );
848
888
free (path );
849
889
return conn ;
850
890
}
0 commit comments