Fix CVE-2024-50349 CVE-2024-52006
This commit is contained in:
parent
4cbb33984f
commit
579eb9f122
@ -0,0 +1,276 @@
|
|||||||
|
From 7725b8100ffbbff2750ee4d61a0fcc1f53a086e8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
Date: Wed, 30 Oct 2024 13:26:10 +0100
|
||||||
|
Subject: [PATCH] credential: sanitize the user prompt
|
||||||
|
|
||||||
|
When asking the user interactively for credentials, we want to avoid
|
||||||
|
misleading them e.g. via control sequences that pretend that the URL
|
||||||
|
targets a trusted host when it does not.
|
||||||
|
|
||||||
|
While Git learned, over the course of the preceding commits, to disallow
|
||||||
|
URLs containing URL-encoded control characters by default, credential
|
||||||
|
helpers are still allowed to specify values very freely (apart from Line
|
||||||
|
Feed and NUL characters, anything is allowed), and this would allow,
|
||||||
|
say, a username containing control characters to be specified that would
|
||||||
|
then be displayed in the interactive terminal prompt asking the user for
|
||||||
|
the password, potentially sending those control characters directly to
|
||||||
|
the terminal. This is undesirable because control characters can be used
|
||||||
|
to mislead users to divulge secret information to untrusted sites.
|
||||||
|
|
||||||
|
To prevent such an attack vector, let's add a `git_prompt()` that forces
|
||||||
|
the displayed text to be sanitized, i.e. displaying question marks
|
||||||
|
instead of control characters.
|
||||||
|
|
||||||
|
Note: While this commit's diff changes a lot of `user@host` strings to
|
||||||
|
`user%40host`, which may look suspicious on the surface, there is a good
|
||||||
|
reason for that: this string specifies a user name, not a
|
||||||
|
<username>@<hostname> combination! In the context of t5541, the actual
|
||||||
|
combination looks like this: `user%40@127.0.0.1:5541`. Therefore, these
|
||||||
|
string replacements document a net improvement introduced by this
|
||||||
|
commit, as `user@host@127.0.0.1` could have left readers wondering where
|
||||||
|
the user name ends and where the host name begins.
|
||||||
|
|
||||||
|
Hinted-at-by: Jeff King <peff@peff.net>
|
||||||
|
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
---
|
||||||
|
Documentation/config/credential.txt | 6 ++++++
|
||||||
|
credential.c | 7 ++++++-
|
||||||
|
credential.h | 4 +++-
|
||||||
|
t/t0300-credentials.sh | 20 ++++++++++++++++++++
|
||||||
|
t/t5541-http-push-smart.sh | 6 +++---
|
||||||
|
t/t5550-http-fetch-dumb.sh | 14 +++++++-------
|
||||||
|
t/t5551-http-fetch-smart.sh | 16 ++++++++--------
|
||||||
|
7 files changed, 53 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
|
||||||
|
index 512f3187..fd8113d6 100644
|
||||||
|
--- a/Documentation/config/credential.txt
|
||||||
|
+++ b/Documentation/config/credential.txt
|
||||||
|
@@ -14,6 +14,12 @@ credential.useHttpPath::
|
||||||
|
or https URL to be important. Defaults to false. See
|
||||||
|
linkgit:gitcredentials[7] for more information.
|
||||||
|
|
||||||
|
+credential.sanitizePrompt::
|
||||||
|
+ By default, user names and hosts that are shown as part of the
|
||||||
|
+ password prompt are not allowed to contain control characters (they
|
||||||
|
+ will be URL-encoded by default). Configure this setting to `false` to
|
||||||
|
+ override that behavior.
|
||||||
|
+
|
||||||
|
credential.username::
|
||||||
|
If no username is set for a network authentication, use this username
|
||||||
|
by default. See credential.<context>.* below, and
|
||||||
|
diff --git a/credential.c b/credential.c
|
||||||
|
index 572f1785..1392a54d 100644
|
||||||
|
--- a/credential.c
|
||||||
|
+++ b/credential.c
|
||||||
|
@@ -67,6 +67,8 @@ static int credential_config_callback(const char *var, const char *value,
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "usehttppath"))
|
||||||
|
c->use_http_path = git_config_bool(var, value);
|
||||||
|
+ else if (!strcmp(key, "sanitizeprompt"))
|
||||||
|
+ c->sanitize_prompt = git_config_bool(var, value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -179,7 +181,10 @@ static char *credential_ask_one(const char *what, struct credential *c,
|
||||||
|
struct strbuf prompt = STRBUF_INIT;
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
- credential_describe(c, &desc);
|
||||||
|
+ if (c->sanitize_prompt)
|
||||||
|
+ credential_format(c, &desc);
|
||||||
|
+ else
|
||||||
|
+ credential_describe(c, &desc);
|
||||||
|
if (desc.len)
|
||||||
|
strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf);
|
||||||
|
else
|
||||||
|
diff --git a/credential.h b/credential.h
|
||||||
|
index 935b28a7..0364d436 100644
|
||||||
|
--- a/credential.h
|
||||||
|
+++ b/credential.h
|
||||||
|
@@ -119,7 +119,8 @@ struct credential {
|
||||||
|
configured:1,
|
||||||
|
quit:1,
|
||||||
|
use_http_path:1,
|
||||||
|
- username_from_proto:1;
|
||||||
|
+ username_from_proto:1,
|
||||||
|
+ sanitize_prompt:1;
|
||||||
|
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
@@ -132,7 +133,10 @@ struct credential {
|
||||||
|
char *path;
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define CREDENTIAL_INIT { STRING_LIST_INIT_DUP }
|
||||||
|
+#define CREDENTIAL_INIT { \
|
||||||
|
+ .helpers = STRING_LIST_INIT_DUP, \
|
||||||
|
+ .sanitize_prompt = 1, \
|
||||||
|
+};
|
||||||
|
|
||||||
|
/* Initialize a credential structure, setting all fields to empty. */
|
||||||
|
void credential_init(struct credential *);
|
||||||
|
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
|
||||||
|
index cb91be14..b62c70c1 100755
|
||||||
|
--- a/t/t0300-credentials.sh
|
||||||
|
+++ b/t/t0300-credentials.sh
|
||||||
|
@@ -45,6 +45,10 @@ test_expect_success 'setup helper scripts' '
|
||||||
|
test -z "$pass" || echo password=$pass
|
||||||
|
EOF
|
||||||
|
|
||||||
|
+ write_script git-credential-cntrl-in-username <<-\EOF &&
|
||||||
|
+ printf "username=\\007latrix Lestrange\\n"
|
||||||
|
+ EOF
|
||||||
|
+
|
||||||
|
PATH="$PWD:$PATH"
|
||||||
|
'
|
||||||
|
|
||||||
|
@@ -825,4 +829,20 @@ test_expect_success 'credential config with partial URLs' '
|
||||||
|
test_i18ngrep "skipping credential lookup for key" stderr
|
||||||
|
'
|
||||||
|
|
||||||
|
+BEL="$(printf '\007')"
|
||||||
|
+
|
||||||
|
+test_expect_success 'interactive prompt is sanitized' '
|
||||||
|
+ check fill cntrl-in-username <<-EOF
|
||||||
|
+ protocol=https
|
||||||
|
+ host=example.org
|
||||||
|
+ --
|
||||||
|
+ protocol=https
|
||||||
|
+ host=example.org
|
||||||
|
+ username=${BEL}latrix Lestrange
|
||||||
|
+ password=askpass-password
|
||||||
|
+ --
|
||||||
|
+ askpass: Password for ${SQ}https://%07latrix%20Lestrange@example.org${SQ}:
|
||||||
|
+ EOF
|
||||||
|
+'
|
||||||
|
+
|
||||||
|
test_done
|
||||||
|
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
|
||||||
|
index d0211cd8..2cd2e1a0 100755
|
||||||
|
--- a/t/t5541-http-push-smart.sh
|
||||||
|
+++ b/t/t5541-http-push-smart.sh
|
||||||
|
@@ -351,7 +351,7 @@ test_expect_success 'push over smart http with auth' '
|
||||||
|
git push "$HTTPD_URL"/auth/smart/test_repo.git &&
|
||||||
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||||
|
log -1 --format=%s >actual &&
|
||||||
|
- expect_askpass both user@host &&
|
||||||
|
+ expect_askpass both user%40host &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
@@ -363,7 +363,7 @@ test_expect_success 'push to auth-only-for-push repo' '
|
||||||
|
git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
|
||||||
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||||
|
log -1 --format=%s >actual &&
|
||||||
|
- expect_askpass both user@host &&
|
||||||
|
+ expect_askpass both user%40host &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
@@ -393,7 +393,7 @@ test_expect_success 'push into half-auth-complete requires password' '
|
||||||
|
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
|
||||||
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
|
||||||
|
log -1 --format=%s >actual &&
|
||||||
|
- expect_askpass both user@host &&
|
||||||
|
+ expect_askpass both user%40host &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
|
||||||
|
index 8f182a3c..5d0e3946 100755
|
||||||
|
--- a/t/t5550-http-fetch-dumb.sh
|
||||||
|
+++ b/t/t5550-http-fetch-dumb.sh
|
||||||
|
@@ -90,13 +90,13 @@ test_expect_success 'http auth can use user/pass in URL' '
|
||||||
|
test_expect_success 'http auth can use just user in URL' '
|
||||||
|
set_askpass wrong pass@host &&
|
||||||
|
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'http auth can request both user and pass' '
|
||||||
|
set_askpass user@host pass@host &&
|
||||||
|
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
|
||||||
|
- expect_askpass both user@host
|
||||||
|
+ expect_askpass both user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'http auth respects credential helper config' '
|
||||||
|
@@ -114,14 +114,14 @@ test_expect_success 'http auth can get username from config' '
|
||||||
|
test_config_global "credential.$HTTPD_URL.username" user@host &&
|
||||||
|
set_askpass wrong pass@host &&
|
||||||
|
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'configured username does not override URL' '
|
||||||
|
test_config_global "credential.$HTTPD_URL.username" wrong &&
|
||||||
|
set_askpass wrong pass@host &&
|
||||||
|
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'set up repo with http submodules' '
|
||||||
|
@@ -142,7 +142,7 @@ test_expect_success 'cmdline credential config passes to submodule via clone' '
|
||||||
|
set_askpass wrong pass@host &&
|
||||||
|
git -c "credential.$HTTPD_URL.username=user@host" \
|
||||||
|
clone --recursive super super-clone &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||||
|
@@ -153,7 +153,7 @@ test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||||
|
git -C super-clone \
|
||||||
|
-c "credential.$HTTPD_URL.username=user@host" \
|
||||||
|
fetch --recurse-submodules &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cmdline credential config passes submodule update' '
|
||||||
|
@@ -170,7 +170,7 @@ test_expect_success 'cmdline credential config passes submodule update' '
|
||||||
|
git -C super-clone \
|
||||||
|
-c "credential.$HTTPD_URL.username=user@host" \
|
||||||
|
submodule update &&
|
||||||
|
- expect_askpass pass user@host
|
||||||
|
+ expect_askpass pass user%40host
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch changes via http' '
|
||||||
|
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
|
||||||
|
index 0908534f..8a27768d 100755
|
||||||
|
--- a/t/t5551-http-fetch-smart.sh
|
||||||
|
+++ b/t/t5551-http-fetch-smart.sh
|
||||||
|
@@ -181,7 +181,7 @@ test_expect_success 'clone from password-protected repository' '
|
||||||
|
echo two >expect &&
|
||||||
|
set_askpass user@host pass@host &&
|
||||||
|
git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
|
||||||
|
- expect_askpass both user@host &&
|
||||||
|
+ expect_askpass both user%40host &&
|
||||||
|
git --git-dir=smart-auth log -1 --format=%s >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
@@ -199,7 +199,7 @@ test_expect_success 'clone from auth-only-for-objects repository' '
|
||||||
|
echo two >expect &&
|
||||||
|
set_askpass user@host pass@host &&
|
||||||
|
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
|
||||||
|
- expect_askpass both user@host &&
|
||||||
|
+ expect_askpass both user%40host &&
|
||||||
|
git --git-dir=half-auth log -1 --format=%s >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
@@ -224,7 +224,7 @@ test_expect_success 'redirects send auth to new location' '
|
||||||
|
set_askpass user@host pass@host &&
|
||||||
|
git -c credential.useHttpPath=true \
|
||||||
|
clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
|
||||||
|
- expect_askpass both user@host auth/smart/repo.git
|
||||||
|
+ expect_askpass both user%40host auth/smart/repo.git
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'disable dumb http on server' '
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
From c903985bf7e772e2d08275c1a95c8a55ab011577 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
Date: Thu, 7 Nov 2024 08:57:52 +0100
|
||||||
|
Subject: [PATCH] credential_format(): also encode <host>[:<port>]
|
||||||
|
|
||||||
|
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 | 3 ++-
|
||||||
|
strbuf.c | 4 +++-
|
||||||
|
strbuf.h | 1 +
|
||||||
|
t/t0300-credentials.sh | 13 +++++++++++++
|
||||||
|
4 files changed, 19 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/credential.c b/credential.c
|
||||||
|
index f3201134..572f1785 100644
|
||||||
|
--- a/credential.c
|
||||||
|
+++ b/credential.c
|
||||||
|
@@ -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);
|
||||||
|
diff --git a/strbuf.c b/strbuf.c
|
||||||
|
index c383f41a..756b96c5 100644
|
||||||
|
--- 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);
|
||||||
|
diff --git a/strbuf.h b/strbuf.h
|
||||||
|
index f6dbb968..f9f8bb03 100644
|
||||||
|
--- 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
|
||||||
|
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
|
||||||
|
index c66d91e8..cb91be14 100755
|
||||||
|
--- a/t/t0300-credentials.sh
|
||||||
|
+++ b/t/t0300-credentials.sh
|
||||||
|
@@ -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" &&
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
@ -0,0 +1,160 @@
|
|||||||
|
From b01b9b81d36759cdcd07305e78765199e1bc2060 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
Date: Mon, 4 Nov 2024 14:48:22 +0100
|
||||||
|
Subject: [PATCH] credential: disallow Carriage Returns in the protocol by
|
||||||
|
default
|
||||||
|
|
||||||
|
While Git has documented that the credential protocol is line-based,
|
||||||
|
with newlines as terminators, the exact shape of a newline has not been
|
||||||
|
documented.
|
||||||
|
|
||||||
|
From Git's perspective, which is firmly rooted in the Linux ecosystem,
|
||||||
|
it is clear that "a newline" means a Line Feed character.
|
||||||
|
|
||||||
|
However, even Git's credential protocol respects Windows line endings
|
||||||
|
(a Carriage Return character followed by a Line Feed character, "CR/LF")
|
||||||
|
by virtue of using `strbuf_getline()`.
|
||||||
|
|
||||||
|
There is a third category of line endings that has been used originally
|
||||||
|
by MacOS, and that is respected by the default line readers of .NET and
|
||||||
|
node.js: bare Carriage Returns.
|
||||||
|
|
||||||
|
Git cannot handle those, and what is worse: Git's remedy against
|
||||||
|
CVE-2020-5260 does not catch when credential helpers are used that
|
||||||
|
interpret bare Carriage Returns as newlines.
|
||||||
|
|
||||||
|
Git Credential Manager addressed this as CVE-2024-50338, but other
|
||||||
|
credential helpers may still be vulnerable. So let's not only disallow
|
||||||
|
Line Feed characters as part of the values in the credential protocol,
|
||||||
|
but also disallow Carriage Return characters.
|
||||||
|
|
||||||
|
In the unlikely event that a credential helper relies on Carriage
|
||||||
|
Returns in the protocol, introduce an escape hatch via the
|
||||||
|
`credential.protectProtocol` config setting.
|
||||||
|
|
||||||
|
This addresses CVE-2024-52006.
|
||||||
|
|
||||||
|
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
---
|
||||||
|
Documentation/config/credential.txt | 5 +++++
|
||||||
|
credential.c | 21 ++++++++++++++-------
|
||||||
|
credential.h | 4 +++-
|
||||||
|
t/t0300-credentials.sh | 16 ++++++++++++++++
|
||||||
|
4 files changed, 38 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
|
||||||
|
index fd8113d6..9cadca7f 100644
|
||||||
|
--- a/Documentation/config/credential.txt
|
||||||
|
+++ b/Documentation/config/credential.txt
|
||||||
|
@@ -20,6 +20,11 @@ credential.sanitizePrompt::
|
||||||
|
will be URL-encoded by default). Configure this setting to `false` to
|
||||||
|
override that behavior.
|
||||||
|
|
||||||
|
+credential.protectProtocol::
|
||||||
|
+ By default, Carriage Return characters are not allowed in the protocol
|
||||||
|
+ that is used when Git talks to a credential helper. This setting allows
|
||||||
|
+ users to override this default.
|
||||||
|
+
|
||||||
|
credential.username::
|
||||||
|
If no username is set for a network authentication, use this username
|
||||||
|
by default. See credential.<context>.* below, and
|
||||||
|
diff --git a/credential.c b/credential.c
|
||||||
|
index 1392a54d..b76a7309 100644
|
||||||
|
--- a/credential.c
|
||||||
|
+++ b/credential.c
|
||||||
|
@@ -69,6 +69,8 @@ static int credential_config_callback(const char *var, const char *value,
|
||||||
|
c->use_http_path = git_config_bool(var, value);
|
||||||
|
else if (!strcmp(key, "sanitizeprompt"))
|
||||||
|
c->sanitize_prompt = git_config_bool(var, value);
|
||||||
|
+ else if (!strcmp(key, "protectprotocol"))
|
||||||
|
+ c->protect_protocol = git_config_bool(var, value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -262,7 +264,8 @@ int credential_read(struct credential *c, FILE *fp)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void credential_write_item(FILE *fp, const char *key, const char *value,
|
||||||
|
+static void credential_write_item(const struct credential *c,
|
||||||
|
+ FILE *fp, const char *key, const char *value,
|
||||||
|
int required)
|
||||||
|
{
|
||||||
|
if (!value && required)
|
||||||
|
@@ -271,16 +274,20 @@ static void credential_write_item(FILE *fp, const char *key, const char *value,
|
||||||
|
return;
|
||||||
|
if (strchr(value, '\n'))
|
||||||
|
die("credential value for %s contains newline", key);
|
||||||
|
+ if (c->protect_protocol && strchr(value, '\r'))
|
||||||
|
+ die("credential value for %s contains carriage return\n"
|
||||||
|
+ "If this is intended, set `credential.protectProtocol=false`",
|
||||||
|
+ key);
|
||||||
|
fprintf(fp, "%s=%s\n", key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void credential_write(const struct credential *c, FILE *fp)
|
||||||
|
{
|
||||||
|
- credential_write_item(fp, "protocol", c->protocol, 1);
|
||||||
|
- credential_write_item(fp, "host", c->host, 1);
|
||||||
|
- credential_write_item(fp, "path", c->path, 0);
|
||||||
|
- credential_write_item(fp, "username", c->username, 0);
|
||||||
|
- credential_write_item(fp, "password", c->password, 0);
|
||||||
|
+ credential_write_item(c, fp, "protocol", c->protocol, 1);
|
||||||
|
+ credential_write_item(c, fp, "host", c->host, 1);
|
||||||
|
+ credential_write_item(c, fp, "path", c->path, 0);
|
||||||
|
+ credential_write_item(c, fp, "username", c->username, 0);
|
||||||
|
+ credential_write_item(c, fp, "password", c->password, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_credential_helper(struct credential *c,
|
||||||
|
diff --git a/credential.h b/credential.h
|
||||||
|
index 0364d436..2c0b39a9 100644
|
||||||
|
--- a/credential.h
|
||||||
|
+++ b/credential.h
|
||||||
|
@@ -120,7 +120,8 @@ struct credential {
|
||||||
|
quit:1,
|
||||||
|
use_http_path:1,
|
||||||
|
username_from_proto:1,
|
||||||
|
- sanitize_prompt:1;
|
||||||
|
+ sanitize_prompt:1,
|
||||||
|
+ protect_protocol:1;
|
||||||
|
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
@@ -134,6 +135,7 @@ struct credential {
|
||||||
|
#define CREDENTIAL_INIT { \
|
||||||
|
.helpers = STRING_LIST_INIT_DUP, \
|
||||||
|
.sanitize_prompt = 1, \
|
||||||
|
+ .protect_protocol = 1, \
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Initialize a credential structure, setting all fields to empty. */
|
||||||
|
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
|
||||||
|
index b62c70c1..168ae765 100755
|
||||||
|
--- a/t/t0300-credentials.sh
|
||||||
|
+++ b/t/t0300-credentials.sh
|
||||||
|
@@ -720,6 +720,22 @@ test_expect_success 'url parser rejects embedded newlines' '
|
||||||
|
test_i18ncmp expect stderr
|
||||||
|
'
|
||||||
|
|
||||||
|
+test_expect_success 'url parser rejects embedded carriage returns' '
|
||||||
|
+ test_config credential.helper "!true" &&
|
||||||
|
+ test_must_fail git credential fill 2>stderr <<-\EOF &&
|
||||||
|
+ url=https://example%0d.com/
|
||||||
|
+ EOF
|
||||||
|
+ cat >expect <<-\EOF &&
|
||||||
|
+ fatal: credential value for host contains carriage return
|
||||||
|
+ If this is intended, set `credential.protectProtocol=false`
|
||||||
|
+ EOF
|
||||||
|
+ test_cmp expect stderr &&
|
||||||
|
+ GIT_ASKPASS=true \
|
||||||
|
+ git -c credential.protectProtocol=false credential fill <<-\EOF
|
||||||
|
+ url=https://example%0d.com/
|
||||||
|
+ EOF
|
||||||
|
+'
|
||||||
|
+
|
||||||
|
test_expect_success 'host-less URLs are parsed as empty host' '
|
||||||
|
check fill "verbatim foo bar" <<-\EOF
|
||||||
|
url=cert:///path/to/cert.pem
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
59
backport-pre-001-CVE-2024-52006.patch
Normal file
59
backport-pre-001-CVE-2024-52006.patch
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
From 356c473295097f4aeaacc1a2dcd70271b7080788 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nikita Leonov <nykyta.leonov@gmail.com>
|
||||||
|
Date: Sat, 3 Oct 2020 13:29:12 +0000
|
||||||
|
Subject: [PATCH] credential: treat CR/LF as line endings in the credential
|
||||||
|
protocol
|
||||||
|
|
||||||
|
This fix makes using Git credentials more friendly to Windows users: it
|
||||||
|
allows a credential helper to communicate using CR/LF line endings ("DOS
|
||||||
|
line endings" commonly found on Windows) instead of LF-only line endings
|
||||||
|
("Unix line endings").
|
||||||
|
|
||||||
|
Note that this changes the behavior a bit: if a credential helper
|
||||||
|
produces, say, a password with a trailing Carriage Return character,
|
||||||
|
that will now be culled even when the rest of the lines end only in Line
|
||||||
|
Feed characters, indicating that the Carriage Return was not meant to be
|
||||||
|
part of the line ending.
|
||||||
|
|
||||||
|
In practice, it seems _very_ unlikely that something like this happens.
|
||||||
|
Passwords usually need to consist of non-control characters, URLs need
|
||||||
|
to have special characters URL-encoded, and user names, well, are names.
|
||||||
|
|
||||||
|
However, it _does_ help on Windows, where CR/LF line endings are common:
|
||||||
|
as unrecognized commands are simply ignored by the credential machinery,
|
||||||
|
even a command like `quit\r` (which is clearly intended to abort) would
|
||||||
|
simply be ignored (silently) by Git.
|
||||||
|
|
||||||
|
So let's change the credential machinery to accept both CR/LF and LF
|
||||||
|
line endings.
|
||||||
|
|
||||||
|
While we do this for the credential helper protocol, we do _not_ adjust
|
||||||
|
`git credential-cache--daemon` (which won't work on Windows, anyway,
|
||||||
|
because it requires Unix sockets) nor `git credential-store` (which
|
||||||
|
writes the file `~/.git-credentials` which we consider an implementation
|
||||||
|
detail that should be opaque to the user, read: we do expect users _not_
|
||||||
|
to edit this file manually).
|
||||||
|
|
||||||
|
Signed-off-by: Nikita Leonov <nykyta.leonov@gmail.com>
|
||||||
|
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||||
|
---
|
||||||
|
credential.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/credential.c b/credential.c
|
||||||
|
index efc29dc5e1..e5202fbef2 100644
|
||||||
|
--- a/credential.c
|
||||||
|
+++ b/credential.c
|
||||||
|
@@ -202,7 +202,7 @@ int credential_read(struct credential *c, FILE *fp)
|
||||||
|
{
|
||||||
|
struct strbuf line = STRBUF_INIT;
|
||||||
|
|
||||||
|
- while (strbuf_getline_lf(&line, fp) != EOF) {
|
||||||
|
+ while (strbuf_getline(&line, fp) != EOF) {
|
||||||
|
char *key = line.buf;
|
||||||
|
char *value = strchr(key, '=');
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
100
backport-pre-002-CVE-2024-52006.patch
Normal file
100
backport-pre-002-CVE-2024-52006.patch
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
From 5726a6b4012cd41701927a6637b9f2070e7760ee Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?=
|
||||||
|
<avarab@gmail.com>
|
||||||
|
Date: Thu, 1 Jul 2021 12:51:26 +0200
|
||||||
|
Subject: [PATCH] *.c *_init(): define in terms of corresponding *_INIT macro
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Change the common patter in the codebase of duplicating the
|
||||||
|
initialization logic between an *_INIT macro and a
|
||||||
|
corresponding *_init() function to use the macro as the canonical
|
||||||
|
source of truth.
|
||||||
|
|
||||||
|
Now we no longer need to keep the function up-to-date with the macro
|
||||||
|
version. This implements a suggestion by Jeff King who found that
|
||||||
|
under -O2 [1] modern compilers will init new version in place without
|
||||||
|
the extra copy[1]. The performance of a single *_init() won't matter
|
||||||
|
in most cases, but even if it does we're going to be producing
|
||||||
|
efficient machine code to perform these operations.
|
||||||
|
|
||||||
|
1. https://lore.kernel.org/git/YNyrDxUO1PlGJvCn@coredump.intra.peff.net/
|
||||||
|
|
||||||
|
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||||
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||||
|
---
|
||||||
|
credential.c | 4 ++--
|
||||||
|
json-writer.c | 6 ++----
|
||||||
|
run-command.c | 5 ++---
|
||||||
|
strbuf.c | 4 ++--
|
||||||
|
strmap.c | 3 ++-
|
||||||
|
strvec.c | 5 ++---
|
||||||
|
6 files changed, 12 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/credential.c b/credential.c
|
||||||
|
index e5202fbef2..3c05c7c669 100644
|
||||||
|
--- a/credential.c
|
||||||
|
+++ b/credential.c
|
||||||
|
@@ -10,8 +10,8 @@
|
||||||
|
|
||||||
|
void credential_init(struct credential *c)
|
||||||
|
{
|
||||||
|
- memset(c, 0, sizeof(*c));
|
||||||
|
- c->helpers.strdup_strings = 1;
|
||||||
|
+ struct credential blank = CREDENTIAL_INIT;
|
||||||
|
+ memcpy(c, &blank, sizeof(*c));
|
||||||
|
}
|
||||||
|
|
||||||
|
void credential_clear(struct credential *c)
|
||||||
|
diff --git a/json-writer.c b/json-writer.c
|
||||||
|
index aadb9dbddc..f1cfd8fa8c 100644
|
||||||
|
--- a/json-writer.c
|
||||||
|
+++ b/json-writer.c
|
||||||
|
@@ -3,10 +3,8 @@
|
||||||
|
|
||||||
|
void jw_init(struct json_writer *jw)
|
||||||
|
{
|
||||||
|
- strbuf_init(&jw->json, 0);
|
||||||
|
- strbuf_init(&jw->open_stack, 0);
|
||||||
|
- jw->need_comma = 0;
|
||||||
|
- jw->pretty = 0;
|
||||||
|
+ struct json_writer blank = JSON_WRITER_INIT;
|
||||||
|
+ memcpy(jw, &blank, sizeof(*jw));;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jw_release(struct json_writer *jw)
|
||||||
|
diff --git a/run-command.c b/run-command.c
|
||||||
|
index be6bc128cd..8750df16d8 100644
|
||||||
|
--- a/run-command.c
|
||||||
|
+++ b/run-command.c
|
||||||
|
@@ -11,9 +11,8 @@
|
||||||
|
|
||||||
|
void child_process_init(struct child_process *child)
|
||||||
|
{
|
||||||
|
- memset(child, 0, sizeof(*child));
|
||||||
|
- argv_array_init(&child->args);
|
||||||
|
- argv_array_init(&child->env_array);
|
||||||
|
+ struct child_process blank = CHILD_PROCESS_INIT;
|
||||||
|
+ memcpy(child, &blank, sizeof(*child));
|
||||||
|
}
|
||||||
|
|
||||||
|
void child_process_clear(struct child_process *child)
|
||||||
|
diff --git a/strbuf.c b/strbuf.c
|
||||||
|
index 4df30b4549..c8a5789694 100644
|
||||||
|
--- a/strbuf.c
|
||||||
|
+++ b/strbuf.c
|
||||||
|
@@ -52,8 +52,8 @@ char strbuf_slopbuf[1];
|
||||||
|
|
||||||
|
void strbuf_init(struct strbuf *sb, size_t hint)
|
||||||
|
{
|
||||||
|
- sb->alloc = sb->len = 0;
|
||||||
|
- sb->buf = strbuf_slopbuf;
|
||||||
|
+ struct strbuf blank = STRBUF_INIT;
|
||||||
|
+ memcpy(sb, &blank, sizeof(*sb));
|
||||||
|
if (hint)
|
||||||
|
strbuf_grow(sb, hint);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
13
git.spec
13
git.spec
@ -1,7 +1,7 @@
|
|||||||
%global gitexecdir %{_libexecdir}/git-core
|
%global gitexecdir %{_libexecdir}/git-core
|
||||||
Name: git
|
Name: git
|
||||||
Version: 2.27.0
|
Version: 2.27.0
|
||||||
Release: 20
|
Release: 21
|
||||||
Summary: A popular and widely used Version Control System
|
Summary: A popular and widely used Version Control System
|
||||||
License: GPLv2+ or LGPLv2.1
|
License: GPLv2+ or LGPLv2.1
|
||||||
URL: https://git-scm.com/
|
URL: https://git-scm.com/
|
||||||
@ -74,6 +74,11 @@ Patch59: backport-CVE-2024-32465-wrapper.c-add-x-un-setenv-and-use-xsetenv-in
|
|||||||
Patch60: backport-CVE-2024-32465-upload-pack-disable-lazy-fetching-by-default.patch
|
Patch60: backport-CVE-2024-32465-upload-pack-disable-lazy-fetching-by-default.patch
|
||||||
Patch61: backport-CVE-2024-32002-dir-introduce-readdir_skip_dot_and_dotdot-helper.patch
|
Patch61: backport-CVE-2024-32002-dir-introduce-readdir_skip_dot_and_dotdot-helper.patch
|
||||||
Patch62: backport-CVE-2024-32002-submodules-submodule-paths-must-not-contain-symlinks.patch
|
Patch62: backport-CVE-2024-32002-submodules-submodule-paths-must-not-contain-symlinks.patch
|
||||||
|
Patch63: backport-pre-001-CVE-2024-52006.patch
|
||||||
|
Patch64: backport-pre-002-CVE-2024-52006.patch
|
||||||
|
Patch65: backport-CVE-2024-50349-credential_format-also-encode-host-port.patch
|
||||||
|
Patch66: backport-CVE-2024-50349-credential-sanitize-the-user-prompt.patch
|
||||||
|
Patch67: backport-CVE-2024-52006-credential-disallow-Carriage-Returns-in-the-protocol.patch
|
||||||
|
|
||||||
BuildRequires: gcc gettext
|
BuildRequires: gcc gettext
|
||||||
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre2-devel desktop-file-utils
|
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre2-devel desktop-file-utils
|
||||||
@ -323,6 +328,12 @@ make %{?_smp_mflags} test
|
|||||||
%{_mandir}/man7/git*.7.*
|
%{_mandir}/man7/git*.7.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Jan 15 2025 fuanan <fuanan3@h-partners.com> - 2.27.0-21
|
||||||
|
- Type:CVE
|
||||||
|
- ID:CVE-2024-50349 CVE-2024-52006
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:Fix CVE-2024-50349 CVE-2024-52006
|
||||||
|
|
||||||
* Tue May 21 2024 qiaojijun <qiaojijun@kylinos.cn> - 2.27.0-20
|
* Tue May 21 2024 qiaojijun <qiaojijun@kylinos.cn> - 2.27.0-20
|
||||||
- Type:CVE
|
- Type:CVE
|
||||||
- ID:CVE-2024-32002
|
- ID:CVE-2024-32002
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user