summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch')
-rw-r--r--meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch156
1 files changed, 156 insertions, 0 deletions
diff --git a/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch b/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch
new file mode 100644
index 0000000000..a9b7348ef7
--- /dev/null
+++ b/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch
@@ -0,0 +1,156 @@
1From 43803880b954a020dbffa5250a5b7fd893442c7c Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Thu, 12 Mar 2020 01:31:11 -0400
4Subject: [PATCH 02/12] credential: detect unrepresentable values when parsing
5 urls
6
7The credential protocol can't represent newlines in values, but URLs can
8embed percent-encoded newlines in various components. A previous commit
9taught the low-level writing routines to die() when encountering this,
10but we can be a little friendlier to the user by detecting them earlier
11and handling them gracefully.
12
13This patch teaches credential_from_url() to notice such components,
14issue a warning, and blank the credential (which will generally result
15in prompting the user for a username and password). We blank the whole
16credential in this case. Another option would be to blank only the
17invalid component. However, we're probably better off not feeding a
18partially-parsed URL result to a credential helper. We don't know how a
19given helper would handle it, so we're better off to err on the side of
20matching nothing rather than something unexpected.
21
22The die() call in credential_write() is _probably_ impossible to reach
23after this patch. Values should end up in credential structs only by URL
24parsing (which is covered here), or by reading credential protocol input
25(which by definition cannot read a newline into a value). But we should
26definitely keep the low-level check, as it's our final and most accurate
27line of defense against protocol injection attacks. Arguably it could
28become a BUG(), but it probably doesn't matter much either way.
29
30Note that the public interface of credential_from_url() grows a little
31more than we need here. We'll use the extra flexibility in a future
32patch to help fsck catch these cases.
33
34Upstream-Status: Backport
35
36Signed-off-by: Li Zhou <li.zhou@windriver.com>
37---
38 credential.c | 36 ++++++++++++++++++++++++++++++++++--
39 credential.h | 16 ++++++++++++++++
40 t/t0300-credentials.sh | 12 ++++++++++--
41 3 files changed, 60 insertions(+), 4 deletions(-)
42
43diff --git a/credential.c b/credential.c
44index a79aff0..2482382 100644
45--- a/credential.c
46+++ b/credential.c
47@@ -324,7 +324,22 @@ void credential_reject(struct credential *c)
48 c->approved = 0;
49 }
50
51-void credential_from_url(struct credential *c, const char *url)
52+static int check_url_component(const char *url, int quiet,
53+ const char *name, const char *value)
54+{
55+ if (!value)
56+ return 0;
57+ if (!strchr(value, '\n'))
58+ return 0;
59+
60+ if (!quiet)
61+ warning(_("url contains a newline in its %s component: %s"),
62+ name, url);
63+ return -1;
64+}
65+
66+int credential_from_url_gently(struct credential *c, const char *url,
67+ int quiet)
68 {
69 const char *at, *colon, *cp, *slash, *host, *proto_end;
70
71@@ -338,7 +353,7 @@ void credential_from_url(struct credential *c, const char *url)
72 */
73 proto_end = strstr(url, "://");
74 if (!proto_end)
75- return;
76+ return 0;
77 cp = proto_end + 3;
78 at = strchr(cp, '@');
79 colon = strchr(cp, ':');
80@@ -373,4 +388,21 @@ void credential_from_url(struct credential *c, const char *url)
81 while (p > c->path && *p == '/')
82 *p-- = '\0';
83 }
84+
85+ if (check_url_component(url, quiet, "username", c->username) < 0 ||
86+ check_url_component(url, quiet, "password", c->password) < 0 ||
87+ check_url_component(url, quiet, "protocol", c->protocol) < 0 ||
88+ check_url_component(url, quiet, "host", c->host) < 0 ||
89+ check_url_component(url, quiet, "path", c->path) < 0)
90+ return -1;
91+
92+ return 0;
93+}
94+
95+void credential_from_url(struct credential *c, const char *url)
96+{
97+ if (credential_from_url_gently(c, url, 0) < 0) {
98+ warning(_("skipping credential lookup for url: %s"), url);
99+ credential_clear(c);
100+ }
101 }
102diff --git a/credential.h b/credential.h
103index 6b0cd16..122a23c 100644
104--- a/credential.h
105+++ b/credential.h
106@@ -28,7 +28,23 @@ struct credential {
107
108 int credential_read(struct credential *, FILE *);
109 void credential_write(const struct credential *, FILE *);
110+
111+/*
112+ * Parse a url into a credential struct, replacing any existing contents.
113+ *
114+ * Ifthe url can't be parsed (e.g., a missing "proto://" component), the
115+ * resulting credential will be empty but we'll still return success from the
116+ * "gently" form.
117+ *
118+ * If we encounter a component which cannot be represented as a credential
119+ * value (e.g., because it contains a newline), the "gently" form will return
120+ * an error but leave the broken state in the credential object for further
121+ * examination. The non-gentle form will issue a warning to stderr and return
122+ * an empty credential.
123+ */
124 void credential_from_url(struct credential *, const char *url);
125+int credential_from_url_gently(struct credential *, const char *url, int quiet);
126+
127 int credential_match(const struct credential *have,
128 const struct credential *want);
129
130diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
131index 26f3c3a..b9c0f1f 100755
132--- a/t/t0300-credentials.sh
133+++ b/t/t0300-credentials.sh
134@@ -308,9 +308,17 @@ test_expect_success 'empty helper spec resets helper list' '
135 EOF
136 '
137
138-test_expect_success 'url parser rejects embedded newlines' '
139- test_must_fail git credential fill <<-\EOF
140+test_expect_success 'url parser ignores embedded newlines' '
141+ check fill <<-EOF
142 url=https://one.example.com?%0ahost=two.example.com/
143+ --
144+ username=askpass-username
145+ password=askpass-password
146+ --
147+ warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
148+ warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
149+ askpass: Username:
150+ askpass: Password:
151 EOF
152 '
153
154--
1551.9.1
156