[PATCH v5 0/9] connect: various cleanups

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 0/9] connect: various cleanups

Mike Hommey-3
I removed the two controvertial patches, and applied the various suggestions
from the last cycle.

Mike Hommey (9):
  connect: call get_host_and_port() earlier
  connect: only match the host with core.gitProxy
  connect: fill the host header in the git protocol with the host and
    port variables
  connect: make parse_connect_url() return separated host and port
  connect: group CONNECT_DIAG_URL handling code
  connect: make parse_connect_url() return the user part of the url as a
    separate value
  connect: change the --diag-url output to separate user and host
  connect: actively reject git:// urls with a user part
  connect: move ssh command line preparation to a separate function

 connect.c             | 222 ++++++++++++++++++++++++++++----------------------
 t/t5500-fetch-pack.sh |  42 +++++++---
 2 files changed, 157 insertions(+), 107 deletions(-)

--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 1/9] connect: call get_host_and_port() earlier

Mike Hommey-3
Currently, get_host_and_port() is called in git_connect() for the ssh
protocol, and in git_tcp_connect_sock() for the git protocol. Instead
of doing this, just call it from a single place, right after
parse_connect_url(), and pass the host and port separately to
git_*_connect() functions.

We however preserve hostandport, at least for now.

Note that in git_tcp_connect_sock, the port was set to "<none>" in a
case that never can happen, so that code path was removed.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 47 +++++++++++++++++++++++------------------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/connect.c b/connect.c
index c53f3f1..d3448c2 100644
--- a/connect.c
+++ b/connect.c
@@ -343,18 +343,16 @@ static const char *ai_name(const struct addrinfo *ai)
 /*
  * Returns a connected socket() fd, or else die()s.
  */
-static int git_tcp_connect_sock(char *host, int flags)
+static int git_tcp_connect_sock(const char *host, const char *port, int flags)
 {
  struct strbuf error_message = STRBUF_INIT;
  int sockfd = -1;
- const char *port = STR(DEFAULT_GIT_PORT);
  struct addrinfo hints, *ai0, *ai;
  int gai;
  int cnt = 0;
 
- get_host_and_port(&host, &port);
- if (!*port)
- port = "<none>";
+ if (!port)
+ port = STR(DEFAULT_GIT_PORT);
 
  memset(&hints, 0, sizeof(hints));
  if (flags & CONNECT_IPV4)
@@ -411,11 +409,10 @@ static int git_tcp_connect_sock(char *host, int flags)
 /*
  * Returns a connected socket() fd, or else die()s.
  */
-static int git_tcp_connect_sock(char *host, int flags)
+static int git_tcp_connect_sock(const char *host, const char *port, int flags)
 {
  struct strbuf error_message = STRBUF_INIT;
  int sockfd = -1;
- const char *port = STR(DEFAULT_GIT_PORT);
  char *ep;
  struct hostent *he;
  struct sockaddr_in sa;
@@ -423,7 +420,8 @@ static int git_tcp_connect_sock(char *host, int flags)
  unsigned int nport;
  int cnt;
 
- get_host_and_port(&host, &port);
+ if (!port)
+ port = STR(DEFAULT_GIT_PORT);
 
  if (flags & CONNECT_VERBOSE)
  fprintf(stderr, "Looking up %s ... ", host);
@@ -482,9 +480,10 @@ static int git_tcp_connect_sock(char *host, int flags)
 #endif /* NO_IPV6 */
 
 
-static void git_tcp_connect(int fd[2], char *host, int flags)
+static void git_tcp_connect(int fd[2], const char *host, const char *port,
+    int flags)
 {
- int sockfd = git_tcp_connect_sock(host, flags);
+ int sockfd = git_tcp_connect_sock(host, port, flags);
 
  fd[0] = sockfd;
  fd[1] = dup(sockfd);
@@ -550,18 +549,16 @@ static int git_use_proxy(const char *host)
  return (git_proxy_command && *git_proxy_command);
 }
 
-static struct child_process *git_proxy_connect(int fd[2], char *host)
+static struct child_process *git_proxy_connect(int fd[2], const char *host,
+       const char *port)
 {
- const char *port = STR(DEFAULT_GIT_PORT);
  struct child_process *proxy;
 
- get_host_and_port(&host, &port);
-
  proxy = xmalloc(sizeof(*proxy));
  child_process_init(proxy);
  argv_array_push(&proxy->args, git_proxy_command);
  argv_array_push(&proxy->args, host);
- argv_array_push(&proxy->args, port);
+ argv_array_push(&proxy->args, port ? port : STR(DEFAULT_GIT_PORT));
  proxy->in = -1;
  proxy->out = -1;
  if (start_command(proxy))
@@ -672,7 +669,8 @@ static struct child_process no_fork = CHILD_PROCESS_INIT;
 struct child_process *git_connect(int fd[2], const char *url,
   const char *prog, int flags)
 {
- char *hostandport, *path;
+ char *hostandport, *path, *host;
+ const char *port = NULL;
  struct child_process *conn = &no_fork;
  enum protocol protocol;
  struct strbuf cmd = STRBUF_INIT;
@@ -683,6 +681,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  signal(SIGCHLD, SIG_DFL);
 
  protocol = parse_connect_url(url, &hostandport, &path);
+ host = xstrdup(hostandport);
+ get_host_and_port(&host, &port);
  if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
@@ -707,9 +707,9 @@ struct child_process *git_connect(int fd[2], const char *url,
  * cannot connect.
  */
  if (git_use_proxy(hostandport))
- conn = git_proxy_connect(fd, hostandport);
+ conn = git_proxy_connect(fd, host, port);
  else
- git_tcp_connect(fd, hostandport, flags);
+ git_tcp_connect(fd, host, port, flags);
  /*
  * Separate original protocol components prog and path
  * from extended host header with a NUL byte.
@@ -737,22 +737,20 @@ struct child_process *git_connect(int fd[2], const char *url,
  if (protocol == PROTO_SSH) {
  const char *ssh;
  int putty = 0, tortoiseplink = 0;
- char *ssh_host = hostandport;
- const char *port = NULL;
  transport_check_allowed("ssh");
- get_host_and_port(&ssh_host, &port);
 
  if (!port)
- port = get_port(ssh_host);
+ port = get_port(host);
 
  if (flags & CONNECT_DIAG_URL) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
- printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
+ printf("Diag: userandhost=%s\n", host ? host : "NULL");
  printf("Diag: port=%s\n", port ? port : "NONE");
  printf("Diag: path=%s\n", path ? path : "NULL");
 
  free(hostandport);
+ free(host);
  free(path);
  free(conn);
  return NULL;
@@ -798,7 +796,7 @@ struct child_process *git_connect(int fd[2], const char *url,
  argv_array_push(&conn->args, putty ? "-P" : "-p");
  argv_array_push(&conn->args, port);
  }
- argv_array_push(&conn->args, ssh_host);
+ argv_array_push(&conn->args, host);
  } else {
  transport_check_allowed("file");
  }
@@ -812,6 +810,7 @@ struct child_process *git_connect(int fd[2], const char *url,
  strbuf_release(&cmd);
  }
  free(hostandport);
+ free(host);
  free(path);
  return conn;
 }
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 2/9] connect: only match the host with core.gitProxy

Mike Hommey-3
In reply to this post by Mike Hommey-3
Currently, core.gitProxy doesn't actually match purely on domain names
as documented: it also matches ports.

So a core.gitProxy value like "script for kernel.org" doesn't make the
script called for an url like git://kernel.org:port/path, while it is
called for git://kernel.org/path.

This per-port behavior seems like an oversight rather than a deliberate
choice, so, make git://kernel.org:port/path call the gitProxy script in
the case described above.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/connect.c b/connect.c
index d3448c2..2a08318 100644
--- a/connect.c
+++ b/connect.c
@@ -706,7 +706,7 @@ struct child_process *git_connect(int fd[2], const char *url,
  /* These underlying connection commands die() if they
  * cannot connect.
  */
- if (git_use_proxy(hostandport))
+ if (git_use_proxy(host))
  conn = git_proxy_connect(fd, host, port);
  else
  git_tcp_connect(fd, host, port, flags);
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 3/9] connect: fill the host header in the git protocol with the host and port variables

Mike Hommey-3
In reply to this post by Mike Hommey-3
The last use of the hostandport variable, besides being strdup'ed before
being split into host and port, is to fill the host header in the git
protocol.

Instead of relying on parse_connect_url() to return a host:port string
that makes sense there, construct one from the host and port variables.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/connect.c b/connect.c
index 2a08318..ed1a00d 100644
--- a/connect.c
+++ b/connect.c
@@ -695,11 +695,24 @@ struct child_process *git_connect(int fd[2], const char *url,
  * connect, unless the user has overridden us in
  * the environment.
  */
- char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
- if (target_host)
- target_host = xstrdup(target_host);
- else
- target_host = xstrdup(hostandport);
+ struct strbuf target_host = STRBUF_INIT;
+ char *override_vhost = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
+ if (override_vhost)
+ strbuf_addstr(&target_host, override_vhost);
+ else {
+ /* If the host contains a colon (ipv6 address), it
+ * needs to be enclosed with square brackets. */
+ const char *colon = strchr(host, ':');
+ if (colon)
+ strbuf_addch(&target_host, '[');
+ strbuf_addstr(&target_host, host);
+ if (colon)
+ strbuf_addch(&target_host, ']');
+ if (port) {
+ strbuf_addch(&target_host, ':');
+ strbuf_addstr(&target_host, port);
+ }
+ }
 
  transport_check_allowed("git");
 
@@ -720,8 +733,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  packet_write(fd[1],
      "%s %s%chost=%s%c",
      prog, path, 0,
-     target_host, 0);
- free(target_host);
+     target_host.buf, 0);
+ strbuf_release(&target_host);
  } else {
  conn = xmalloc(sizeof(*conn));
  child_process_init(conn);
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 4/9] connect: make parse_connect_url() return separated host and port

Mike Hommey-3
In reply to this post by Mike Hommey-3
Now that nothing besides CONNECT_DIAG_URL is using hostandport, we can
have parse_connect_url() itself do the host and port splitting.

This still leaves "user@" part of the host, if there is one, which will
be addressed in a subsequent change. This however does add /some/
handling of the "user@" part of the host, in order to pick the port
properly.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c             | 30 ++++++++++++++++++------------
 t/t5500-fetch-pack.sh | 32 +++++++++++++++++++++-----------
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/connect.c b/connect.c
index ed1a00d..3428149 100644
--- a/connect.c
+++ b/connect.c
@@ -589,10 +589,11 @@ static char *get_port(char *host)
  * The caller must free() the returned strings.
  */
 static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
-       char **ret_path)
+       char **ret_port, char **ret_path)
 {
  char *url;
  char *host, *path;
+ const char *port = NULL;
  char *end;
  int separator = '/';
  enum protocol protocol = PROTO_LOCAL;
@@ -647,7 +648,17 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
  path = xstrdup(path);
  *end = '\0';
 
+ get_host_and_port(&host, &port);
+
+ if (*host && !port) {
+ /* The host might contain a user:password string, ignore it
+ * when searching for the port again */
+ char *end_user = strrchr(host, '@');
+ port = get_port(end_user ? end_user : host);
+ }
+
  *ret_host = xstrdup(host);
+ *ret_port = port ? xstrdup(port) : NULL;
  *ret_path = path;
  free(url);
  return protocol;
@@ -669,8 +680,7 @@ static struct child_process no_fork = CHILD_PROCESS_INIT;
 struct child_process *git_connect(int fd[2], const char *url,
   const char *prog, int flags)
 {
- char *hostandport, *path, *host;
- const char *port = NULL;
+ char *host, *port, *path;
  struct child_process *conn = &no_fork;
  enum protocol protocol;
  struct strbuf cmd = STRBUF_INIT;
@@ -680,13 +690,12 @@ struct child_process *git_connect(int fd[2], const char *url,
  */
  signal(SIGCHLD, SIG_DFL);
 
- protocol = parse_connect_url(url, &hostandport, &path);
- host = xstrdup(hostandport);
- get_host_and_port(&host, &port);
+ protocol = parse_connect_url(url, &host, &port, &path);
  if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
- printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
+ printf("Diag: userandhost=%s\n", host ? host : "NULL");
+ printf("Diag: port=%s\n", port ? port : "NONE");
  printf("Diag: path=%s\n", path ? path : "NULL");
  conn = NULL;
  } else if (protocol == PROTO_GIT) {
@@ -752,9 +761,6 @@ struct child_process *git_connect(int fd[2], const char *url,
  int putty = 0, tortoiseplink = 0;
  transport_check_allowed("ssh");
 
- if (!port)
- port = get_port(host);
-
  if (flags & CONNECT_DIAG_URL) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
@@ -762,8 +768,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  printf("Diag: port=%s\n", port ? port : "NONE");
  printf("Diag: path=%s\n", path ? path : "NULL");
 
- free(hostandport);
  free(host);
+ free(port);
  free(path);
  free(conn);
  return NULL;
@@ -822,8 +828,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  fd[1] = conn->in;  /* write to child's stdin */
  strbuf_release(&cmd);
  }
- free(hostandport);
  free(host);
+ free(port);
  free(path);
  return conn;
 }
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 91a69fc..9acba2b 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -553,7 +553,7 @@ check_prot_path () {
  Diag: protocol=$2
  Diag: path=$3
  EOF
- git fetch-pack --diag-url "$1" | grep -v hostandport= >actual &&
+ git fetch-pack --diag-url "$1" | grep -v host= | grep -v port= >actual &&
  test_cmp expected actual
 }
 
@@ -562,22 +562,17 @@ check_prot_host_port_path () {
  case "$2" in
  *ssh*)
  pp=ssh
- uah=userandhost
- ehost=$(echo $3 | tr -d "[]")
- diagport="Diag: port=$4"
  ;;
  *)
- pp=$p
- uah=hostandport
- ehost=$(echo $3$4 | sed -e "s/22$/:22/" -e "s/NONE//")
- diagport=""
+ pp=$2
  ;;
  esac
+ ehost=$(echo $3 | tr -d "[]")
  cat >exp <<-EOF &&
  Diag: url=$1
  Diag: protocol=$pp
- Diag: $uah=$ehost
- $diagport
+ Diag: userandhost=$ehost
+ Diag: port=$4
  Diag: path=$5
  EOF
  grep -v "^$" exp >expected
@@ -585,7 +580,7 @@ check_prot_host_port_path () {
  test_cmp expected actual
 }
 
-for r in repo re:po re/po
+for r in repo re:po re/po re@po
 do
  # git or ssh with scheme
  for p in "ssh+git" "git+ssh" git ssh
@@ -608,6 +603,9 @@ do
  test_expect_success "fetch-pack --diag-url $p://$h:22/$r" '
  check_prot_host_port_path $p://$h:22/$r $p "$h" 22 "/$r"
  '
+ test_expect_success "fetch-pack --diag-url $p://$h:22/$r" '
+ check_prot_host_port_path $p://$h:22/$r $p "$h" 22 "/$r"
+ '
  done
  done
  # file with scheme
@@ -644,6 +642,18 @@ do
  check_prot_host_port_path $h:/~$r $p "$h" NONE "~$r"
  '
  done
+ #ssh without scheme with port
+ p=ssh
+ for h in host user@host
+ do
+ test_expect_success "fetch-pack --diag-url [$h:22]:$r" '
+ check_prot_host_port_path [$h:22]:$r $p $h 22 "$r"
+ '
+ # Do "/~" -> "~" conversion
+ test_expect_success "fetch-pack --diag-url [$h:22]:/~$r" '
+ check_prot_host_port_path [$h:22]:/~$r $p $h 22 "~$r"
+ '
+ done
 done
 
 test_expect_success MINGW 'fetch-pack --diag-url file://c:/repo' '
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 5/9] connect: group CONNECT_DIAG_URL handling code

Mike Hommey-3
In reply to this post by Mike Hommey-3
Previous changes made both branches handling CONNECT_DIAG_URL identical.
We can now remove one of those branches and have CONNECT_DIAG_URL be
handled in one place.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/connect.c b/connect.c
index 3428149..8813f90 100644
--- a/connect.c
+++ b/connect.c
@@ -691,7 +691,7 @@ struct child_process *git_connect(int fd[2], const char *url,
  signal(SIGCHLD, SIG_DFL);
 
  protocol = parse_connect_url(url, &host, &port, &path);
- if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
+ if (flags & CONNECT_DIAG_URL) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
  printf("Diag: userandhost=%s\n", host ? host : "NULL");
@@ -761,20 +761,6 @@ struct child_process *git_connect(int fd[2], const char *url,
  int putty = 0, tortoiseplink = 0;
  transport_check_allowed("ssh");
 
- if (flags & CONNECT_DIAG_URL) {
- printf("Diag: url=%s\n", url ? url : "NULL");
- printf("Diag: protocol=%s\n", prot_name(protocol));
- printf("Diag: userandhost=%s\n", host ? host : "NULL");
- printf("Diag: port=%s\n", port ? port : "NONE");
- printf("Diag: path=%s\n", path ? path : "NULL");
-
- free(host);
- free(port);
- free(path);
- free(conn);
- return NULL;
- }
-
  ssh = getenv("GIT_SSH_COMMAND");
  if (!ssh) {
  const char *base;
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 6/9] connect: make parse_connect_url() return the user part of the url as a separate value

Mike Hommey-3
In reply to this post by Mike Hommey-3
Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/connect.c b/connect.c
index 8813f90..c40ff35 100644
--- a/connect.c
+++ b/connect.c
@@ -588,11 +588,13 @@ static char *get_port(char *host)
  * Extract protocol and relevant parts from the specified connection URL.
  * The caller must free() the returned strings.
  */
-static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
-       char **ret_port, char **ret_path)
+static enum protocol parse_connect_url(const char *url_orig, char **ret_user,
+       char **ret_host, char **ret_port,
+       char **ret_path)
 {
  char *url;
  char *host, *path;
+ const char *user = NULL;
  const char *port = NULL;
  char *end;
  int separator = '/';
@@ -650,13 +652,20 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
 
  get_host_and_port(&host, &port);
 
- if (*host && !port) {
+ if (*host) {
  /* The host might contain a user:password string, ignore it
  * when searching for the port again */
  char *end_user = strrchr(host, '@');
- port = get_port(end_user ? end_user : host);
+ if (end_user) {
+ *end_user = '\0';
+ user = host;
+ host = end_user + 1;
+ }
  }
+ if (!port)
+ port = get_port(host);
 
+ *ret_user = user ? xstrdup(user) : NULL;
  *ret_host = xstrdup(host);
  *ret_port = port ? xstrdup(port) : NULL;
  *ret_path = path;
@@ -680,7 +689,7 @@ static struct child_process no_fork = CHILD_PROCESS_INIT;
 struct child_process *git_connect(int fd[2], const char *url,
   const char *prog, int flags)
 {
- char *host, *port, *path;
+ char *user, *host, *port, *path;
  struct child_process *conn = &no_fork;
  enum protocol protocol;
  struct strbuf cmd = STRBUF_INIT;
@@ -690,11 +699,14 @@ struct child_process *git_connect(int fd[2], const char *url,
  */
  signal(SIGCHLD, SIG_DFL);
 
- protocol = parse_connect_url(url, &host, &port, &path);
+ protocol = parse_connect_url(url, &user, &host, &port, &path);
  if (flags & CONNECT_DIAG_URL) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
- printf("Diag: userandhost=%s\n", host ? host : "NULL");
+ if (user)
+ printf("Diag: userandhost=%s@%s\n", user, host);
+ else
+ printf("Diag: userandhost=%s\n", host ? host : "NULL");
  printf("Diag: port=%s\n", port ? port : "NONE");
  printf("Diag: path=%s\n", path ? path : "NULL");
  conn = NULL;
@@ -801,7 +813,11 @@ struct child_process *git_connect(int fd[2], const char *url,
  argv_array_push(&conn->args, putty ? "-P" : "-p");
  argv_array_push(&conn->args, port);
  }
- argv_array_push(&conn->args, host);
+ if (user)
+ argv_array_pushf(&conn->args, "%s@%s",
+                 user, host);
+ else
+ argv_array_push(&conn->args, host);
  } else {
  transport_check_allowed("file");
  }
@@ -814,6 +830,7 @@ struct child_process *git_connect(int fd[2], const char *url,
  fd[1] = conn->in;  /* write to child's stdin */
  strbuf_release(&cmd);
  }
+ free(user);
  free(host);
  free(port);
  free(path);
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 7/9] connect: change the --diag-url output to separate user and host

Mike Hommey-3
In reply to this post by Mike Hommey-3
Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c             |  6 ++----
 t/t5500-fetch-pack.sh | 14 ++++++++++++--
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/connect.c b/connect.c
index c40ff35..df15ff3 100644
--- a/connect.c
+++ b/connect.c
@@ -703,10 +703,8 @@ struct child_process *git_connect(int fd[2], const char *url,
  if (flags & CONNECT_DIAG_URL) {
  printf("Diag: url=%s\n", url ? url : "NULL");
  printf("Diag: protocol=%s\n", prot_name(protocol));
- if (user)
- printf("Diag: userandhost=%s@%s\n", user, host);
- else
- printf("Diag: userandhost=%s\n", host ? host : "NULL");
+ printf("Diag: user=%s\n", user ? user : "NULL");
+ printf("Diag: host=%s\n", host ? host : "NULL");
  printf("Diag: port=%s\n", port ? port : "NONE");
  printf("Diag: path=%s\n", path ? path : "NULL");
  conn = NULL;
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 9acba2b..2d9c4be 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -553,7 +553,7 @@ check_prot_path () {
  Diag: protocol=$2
  Diag: path=$3
  EOF
- git fetch-pack --diag-url "$1" | grep -v host= | grep -v port= >actual &&
+ git fetch-pack --diag-url "$1" | egrep -v "(user|host|port)=" >actual &&
  test_cmp expected actual
 }
 
@@ -568,10 +568,20 @@ check_prot_host_port_path () {
  ;;
  esac
  ehost=$(echo $3 | tr -d "[]")
+ case "$ehost" in
+ *@*)
+ user=${ehost%@*}
+ ehost=${ehost#$user@}
+ ;;
+ *)
+ user=NULL
+ ;;
+ esac
  cat >exp <<-EOF &&
  Diag: url=$1
  Diag: protocol=$pp
- Diag: userandhost=$ehost
+ Diag: user=$user
+ Diag: host=$ehost
  Diag: port=$4
  Diag: path=$5
  EOF
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 8/9] connect: actively reject git:// urls with a user part

Mike Hommey-3
In reply to this post by Mike Hommey-3
Currently, urls of the for git://user@host don't work because user@host
is not resolving at the DNS level, but we shouldn't be relying on it
being an invalid host name, and actively reject it for containing a
username in the first place.

Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/connect.c b/connect.c
index df15ff3..fdd40b0 100644
--- a/connect.c
+++ b/connect.c
@@ -716,6 +716,9 @@ struct child_process *git_connect(int fd[2], const char *url,
  */
  struct strbuf target_host = STRBUF_INIT;
  char *override_vhost = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
+ if (user)
+ die("user@host is not allowed in git:// urls");
+
  if (override_vhost)
  strbuf_addstr(&target_host, override_vhost);
  else {
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH v5 9/9] connect: move ssh command line preparation to a separate function

Mike Hommey-3
In reply to this post by Mike Hommey-3
Signed-off-by: Mike Hommey <[hidden email]>
---
 connect.c | 108 +++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 58 insertions(+), 50 deletions(-)

diff --git a/connect.c b/connect.c
index fdd40b0..ae9ef7b 100644
--- a/connect.c
+++ b/connect.c
@@ -673,6 +673,61 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_user,
  return protocol;
 }
 
+static int prepare_ssh_command(struct argv_array *cmd, const char *user,
+       const char *host, const char *port, int flags)
+{
+ const char *ssh;
+ int putty = 0, tortoiseplink = 0, use_shell = 1;
+ transport_check_allowed("ssh");
+
+ ssh = getenv("GIT_SSH_COMMAND");
+ if (!ssh) {
+ const char *base;
+ char *ssh_dup;
+
+ /*
+ * GIT_SSH is the no-shell version of
+ * GIT_SSH_COMMAND (and must remain so for
+ * historical compatibility).
+ */
+ use_shell = 0;
+
+ ssh = getenv("GIT_SSH");
+ if (!ssh)
+ ssh = "ssh";
+
+ ssh_dup = xstrdup(ssh);
+ base = basename(ssh_dup);
+
+ tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
+ !strcasecmp(base, "tortoiseplink.exe");
+ putty = tortoiseplink ||
+ !strcasecmp(base, "plink") ||
+ !strcasecmp(base, "plink.exe");
+
+ free(ssh_dup);
+ }
+
+ argv_array_push(cmd, ssh);
+ if (flags & CONNECT_IPV4)
+ argv_array_push(cmd, "-4");
+ else if (flags & CONNECT_IPV6)
+ argv_array_push(cmd, "-6");
+ if (tortoiseplink)
+ argv_array_push(cmd, "-batch");
+ if (port) {
+ /* P is for PuTTY, p is for OpenSSH */
+ argv_array_push(cmd, putty ? "-P" : "-p");
+ argv_array_push(cmd, port);
+ }
+ if (user)
+ argv_array_pushf(cmd, "%s@%s", user, host);
+ else
+ argv_array_push(cmd, host);
+
+ return use_shell;
+}
+
 static struct child_process no_fork = CHILD_PROCESS_INIT;
 
 /*
@@ -767,59 +822,12 @@ struct child_process *git_connect(int fd[2], const char *url,
 
  /* remove repo-local variables from the environment */
  conn->env = local_repo_env;
- conn->use_shell = 1;
  conn->in = conn->out = -1;
  if (protocol == PROTO_SSH) {
- const char *ssh;
- int putty = 0, tortoiseplink = 0;
- transport_check_allowed("ssh");
-
- ssh = getenv("GIT_SSH_COMMAND");
- if (!ssh) {
- const char *base;
- char *ssh_dup;
-
- /*
- * GIT_SSH is the no-shell version of
- * GIT_SSH_COMMAND (and must remain so for
- * historical compatibility).
- */
- conn->use_shell = 0;
-
- ssh = getenv("GIT_SSH");
- if (!ssh)
- ssh = "ssh";
-
- ssh_dup = xstrdup(ssh);
- base = basename(ssh_dup);
-
- tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
- !strcasecmp(base, "tortoiseplink.exe");
- putty = tortoiseplink ||
- !strcasecmp(base, "plink") ||
- !strcasecmp(base, "plink.exe");
-
- free(ssh_dup);
- }
-
- argv_array_push(&conn->args, ssh);
- if (flags & CONNECT_IPV4)
- argv_array_push(&conn->args, "-4");
- else if (flags & CONNECT_IPV6)
- argv_array_push(&conn->args, "-6");
- if (tortoiseplink)
- argv_array_push(&conn->args, "-batch");
- if (port) {
- /* P is for PuTTY, p is for OpenSSH */
- argv_array_push(&conn->args, putty ? "-P" : "-p");
- argv_array_push(&conn->args, port);
- }
- if (user)
- argv_array_pushf(&conn->args, "%s@%s",
-                 user, host);
- else
- argv_array_push(&conn->args, host);
+ conn->use_shell = prepare_ssh_command(
+ &conn->args, user, host, port, flags);
  } else {
+ conn->use_shell = 1;
  transport_check_allowed("file");
  }
  argv_array_push(&conn->args, cmd.buf);
--
2.8.2.411.ga331486

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 2/9] connect: only match the host with core.gitProxy

Junio C Hamano
In reply to this post by Mike Hommey-3
Mike Hommey <[hidden email]> writes:

> Currently, core.gitProxy doesn't actually match purely on domain names
> as documented: it also matches ports.
> ...
> This per-port behavior seems like an oversight rather than a deliberate
> choice, so, make git://kernel.org:port/path call the gitProxy script in

Hmph.  The fact that hostandport, not just host after stripping
possible ":port" part, is passed to the function smells like a
deliberate design to allow people to use different proxy for
different port, so I am not sure everybody agrees with your "seems
like an oversight".

Don't existing users depend on the behaviour?  Isn't the change
robbing Peter to pay Paul?

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 2/9] connect: only match the host with core.gitProxy

Mike Hommey-3
On Mon, May 16, 2016 at 03:30:01PM -0700, Junio C Hamano wrote:

> Mike Hommey <[hidden email]> writes:
>
> > Currently, core.gitProxy doesn't actually match purely on domain names
> > as documented: it also matches ports.
> > ...
> > This per-port behavior seems like an oversight rather than a deliberate
> > choice, so, make git://kernel.org:port/path call the gitProxy script in
>
> Hmph.  The fact that hostandport, not just host after stripping
> possible ":port" part, is passed to the function smells like a
> deliberate design to allow people to use different proxy for
> different port, so I am not sure everybody agrees with your "seems
> like an oversight".
>
> Don't existing users depend on the behaviour?  Isn't the change
> robbing Peter to pay Paul?

The gitProxy script gets the port passed. Why would you need different
scripts for different ports if the port is passed as an argument? Also,
if it's deliberate, it's widely undocumented.

Mike
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 4/9] connect: make parse_connect_url() return separated host and port

Junio C Hamano
In reply to this post by Mike Hommey-3
Mike Hommey <[hidden email]> writes:

> + get_host_and_port(&host, &port);
> +
> + if (*host && !port) {
> + /* The host might contain a user:password string, ignore it
> + * when searching for the port again */
> + char *end_user = strrchr(host, '@');
> + port = get_port(end_user ? end_user : host);

Scanning from the right because host part would never have '@', but
there could be an invalid URL with an unquoted '@' in userinfo part?
Then this makes sense.

> diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
> index 91a69fc..9acba2b 100755
> --- a/t/t5500-fetch-pack.sh
> +++ b/t/t5500-fetch-pack.sh
> @@ -553,7 +553,7 @@ check_prot_path () {
>   Diag: protocol=$2
>   Diag: path=$3
>   EOF
> - git fetch-pack --diag-url "$1" | grep -v hostandport= >actual &&
> + git fetch-pack --diag-url "$1" | grep -v host= | grep -v port= >actual &&

A single process:

        ... | grep -v -e '^host=' -e '^port='

perhaps?

> @@ -562,22 +562,17 @@ check_prot_host_port_path () {
>   case "$2" in
>   *ssh*)
>   pp=ssh
> - uah=userandhost
> - ehost=$(echo $3 | tr -d "[]")
> - diagport="Diag: port=$4"
>   ;;
>   *)
> - pp=$p
> - uah=hostandport
> - ehost=$(echo $3$4 | sed -e "s/22$/:22/" -e "s/NONE//")
> - diagport=""
> + pp=$2
>   ;;
>   esac
> + ehost=$(echo $3 | tr -d "[]")
>   cat >exp <<-EOF &&
>   Diag: url=$1
>   Diag: protocol=$pp
> - Diag: $uah=$ehost
> - $diagport
> + Diag: userandhost=$ehost
> + Diag: port=$4
>   Diag: path=$5
>   EOF

This makes the diag output simpler and allows the caller to expect
the same set of variables, which is good.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 8/9] connect: actively reject git:// urls with a user part

Junio C Hamano
In reply to this post by Mike Hommey-3
Mike Hommey <[hidden email]> writes:

> Currently, urls of the for git://user@host don't work because user@host
> is not resolving at the DNS level, but we shouldn't be relying on it
> being an invalid host name, and actively reject it for containing a
> username in the first place.

Makes sense.  Connecting to host by stripping user@ would probably
give us a better behaviour, but this is a good first step even if we
are aiming for that endgame state.

>
> Signed-off-by: Mike Hommey <[hidden email]>
> ---
>  connect.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/connect.c b/connect.c
> index df15ff3..fdd40b0 100644
> --- a/connect.c
> +++ b/connect.c
> @@ -716,6 +716,9 @@ struct child_process *git_connect(int fd[2], const char *url,
>   */
>   struct strbuf target_host = STRBUF_INIT;
>   char *override_vhost = getenv("GIT_OVERRIDE_VIRTUAL_HOST");
> + if (user)
> + die("user@host is not allowed in git:// urls");
> +
>   if (override_vhost)
>   strbuf_addstr(&target_host, override_vhost);
>   else {
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 4/9] connect: make parse_connect_url() return separated host and port

Mike Hommey-3
In reply to this post by Junio C Hamano
On Mon, May 16, 2016 at 03:39:08PM -0700, Junio C Hamano wrote:

> Mike Hommey <[hidden email]> writes:
>
> > + get_host_and_port(&host, &port);
> > +
> > + if (*host && !port) {
> > + /* The host might contain a user:password string, ignore it
> > + * when searching for the port again */
> > + char *end_user = strrchr(host, '@');
> > + port = get_port(end_user ? end_user : host);
>
> Scanning from the right because host part would never have '@', but
> there could be an invalid URL with an unquoted '@' in userinfo part?
> Then this makes sense.

Indeed, I forgot to update the comment after the discussion on this
list.

> > diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
> > index 91a69fc..9acba2b 100755
> > --- a/t/t5500-fetch-pack.sh
> > +++ b/t/t5500-fetch-pack.sh
> > @@ -553,7 +553,7 @@ check_prot_path () {
> >   Diag: protocol=$2
> >   Diag: path=$3
> >   EOF
> > - git fetch-pack --diag-url "$1" | grep -v hostandport= >actual &&
> > + git fetch-pack --diag-url "$1" | grep -v host= | grep -v port= >actual &&
>
> A single process:
>
> ... | grep -v -e '^host=' -e '^port='

heh, I'm actually replacing it with a single egrep in a subsequent
patch, following feedback from previous round, but missed that there was
this intermediate step with multiple greps still. Do you want an update
anyways, or does only the final result really matter? I guess I can
update it in any case, since I'll have to update the patch for the
comment above anyways.

Mike
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v5 2/9] connect: only match the host with core.gitProxy

Junio C Hamano
In reply to this post by Mike Hommey-3
Mike Hommey <[hidden email]> writes:

> The gitProxy script gets the port passed. Why would you need different
> scripts for different ports if the port is passed as an argument? Also,
> if it's deliberate, it's widely undocumented.

Fair enough.

A user who has been working around thsi "oversight", would have
relied on her proxy configured with 'script for myhost.xz:9111' to
be called for git://myhost.xz:9111/path, right?  We'd need to
somehow let her know that her configuration will be broken, but as
long as we can find a way to do so to ease the transition, I think
the updated "if you want to use a different behaviour depending on
port, use the port parameter" is a lot more sensible behaviour than
what we had traditionally.


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html