Merge branch 'debian-sid' into debian-stable-backports
* debian-sid:
debian: new upstream point release
Git 2.17.5
fsck: reject URL with empty host in .gitmodules
credential: treat URL with empty scheme as invalid
credential: treat URL without scheme as invalid
credential: die() when parsing invalid urls
fsck: convert gitmodules url to URL passed to curl
credential: refuse to operate when missing host or protocol
credential: parse URL without host as empty host, not unset
t0300: use more realistic inputs
t0300: make "quit" helper more realistic
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Change-Id: I3b448f1bd2a1df71fcbed55ed02a1d4108280330
diff --git a/Documentation/RelNotes/2.17.5.txt b/Documentation/RelNotes/2.17.5.txt
new file mode 100644
index 0000000..2abb821
--- /dev/null
+++ b/Documentation/RelNotes/2.17.5.txt
@@ -0,0 +1,22 @@
+Git v2.17.5 Release Notes
+=========================
+
+This release is to address a security issue: CVE-2020-11008
+
+Fixes since v2.17.4
+-------------------
+
+ * With a crafted URL that contains a newline or empty host, or lacks
+ a scheme, the credential helper machinery can be fooled into
+ providing credential information that is not appropriate for the
+ protocol in use and host being contacted.
+
+ Unlike the vulnerability CVE-2020-5260 fixed in v2.17.4, the
+ credentials are not for a host of the attacker's choosing; instead,
+ they are for some unspecified host (based on how the configured
+ credential helper handles an absent "host" parameter).
+
+ The attack has been made impossible by refusing to work with
+ under-specified credential patterns.
+
+Credit for finding the vulnerability goes to Carlo Arenas.
diff --git a/Documentation/RelNotes/2.18.4.txt b/Documentation/RelNotes/2.18.4.txt
new file mode 100644
index 0000000..e8ef858
--- /dev/null
+++ b/Documentation/RelNotes/2.18.4.txt
@@ -0,0 +1,5 @@
+Git v2.18.4 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.19.5.txt b/Documentation/RelNotes/2.19.5.txt
new file mode 100644
index 0000000..18a4dcb
--- /dev/null
+++ b/Documentation/RelNotes/2.19.5.txt
@@ -0,0 +1,5 @@
+Git v2.19.5 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.20.4.txt b/Documentation/RelNotes/2.20.4.txt
new file mode 100644
index 0000000..5a9e24e
--- /dev/null
+++ b/Documentation/RelNotes/2.20.4.txt
@@ -0,0 +1,5 @@
+Git v2.20.4 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.21.3.txt b/Documentation/RelNotes/2.21.3.txt
new file mode 100644
index 0000000..2ca0aa5
--- /dev/null
+++ b/Documentation/RelNotes/2.21.3.txt
@@ -0,0 +1,5 @@
+Git v2.21.3 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.22.4.txt b/Documentation/RelNotes/2.22.4.txt
new file mode 100644
index 0000000..8b5f3e3
--- /dev/null
+++ b/Documentation/RelNotes/2.22.4.txt
@@ -0,0 +1,5 @@
+Git v2.22.4 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.23.3.txt b/Documentation/RelNotes/2.23.3.txt
new file mode 100644
index 0000000..2e35490
--- /dev/null
+++ b/Documentation/RelNotes/2.23.3.txt
@@ -0,0 +1,5 @@
+Git v2.23.3 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.24.3.txt b/Documentation/RelNotes/2.24.3.txt
new file mode 100644
index 0000000..5302e0f
--- /dev/null
+++ b/Documentation/RelNotes/2.24.3.txt
@@ -0,0 +1,5 @@
+Git v2.24.3 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.25.4.txt b/Documentation/RelNotes/2.25.4.txt
new file mode 100644
index 0000000..0dbb5da
--- /dev/null
+++ b/Documentation/RelNotes/2.25.4.txt
@@ -0,0 +1,5 @@
+Git v2.25.4 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.26.2.txt b/Documentation/RelNotes/2.26.2.txt
new file mode 100644
index 0000000..d434d0c
--- /dev/null
+++ b/Documentation/RelNotes/2.26.2.txt
@@ -0,0 +1,5 @@
+Git v2.26.2 Release Notes
+=========================
+
+This release merges the security fix that appears in v2.17.5; see
+the release notes for that version for details.
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index a65cf74..dafe6d0 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.26.1
+DEF_VER=v2.26.2
LF='
'
diff --git a/RelNotes b/RelNotes
index 9ccd8ca..3427be6 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.26.1.txt
\ No newline at end of file
+Documentation/RelNotes/2.26.2.txt
\ No newline at end of file
diff --git a/credential.c b/credential.c
index 21b3ba1..108d9e1 100644
--- a/credential.c
+++ b/credential.c
@@ -88,6 +88,11 @@
struct urlmatch_config config = { STRING_LIST_INIT_DUP };
struct strbuf url = STRBUF_INIT;
+ if (!c->host)
+ die(_("refusing to work with credential missing host field"));
+ if (!c->protocol)
+ die(_("refusing to work with credential missing protocol field"));
+
if (c->configured)
return;
@@ -222,8 +227,11 @@
return 0;
}
-static void credential_write_item(FILE *fp, const char *key, const char *value)
+static void credential_write_item(FILE *fp, const char *key, const char *value,
+ int required)
{
+ if (!value && required)
+ BUG("credential value for %s is missing", key);
if (!value)
return;
if (strchr(value, '\n'))
@@ -233,11 +241,11 @@
void credential_write(const struct credential *c, FILE *fp)
{
- credential_write_item(fp, "protocol", c->protocol);
- credential_write_item(fp, "host", c->host);
- credential_write_item(fp, "path", c->path);
- credential_write_item(fp, "username", c->username);
- credential_write_item(fp, "password", c->password);
+ 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);
}
static int run_credential_helper(struct credential *c,
@@ -383,8 +391,11 @@
* (3) proto://<user>:<pass>@<host>/...
*/
proto_end = strstr(url, "://");
- if (!proto_end)
- return 0;
+ if (!proto_end || proto_end == url) {
+ if (!quiet)
+ warning(_("url has no scheme: %s"), url);
+ return -1;
+ }
cp = proto_end + 3;
at = strchr(cp, '@');
colon = strchr(cp, ':');
@@ -409,10 +420,8 @@
host = at + 1;
}
- if (proto_end - url > 0)
- c->protocol = xmemdupz(url, proto_end - url);
- if (slash - host > 0)
- c->host = url_decode_mem(host, slash - host);
+ c->protocol = xmemdupz(url, proto_end - url);
+ c->host = url_decode_mem(host, slash - host);
/* Trim leading and trailing slashes from path */
while (*slash == '/')
slash++;
@@ -436,8 +445,6 @@
void credential_from_url(struct credential *c, const char *url)
{
- if (credential_from_url_gently(c, url, 0) < 0) {
- warning(_("skipping credential lookup for url: %s"), url);
- credential_clear(c);
- }
+ if (credential_from_url_gently(c, url, 0) < 0)
+ die(_("credential url cannot be parsed: %s"), url);
}
diff --git a/debian/changelog b/debian/changelog
index a05ff4e..2d9ca65 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,37 @@
+git (1:2.26.2-1~bpo10+1) buster-backports; urgency=high
+
+ * upload to buster-backports.
+
+ -- Jonathan Nieder <jrnieder@gmail.com> Mon, 20 Apr 2020 11:23:20 -0700
+
+git (1:2.26.2-1) unstable; urgency=high
+
+ * new upstream point release (see RelNotes/2.26.2.txt).
+ * Addresses the security issue CVE-2020-11008.
+
+ With a crafted URL that contains a newline or empty host, or
+ lacks a scheme, the credential helper machinery can be fooled
+ into providing credential information that is not appropriate
+ for the protocol in use and host being contacted.
+
+ Unlike the vulnerability fixed in 2.26.1, the credentials are
+ not for a host of the attacker's choosing. Instead, they are
+ for an unspecified host, based on how the configured
+ credential helper handles an absent "host" parameter.
+
+ The attack has been made impossible by refusing to work with
+ underspecified credential patterns.
+
+ Thanks to Carlo Arenas for reporting that Git was still
+ vulnerable, Felix Wilhelm for providing the proof of concept
+ demonstrating this issue, and Jeff King for promptly providing
+ a corrected fix.
+
+ Tested using the proof of concept at
+ https://crbug.com/project-zero/2021.
+
+ -- Jonathan Nieder <jrnieder@gmail.com> Mon, 20 Apr 2020 10:44:09 -0700
+
git (1:2.26.1-1~bpo10+1) buster-backports; urgency=high
* upload to buster-backports.
diff --git a/debian/changelog.upstream b/debian/changelog.upstream
index 0722ed1..17d0ff5 100644
--- a/debian/changelog.upstream
+++ b/debian/changelog.upstream
@@ -1,3 +1,34 @@
+Version v2.26.2; changes since v2.26.1:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.26.1; changes since v2.26.0:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.26.0; changes since v2.26.0-rc2:
-------------------------------------------
@@ -162,7 +193,7 @@
remote-curl: show progress for fetches over dumb HTTP
-Version v2.26.0-rc0; changes since v2.25.2:
+Version v2.26.0-rc0; changes since v2.25.4:
-------------------------------------------
Abhishek Kumar (2):
@@ -588,6 +619,37 @@
credential: allow wildcard patterns when matching config
+Version v2.25.4; changes since v2.25.3:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.25.3; changes since v2.25.2:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.25.2; changes since v2.25.1:
---------------------------------------
@@ -870,7 +932,7 @@
Git 2.25-rc1
-Version v2.25.0-rc0; changes since v2.24.1:
+Version v2.25.0-rc0; changes since v2.24.3:
-------------------------------------------
Alban Gruin (6):
@@ -1475,6 +1537,40 @@
userdiff: add Elixir to supported userdiff languages
+Version v2.24.3; changes since v2.24.2:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.24.2; changes since v2.24.1:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Johannes Schindelin (1):
+ msvc: accommodate for vcpkg's upgrade to OpenSSL v1.1.x
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.24.1; changes since v2.24.0:
---------------------------------------
@@ -1668,7 +1764,7 @@
remote-curl: pass on atomic capability to remote side
-Version v2.24.0-rc0; changes since v2.23.1:
+Version v2.24.0-rc0; changes since v2.23.3:
-------------------------------------------
Adam Roben (1):
@@ -2291,6 +2387,37 @@
rebase tests: test linear branch topology
+Version v2.23.3; changes since v2.23.2:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.23.2; changes since v2.23.1:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.23.1; changes since v2.23.0:
---------------------------------------
@@ -2511,7 +2638,7 @@
t2203: avoid hard-coded object ID values
-Version v2.23.0-rc0; changes since v2.22.2:
+Version v2.23.0-rc0; changes since v2.22.4:
-------------------------------------------
Andrey Mazo (8):
@@ -2908,6 +3035,37 @@
clone: test for our behavior on odd objects/* content
+Version v2.22.4; changes since v2.22.3:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.22.3; changes since v2.22.2:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.22.2; changes since v2.22.1:
---------------------------------------
@@ -3369,7 +3527,7 @@
mingw: enable DEP and ASLR
-Version v2.22.0-rc0; changes since v2.21.1:
+Version v2.22.0-rc0; changes since v2.21.3:
-------------------------------------------
Alban Gruin (18):
@@ -4137,6 +4295,37 @@
trace2: fix up a missing "leave" entry point
+Version v2.21.3; changes since v2.21.2:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.21.2; changes since v2.21.1:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.21.1; changes since v2.21.0:
---------------------------------------
@@ -4360,7 +4549,7 @@
rebase: fix regression in rebase.useBuiltin=false test mode
-Version v2.21.0-rc0; changes since v2.20.2:
+Version v2.21.0-rc0; changes since v2.20.4:
-------------------------------------------
Arti Zirk (1):
@@ -4896,6 +5085,37 @@
diff-tree doc: correct & remove wrong documentation
+Version v2.20.4; changes since v2.20.3:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.20.3; changes since v2.20.2:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.20.2; changes since v2.20.1:
---------------------------------------
@@ -5124,7 +5344,7 @@
git-compat-util: prefer poll.h to sys/poll.h
-Version v2.20.0-rc0; changes since v2.19.3:
+Version v2.20.0-rc0; changes since v2.19.5:
-------------------------------------------
Aaron Lindsay (1):
@@ -5999,6 +6219,37 @@
tests: add a special setup where rebase.useBuiltin is off
+Version v2.19.5; changes since v2.19.4:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.19.4; changes since v2.19.3:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.19.3; changes since v2.19.2:
---------------------------------------
@@ -6384,7 +6635,7 @@
refactor various if (x) FREE_AND_NULL(x) to just FREE_AND_NULL(x)
-Version v2.19.0-rc0; changes since v2.18.2:
+Version v2.19.0-rc0; changes since v2.18.4:
-------------------------------------------
Aaron Schrab (1):
@@ -7215,6 +7466,37 @@
completion: complete remote names too
+Version v2.18.4; changes since v2.18.3:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.18.3; changes since v2.18.2:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.18.2; changes since v2.18.1:
---------------------------------------
@@ -7483,7 +7765,7 @@
t3430: test clean-up
-Version v2.18.0-rc0; changes since v2.17.3:
+Version v2.18.0-rc0; changes since v2.17.5:
-------------------------------------------
Anders Kaseorg (1):
@@ -8384,6 +8666,37 @@
get_short_oid: sort ambiguous objects by type, then SHA-1
+Version v2.17.5; changes since v2.17.4:
+---------------------------------------
+
+Jeff King (6):
+ t0300: make "quit" helper more realistic
+ t0300: use more realistic inputs
+ credential: parse URL without host as empty host, not unset
+ credential: refuse to operate when missing host or protocol
+ credential: die() when parsing invalid urls
+ Git 2.17.5
+
+Jonathan Nieder (4):
+ fsck: convert gitmodules url to URL passed to curl
+ credential: treat URL without scheme as invalid
+ credential: treat URL with empty scheme as invalid
+ fsck: reject URL with empty host in .gitmodules
+
+
+Version v2.17.4; changes since v2.17.3:
+---------------------------------------
+
+Jeff King (4):
+ credential: avoid writing values with newlines
+ t/lib-credential: use test_i18ncmp to check stderr
+ credential: detect unrepresentable values when parsing urls
+ fsck: detect gitmodules URLs with embedded newlines
+
+Junio C Hamano (1):
+ Git 2.17.4
+
+
Version v2.17.3; changes since v2.17.2:
---------------------------------------
diff --git a/debian/versions.upstream b/debian/versions.upstream
index 18733f0..224cac8 100644
--- a/debian/versions.upstream
+++ b/debian/versions.upstream
@@ -623,12 +623,16 @@
v2.17.1
v2.17.2
v2.17.3
+v2.17.4
+v2.17.5
v2.18.0-rc0
v2.18.0-rc1
v2.18.0-rc2
v2.18.0
v2.18.1
v2.18.2
+v2.18.3
+v2.18.4
v2.19.0-rc0
v2.19.0-rc1
v2.19.0-rc2
@@ -636,17 +640,23 @@
v2.19.1
v2.19.2
v2.19.3
+v2.19.4
+v2.19.5
v2.20.0-rc0
v2.20.0-rc1
v2.20.0-rc2
v2.20.0
v2.20.1
v2.20.2
+v2.20.3
+v2.20.4
v2.21.0-rc0
v2.21.0-rc1
v2.21.0-rc2
v2.21.0
v2.21.1
+v2.21.2
+v2.21.3
v2.22.0-rc0
v2.22.0-rc1
v2.22.0-rc2
@@ -654,23 +664,33 @@
v2.22.0
v2.22.1
v2.22.2
+v2.22.3
+v2.22.4
v2.23.0-rc0
v2.23.0-rc1
v2.23.0-rc2
v2.23.0
v2.23.1
+v2.23.2
+v2.23.3
v2.24.0-rc0
v2.24.0-rc1
v2.24.0-rc2
v2.24.0
v2.24.1
+v2.24.2
+v2.24.3
v2.25.0-rc0
v2.25.0-rc1
v2.25.0-rc2
v2.25.0
v2.25.1
v2.25.2
+v2.25.3
+v2.25.4
v2.26.0-rc0
v2.26.0-rc1
v2.26.0-rc2
v2.26.0
+v2.26.1
+v2.26.2
diff --git a/fsck.c b/fsck.c
index dc6f6ac..73f3077 100644
--- a/fsck.c
+++ b/fsck.c
@@ -9,6 +9,7 @@
#include "tag.h"
#include "fsck.h"
#include "refs.h"
+#include "url.h"
#include "utf8.h"
#include "decorate.h"
#include "oidset.h"
@@ -911,17 +912,147 @@
return ret;
}
+/*
+ * Like builtin/submodule--helper.c's starts_with_dot_slash, but without
+ * relying on the platform-dependent is_dir_sep helper.
+ *
+ * This is for use in checking whether a submodule URL is interpreted as
+ * relative to the current directory on any platform, since \ is a
+ * directory separator on Windows but not on other platforms.
+ */
+static int starts_with_dot_slash(const char *str)
+{
+ return str[0] == '.' && (str[1] == '/' || str[1] == '\\');
+}
+
+/*
+ * Like starts_with_dot_slash, this is a variant of submodule--helper's
+ * helper of the same name with the twist that it accepts backslash as a
+ * directory separator even on non-Windows platforms.
+ */
+static int starts_with_dot_dot_slash(const char *str)
+{
+ return str[0] == '.' && starts_with_dot_slash(str + 1);
+}
+
+static int submodule_url_is_relative(const char *url)
+{
+ return starts_with_dot_slash(url) || starts_with_dot_dot_slash(url);
+}
+
+/*
+ * Count directory components that a relative submodule URL should chop
+ * from the remote_url it is to be resolved against.
+ *
+ * In other words, this counts "../" components at the start of a
+ * submodule URL.
+ *
+ * Returns the number of directory components to chop and writes a
+ * pointer to the next character of url after all leading "./" and
+ * "../" components to out.
+ */
+static int count_leading_dotdots(const char *url, const char **out)
+{
+ int result = 0;
+ while (1) {
+ if (starts_with_dot_dot_slash(url)) {
+ result++;
+ url += strlen("../");
+ continue;
+ }
+ if (starts_with_dot_slash(url)) {
+ url += strlen("./");
+ continue;
+ }
+ *out = url;
+ return result;
+ }
+}
+/*
+ * Check whether a transport is implemented by git-remote-curl.
+ *
+ * If it is, returns 1 and writes the URL that would be passed to
+ * git-remote-curl to the "out" parameter.
+ *
+ * Otherwise, returns 0 and leaves "out" untouched.
+ *
+ * Examples:
+ * http::https://example.com/repo.git -> 1, https://example.com/repo.git
+ * https://example.com/repo.git -> 1, https://example.com/repo.git
+ * git://example.com/repo.git -> 0
+ *
+ * This is for use in checking for previously exploitable bugs that
+ * required a submodule URL to be passed to git-remote-curl.
+ */
+static int url_to_curl_url(const char *url, const char **out)
+{
+ /*
+ * We don't need to check for case-aliases, "http.exe", and so
+ * on because in the default configuration, is_transport_allowed
+ * prevents URLs with those schemes from being cloned
+ * automatically.
+ */
+ if (skip_prefix(url, "http::", out) ||
+ skip_prefix(url, "https::", out) ||
+ skip_prefix(url, "ftp::", out) ||
+ skip_prefix(url, "ftps::", out))
+ return 1;
+ if (starts_with(url, "http://") ||
+ starts_with(url, "https://") ||
+ starts_with(url, "ftp://") ||
+ starts_with(url, "ftps://")) {
+ *out = url;
+ return 1;
+ }
+ return 0;
+}
+
static int check_submodule_url(const char *url)
{
- struct credential c = CREDENTIAL_INIT;
- int ret;
+ const char *curl_url;
if (looks_like_command_line_option(url))
return -1;
- ret = credential_from_url_gently(&c, url, 1);
- credential_clear(&c);
- return ret;
+ if (submodule_url_is_relative(url)) {
+ char *decoded;
+ const char *next;
+ int has_nl;
+
+ /*
+ * This could be appended to an http URL and url-decoded;
+ * check for malicious characters.
+ */
+ decoded = url_decode(url);
+ has_nl = !!strchr(decoded, '\n');
+
+ free(decoded);
+ if (has_nl)
+ return -1;
+
+ /*
+ * URLs which escape their root via "../" can overwrite
+ * the host field and previous components, resolving to
+ * URLs like https::example.com/submodule.git and
+ * https:///example.com/submodule.git that were
+ * susceptible to CVE-2020-11008.
+ */
+ if (count_leading_dotdots(url, &next) > 0 &&
+ (*next == ':' || *next == '/'))
+ return -1;
+ }
+
+ else if (url_to_curl_url(url, &curl_url)) {
+ struct credential c = CREDENTIAL_INIT;
+ int ret = 0;
+ if (credential_from_url_gently(&c, curl_url, 1) ||
+ !*c.host)
+ ret = -1;
+ credential_clear(&c);
+ return ret;
+ }
+
+ return 0;
}
struct fsck_gitmodules_data {
diff --git a/http.c b/http.c
index 00a0e50..5f71263 100644
--- a/http.c
+++ b/http.c
@@ -558,6 +558,7 @@
return 0;
if (!cert_auth.password) {
cert_auth.protocol = xstrdup("cert");
+ cert_auth.host = xstrdup("");
cert_auth.username = xstrdup("");
cert_auth.path = xstrdup(ssl_cert);
credential_fill(&cert_auth);
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 5b78ebb..5555a15 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -22,6 +22,11 @@
exit 0
EOF
+ write_script git-credential-quit <<-\EOF &&
+ . ./dump
+ echo quit=1
+ EOF
+
write_script git-credential-verbatim <<-\EOF &&
user=$1; shift
pass=$1; shift
@@ -35,43 +40,71 @@
test_expect_success 'credential_fill invokes helper' '
check fill "verbatim foo bar" <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=foo
password=bar
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
EOF
'
test_expect_success 'credential_fill invokes multiple helpers' '
check fill useless "verbatim foo bar" <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=foo
password=bar
--
useless: get
+ useless: protocol=http
+ useless: host=example.com
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
EOF
'
test_expect_success 'credential_fill stops when we get a full response' '
check fill "verbatim one two" "verbatim three four" <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=one
password=two
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
EOF
'
test_expect_success 'credential_fill continues through partial response' '
check fill "verbatim one \"\"" "verbatim two three" <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=two
password=three
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: username=one
EOF
'
@@ -97,14 +130,20 @@
test_expect_success 'credential_approve calls all helpers' '
check approve useless "verbatim one two" <<-\EOF
+ protocol=http
+ host=example.com
username=foo
password=bar
--
--
useless: store
+ useless: protocol=http
+ useless: host=example.com
useless: username=foo
useless: password=bar
verbatim: store
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: username=foo
verbatim: password=bar
EOF
@@ -112,6 +151,8 @@
test_expect_success 'do not bother storing password-less credential' '
check approve useless <<-\EOF
+ protocol=http
+ host=example.com
username=foo
--
--
@@ -121,14 +162,20 @@
test_expect_success 'credential_reject calls all helpers' '
check reject useless "verbatim one two" <<-\EOF
+ protocol=http
+ host=example.com
username=foo
password=bar
--
--
useless: erase
+ useless: protocol=http
+ useless: host=example.com
useless: username=foo
useless: password=bar
verbatim: erase
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: username=foo
verbatim: password=bar
EOF
@@ -136,33 +183,49 @@
test_expect_success 'usernames can be preserved' '
check fill "verbatim \"\" three" <<-\EOF
+ protocol=http
+ host=example.com
username=one
--
+ protocol=http
+ host=example.com
username=one
password=three
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: username=one
EOF
'
test_expect_success 'usernames can be overridden' '
check fill "verbatim two three" <<-\EOF
+ protocol=http
+ host=example.com
username=one
--
+ protocol=http
+ host=example.com
username=two
password=three
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
verbatim: username=one
EOF
'
test_expect_success 'do not bother completing already-full credential' '
check fill "verbatim three four" <<-\EOF
+ protocol=http
+ host=example.com
username=one
password=two
--
+ protocol=http
+ host=example.com
username=one
password=two
--
@@ -174,23 +237,31 @@
# askpass helper is run, we know the internal getpass is working.
test_expect_success 'empty helper list falls back to internal getpass' '
check fill <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=askpass-username
password=askpass-password
--
- askpass: Username:
- askpass: Password:
+ askpass: Username for '\''http://example.com'\'':
+ askpass: Password for '\''http://askpass-username@example.com'\'':
EOF
'
test_expect_success 'internal getpass does not ask for known username' '
check fill <<-\EOF
+ protocol=http
+ host=example.com
username=foo
--
+ protocol=http
+ host=example.com
username=foo
password=askpass-password
--
- askpass: Password:
+ askpass: Password for '\''http://foo@example.com'\'':
EOF
'
@@ -202,7 +273,11 @@
test_expect_success 'respect configured credentials' '
test_config credential.helper "$HELPER" &&
check fill <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=foo
password=bar
--
@@ -419,35 +494,85 @@
test_expect_success 'helpers can abort the process' '
test_must_fail git \
- -c credential.helper="!f() { echo quit=1; }; f" \
+ -c credential.helper=quit \
-c credential.helper="verbatim foo bar" \
- credential fill >stdout &&
- test_must_be_empty stdout
+ credential fill >stdout 2>stderr <<-\EOF &&
+ protocol=http
+ host=example.com
+ EOF
+ test_must_be_empty stdout &&
+ cat >expect <<-\EOF &&
+ quit: get
+ quit: protocol=http
+ quit: host=example.com
+ fatal: credential helper '\''quit'\'' told us to quit
+ EOF
+ test_i18ncmp expect stderr
'
test_expect_success 'empty helper spec resets helper list' '
test_config credential.helper "verbatim file file" &&
check fill "" "verbatim cmdline cmdline" <<-\EOF
+ protocol=http
+ host=example.com
--
+ protocol=http
+ host=example.com
username=cmdline
password=cmdline
--
verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
EOF
'
-test_expect_success 'url parser ignores embedded newlines' '
- check fill <<-EOF
+test_expect_success 'url parser rejects embedded newlines' '
+ test_must_fail git credential fill 2>stderr <<-\EOF &&
url=https://one.example.com?%0ahost=two.example.com/
- --
- username=askpass-username
- password=askpass-password
- --
- warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
- warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
- askpass: Username:
- askpass: Password:
EOF
+ cat >expect <<-\EOF &&
+ warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
+ fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/
+ EOF
+ test_i18ncmp expect stderr
+'
+
+test_expect_success 'host-less URLs are parsed as empty host' '
+ check fill "verbatim foo bar" <<-\EOF
+ url=cert:///path/to/cert.pem
+ --
+ protocol=cert
+ host=
+ path=path/to/cert.pem
+ username=foo
+ password=bar
+ --
+ verbatim: get
+ verbatim: protocol=cert
+ verbatim: host=
+ verbatim: path=path/to/cert.pem
+ EOF
+'
+
+test_expect_success 'credential system refuses to work with missing host' '
+ test_must_fail git credential fill 2>stderr <<-\EOF &&
+ protocol=http
+ EOF
+ cat >expect <<-\EOF &&
+ fatal: refusing to work with credential missing host field
+ EOF
+ test_i18ncmp expect stderr
+'
+
+test_expect_success 'credential system refuses to work with missing protocol' '
+ test_must_fail git credential fill 2>stderr <<-\EOF &&
+ host=example.com
+ EOF
+ cat >expect <<-\EOF &&
+ fatal: refusing to work with credential missing protocol field
+ EOF
+ test_i18ncmp expect stderr
'
test_done
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index b811d89..ea2688b 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -321,11 +321,17 @@
'
test_expect_success 'remote-http complains cleanly about malformed urls' '
- # do not actually issue "list" or other commands, as we do not
- # want to rely on what curl would actually do with such a broken
- # URL. This is just about making sure we do not segfault during
- # initialization.
- test_must_fail git remote-http http::/example.com/repo.git
+ test_must_fail git remote-http http::/example.com/repo.git 2>stderr &&
+ test_i18ngrep "url has no scheme" stderr
+'
+
+# NEEDSWORK: Writing commands to git-remote-curl can race against the latter
+# erroring out, producing SIGPIPE. Remove "ok=sigpipe" once transport-helper has
+# learned to handle early remote helper failures more cleanly.
+test_expect_success 'remote-http complains cleanly about empty scheme' '
+ test_must_fail ok=sigpipe git ls-remote \
+ http::${HTTPD_URL#http}/dumb/repo.git 2>stderr &&
+ test_i18ngrep "url has no scheme" stderr
'
test_expect_success 'redirects can be forbidden/allowed' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 41431b1..eec96e0 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -60,6 +60,116 @@
test_i18ngrep ! "unknown option" err
'
+test_expect_success 'fsck rejects missing URL scheme' '
+ git checkout --orphan missing-scheme &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = http::one.example.com/foo.git
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "gitmodules with missing URL scheme" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck rejects relative URL resolving to missing scheme' '
+ git checkout --orphan relative-missing-scheme &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = "..\\../.\\../:one.example.com/foo.git"
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "gitmodules with relative URL that strips off scheme" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck rejects empty URL scheme' '
+ git checkout --orphan empty-scheme &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = http::://one.example.com/foo.git
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "gitmodules with empty URL scheme" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck rejects relative URL resolving to empty scheme' '
+ git checkout --orphan relative-empty-scheme &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = ../../../:://one.example.com/foo.git
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "relative gitmodules URL resolving to empty scheme" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck rejects empty hostname' '
+ git checkout --orphan empty-host &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = http:///one.example.com/foo.git
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "gitmodules with extra slashes" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck rejects relative url that produced empty hostname' '
+ git checkout --orphan messy-relative &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = ../../..//one.example.com/foo.git
+ EOF
+ git add .gitmodules &&
+ test_tick &&
+ git commit -m "gitmodules abusing relative_path" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
+test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
+ git checkout --orphan newscheme &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = "data://acjbkd%0akajfdickajkd"
+ EOF
+ git add .gitmodules &&
+ git commit -m "gitmodules with unrecognized scheme" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ git push dst HEAD
+'
+
test_expect_success 'fsck rejects embedded newline in url' '
# create an orphan branch to avoid existing .gitmodules objects
git checkout --orphan newline &&
@@ -76,4 +186,19 @@
grep gitmodulesUrl err
'
+test_expect_success 'fsck rejects embedded newline in relative url' '
+ git checkout --orphan relative-newline &&
+ cat >.gitmodules <<-\EOF &&
+ [submodule "foo"]
+ url = "./%0ahost=two.example.com/foo.git"
+ EOF
+ git add .gitmodules &&
+ git commit -m "relative url with newline" &&
+ test_when_finished "rm -rf dst" &&
+ git init --bare dst &&
+ git -C dst config transfer.fsckObjects true &&
+ test_must_fail git push dst HEAD 2>err &&
+ grep gitmodulesUrl err
+'
+
test_done