All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Torsten Bögershausen" <tboegi@web.de>
To: git@vger.kernel.org
Cc: tboegi@web.de, lists@hcf.yourweb.de
Subject: [PATCH 1/3] connect.c: Improve parsing of literal IPV6 addresses
Date: Mon, 19 Jan 2015 18:21:24 +0100	[thread overview]
Message-ID: <54BD3D14.90309@web.de> (raw)

When parsing an URL, older Git versions did handle
URLs like ssh://2001:db8::1/repo.git the same way as
ssh://[2001:db8::1]/repo.git

Commit 83b058 broke the parsing of IPV6 adresses without "[]":
It was written in mind that the fist ':' in a URL was the beginning of a
port number, while the old code was more clever:
Literal IPV6 addresses have always at least two ':'.
When the "hostandport" had a ':' and the rest of the hostandport string
could be parsed into an integer between 0 and 65536, then it was used
as a port number, like "host:22".
Otherwise the first ':' was assumed to be part of a literal IPV6 address,
like "ssh://[2001:db8::1]/repo.git" or "ssh://[::1]/repo.git".

Re-introduce the old parsing in get_host_and_port().

Improve the parsing to handle URLs which have a user name and a literal
IPV6 like "ssh://user@[2001:db8::1]/repo.git".
(Thanks to Christian Taube <lists@hcf.yourweb.de> for reporting this long
standing issue)

Another regression was introduced in 83b058:
A non-RFC conform URL like "[localhost:222]" could be used in older versions
of Git to connect to run "ssh -p 222 localhost".
The new stricter parsing did not allow this any more.
See even 8d3d28f5dba why "[localhost:222]" should be declared a feature.

Signed-off-by: Torsten Bögershausen <tboegi@web.de>
---
Unfortunatly my attemps to improve connect.c introduced some
regressions:
- "git clone ssh://::1/repo" did not work anymore (for some reason I assumed
  that literall IPV6 addresses always should have brackets, but that was wrong)
- "ssh://host:2222/repo" written in the "unofficial short form"
  "[host:2222]:repo did not work anymore. I think that should be
  an "unoffical feature", because it worked in older Git versions

On top of that, the combination of ssh://username@[host] had never
be handled correctly, so fix that as well.
Thanks to Christian Taube for reporting it.


Comments and an extra pair of critical eyes are welcome.


 connect.c        | 63 ++++++++++++++++++++++++++++++++++----------------------
 t/t5601-clone.sh |  2 +-
 2 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/connect.c b/connect.c
index d47d0ec..b608976 100644
--- a/connect.c
+++ b/connect.c
@@ -274,28 +274,44 @@ static enum protocol get_protocol(const char *name)
 	die("I don't handle protocol '%s'", name);
 }
 
+static char *host_end(char **hoststart, int removebrackets)
+{
+	char *host = *hoststart;
+	char *end;
+	char *start = strstr(host, "@[");
+	if (start)
+		start++; /* Jump over '@' */
+	else
+		start = host;
+	if (start[0] == '[') {
+		end = strchr(start + 1, ']');
+		if (end) {
+			if (removebrackets) {
+				*end = 0;
+				memmove(start, start + 1, end - start);
+				end++;
+			}
+		} else
+			end = host;
+	} else
+		end = host;
+	return end;
+}
+
 #define STR_(s)	# s
 #define STR(s)	STR_(s)
 
 static void get_host_and_port(char **host, const char **port)
 {
 	char *colon, *end;
-
-	if (*host[0] == '[') {
-		end = strchr(*host + 1, ']');
-		if (end) {
-			*end = 0;
-			end++;
-			(*host)++;
-		} else
-			end = *host;
-	} else
-		end = *host;
+	end = host_end(host, 1);
 	colon = strchr(end, ':');
-
 	if (colon) {
-		*colon = 0;
-		*port = colon + 1;
+		long portnr = strtol(colon + 1, &end, 10);
+		if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) {
+			*colon = 0;
+			*port = colon + 1;
+		}
 	}
 }
 
@@ -547,13 +563,16 @@ static struct child_process *git_proxy_connect(int fd[2], char *host)
 	return proxy;
 }
 
-static const char *get_port_numeric(const char *p)
+static char *get_port(char *host)
 {
 	char *end;
+	char *p = strchr(host, ':');
+
 	if (p) {
 		long port = strtol(p + 1, &end, 10);
 		if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
-			return p;
+			*p = '\0';
+			return p+1;
 		}
 	}
 
@@ -595,14 +614,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
 	 * Don't do destructive transforms as protocol code does
 	 * '[]' unwrapping in get_host_and_port()
 	 */
-	if (host[0] == '[') {
-		end = strchr(host + 1, ']');
-		if (end) {
-			end++;
-		} else
-			end = host;
-	} else
-		end = host;
+	end = host_end(&host, 0);
 
 	if (protocol == PROTO_LOCAL)
 		path = end;
@@ -705,7 +717,8 @@ struct child_process *git_connect(int fd[2], const char *url,
 			char *ssh_host = hostandport;
 			const char *port = NULL;
 			get_host_and_port(&ssh_host, &port);
-			port = get_port_numeric(port);
+			if (!port)
+				port = get_port(ssh_host);
 
 			if (!ssh) ssh = "ssh";
 
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index e4f10c0..f901b8a 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -326,7 +326,7 @@ test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
 
 test_expect_success 'bracketed hostnames are still ssh' '
 	git clone "[myhost:123]:src" ssh-bracket-clone &&
-	expect_ssh myhost:123 src
+	expect_ssh myhost '-p 123' src
 '
 
 counter=0
-- 
2.2.0.rc1.26.g3e3a70d

             reply	other threads:[~2015-01-19 17:22 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-19 17:21 Torsten Bögershausen [this message]
2015-01-22 20:07 ` [PATCH 1/3] connect.c: Improve parsing of literal IPV6 addresses brian m. carlson
2015-01-22 22:05   ` Torsten Bögershausen
2015-01-22 23:41     ` brian m. carlson
2015-02-18 18:40       ` Junio C Hamano
2015-02-19 16:42         ` Torsten Bögershausen
2015-02-19 17:54           ` Junio C Hamano
2015-02-19 19:40             ` brian m. carlson
2015-02-20 22:11               ` Torsten Bögershausen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54BD3D14.90309@web.de \
    --to=tboegi@web.de \
    --cc=git@vger.kernel.org \
    --cc=lists@hcf.yourweb.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.