]> git.ipfire.org Git - thirdparty/git.git/commitdiff
credential_format(): also encode <host>[:<port>]
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 7 Nov 2024 07:57:52 +0000 (08:57 +0100)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Tue, 26 Nov 2024 19:24:00 +0000 (20:24 +0100)
An upcoming change wants to sanitize the credential password prompt
where a URL is displayed that may potentially come from a `.gitmodules`
file. To this end, the `credential_format()` function is employed.

To sanitize the host name (and optional port) part of the URL, we need a
new mode of the `strbuf_add_percentencode()` function because the
current mode is both too strict and too lenient: too strict because it
encodes `:`, `[` and `]` (which should be left unencoded in
`<host>:<port>` and in IPv6 addresses), and too lenient because it does
not encode invalid host name characters `/`, `_` and `~`.

So let's introduce and use a new mode specifically to encode the host
name and optional port part of a URI, leaving alpha-numerical
characters, periods, colons and brackets alone and encoding all others.

This only leads to a change of behavior for URLs that contain invalid
host names.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
credential.c
strbuf.c
strbuf.h
t/t0300-credentials.sh

index f32011343f9400a80cb9999fe75e0eeefde48146..572f1785da7d3e3540d523e12cdedfbeaab6ce91 100644 (file)
@@ -164,7 +164,8 @@ static void credential_format(struct credential *c, struct strbuf *out)
                strbuf_addch(out, '@');
        }
        if (c->host)
-               strbuf_addstr(out, c->host);
+               strbuf_add_percentencode(out, c->host,
+                                        STRBUF_ENCODE_HOST_AND_PORT);
        if (c->path) {
                strbuf_addch(out, '/');
                strbuf_add_percentencode(out, c->path, 0);
index c383f41a3c5ccc6c6228c4ed4f9631529633f878..756b96c56157c37a22c826cbb1c9da5e6e1ae908 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -492,7 +492,9 @@ void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
                unsigned char ch = src[i];
                if (ch <= 0x1F || ch >= 0x7F ||
                    (ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
-                   strchr(URL_UNSAFE_CHARS, ch))
+                   ((flags & STRBUF_ENCODE_HOST_AND_PORT) ?
+                    !isalnum(ch) && !strchr("-.:[]", ch) :
+                    !!strchr(URL_UNSAFE_CHARS, ch)))
                        strbuf_addf(dst, "%%%02X", (unsigned char)ch);
                else
                        strbuf_addch(dst, ch);
index f6dbb9681ee768221e707a39c37dc0a00f63b95d..f9f8bb0381b3c54e15caf43c309d1c584b3bbf6a 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -380,6 +380,7 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb,
 void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
 
 #define STRBUF_ENCODE_SLASH 1
+#define STRBUF_ENCODE_HOST_AND_PORT 2
 
 /**
  * Append the contents of a string to a strbuf, percent-encoding any characters
index c66d91e82d8bc737bc6b909c9427f163aef5dfea..cb91be1427f1d29c9bbf14bed6e5883cabff2cec 100755 (executable)
@@ -514,6 +514,19 @@ test_expect_success 'match percent-encoded values in username' '
        EOF
 '
 
+test_expect_success 'match percent-encoded values in hostname' '
+       test_config "credential.https://a%20b%20c/.helper" "$HELPER" &&
+       check fill <<-\EOF
+       url=https://a b c/
+       --
+       protocol=https
+       host=a b c
+       username=foo
+       password=bar
+       --
+       EOF
+'
+
 test_expect_success 'fetch with multiple path components' '
        test_unconfig credential.helper &&
        test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&