From patchwork Thu Feb 20 02:24:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "brian m. carlson" X-Patchwork-Id: 11393067 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A5A3817EF for ; Thu, 20 Feb 2020 02:24:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7BAEA24673 for ; Thu, 20 Feb 2020 02:24:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (3072-bit key) header.d=crustytoothpaste.net header.i=@crustytoothpaste.net header.b="WU5obRMH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727648AbgBTCYh (ORCPT ); Wed, 19 Feb 2020 21:24:37 -0500 Received: from injection.crustytoothpaste.net ([192.241.140.119]:36864 "EHLO injection.crustytoothpaste.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727370AbgBTCYh (ORCPT ); Wed, 19 Feb 2020 21:24:37 -0500 Received: from camp.crustytoothpaste.net (unknown [IPv6:2001:470:b978:101:b610:a2f0:36c1:12e3]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by injection.crustytoothpaste.net (Postfix) with ESMTPSA id 1B9706079B; Thu, 20 Feb 2020 02:24:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crustytoothpaste.net; s=default; t=1582165476; bh=x6L+iTpAy3iVbbRDBWTz5ODDwRuokTKLNPNkE+nAkS4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Reply-To: Subject:Date:To:CC:Resent-Date:Resent-From:Resent-To:Resent-Cc: In-Reply-To:References:Content-Type:Content-Disposition; b=WU5obRMHgr8/ZZ/cuNHtEJ5EzCaRX1KXSQVzoXw6Q5wdJcedZIbDUZNdXLG1BIfro iaTEcWZBtWadeoktJV7MccG3F0rD1dGjf7RPv79H5SEswR8e1/nsWdOqvucshvTypZ FgqiVitUaq5bSlLjoHyEXXyHzONLMdWxM86RafKArK9VDxGiYxGxOeMCE+F3LtwCW4 zKtLycY2b/3k92S9/SkGEwgGN7xOr5OXb8jHCA8ruqCr/oqBtLR40AzpBR3dNcT/2w gVxb6EtPAdh/Go7i4Et3oGDNwRYAGdUVvfphNQAlQgwQMgOvAxYg93vbAfaor/3X7w ET6RiYLflmGJtS2PApNvz1XNuAFaR4xZFha9bwGOjUluvTBKkGzWzdNAhiR4aZRsUT WPYiGcU7R+OKiEy5Xcor4waMOCFY9I6IPcTSCzBzBW0Do5NbrRwWrWCLEsuHi5Tlcj zBpoh2tGSHyLR18Zu3FPja9m6LIRAUqW8NMm4AQGXqmjuxRswX1 From: "brian m. carlson" To: Cc: Jeff King Subject: [PATCH v2 1/5] mailmap: add an additional email address for brian m. carlson Date: Thu, 20 Feb 2020 02:24:09 +0000 Message-Id: <20200220022413.258026-2-sandals@crustytoothpaste.net> X-Mailer: git-send-email 2.25.1.481.gfbce0eb801 In-Reply-To: <20200220022413.258026-1-sandals@crustytoothpaste.net> References: <20200220022413.258026-1-sandals@crustytoothpaste.net> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: brian m. carlson To more accurately track the provenance of contributions, brian uses a work email address for commits created at work. Add this email address to .mailmap so that contributions are properly attributed to the same person. Signed-off-by: brian m. carlson --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 73fd92e192..bde7aba756 100644 --- a/.mailmap +++ b/.mailmap @@ -31,6 +31,7 @@ Brandon Casey Brandon Williams brian m. carlson brian m. carlson +brian m. carlson Bryan Larsen Bryan Larsen Cheng Renquan From patchwork Thu Feb 20 02:24:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "brian m. carlson" X-Patchwork-Id: 11393071 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DF27417EF for ; Thu, 20 Feb 2020 02:24:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B60D624671 for ; Thu, 20 Feb 2020 02:24:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (3072-bit key) header.d=crustytoothpaste.net header.i=@crustytoothpaste.net header.b="BcXonqKD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727801AbgBTCYj (ORCPT ); Wed, 19 Feb 2020 21:24:39 -0500 Received: from injection.crustytoothpaste.net ([192.241.140.119]:36868 "EHLO injection.crustytoothpaste.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727291AbgBTCYh (ORCPT ); Wed, 19 Feb 2020 21:24:37 -0500 Received: from camp.crustytoothpaste.net (unknown [IPv6:2001:470:b978:101:b610:a2f0:36c1:12e3]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by injection.crustytoothpaste.net (Postfix) with ESMTPSA id 838A36079C; Thu, 20 Feb 2020 02:24:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crustytoothpaste.net; s=default; t=1582165476; bh=tUKafEHjcepxODMGUUwamIB7uUBqCvgbU4tAT+rHV7k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Reply-To: Subject:Date:To:CC:Resent-Date:Resent-From:Resent-To:Resent-Cc: In-Reply-To:References:Content-Type:Content-Disposition; b=BcXonqKDw10InRwBb4kfsVv1z69FgiUFFBc+pU4EgEg1zWepsaWC5FXrs5Q9SzrtW 9/6H8h2/HrkU3sLFppK8qmUe7sxDuDuet+QzfziGllutlMndFZjrcl2rwpnHPcNT3Y UJ8eTOBeUt8FsXW9dNsc5zUKo9fMav5SPhyvBUuG7s7ViqKUYuGk5odLugakUWn5cF OJovuskK5cl5UTN+rkr62ykkhzzJqP3/n+9/dHnS7gkD6FVFtNx7n6YfOchOR4/KYZ 9SMgHFgdy3Asz7Ivw48VhB8eVKKAx2shcvun9UjeKwbkekn1ME7X3ecnY3rJzKsq/G bMlzPCSXWcVL1A8dEAh/fXmttCzBawGgBHcFgFnblvBGIw6Q8KTb1Rn/z5RGSdtCSs b1UssZeF+oAwq8HDua0OThQkewpRgjBWSfWZy8NmBRcuh3in4jUaudc8Xf+Rtm+sSn 63PzvNi3zznlbT3gVCMke7GLiFX+aAwkDDVFT6yY7aAL/AsIwgF From: "brian m. carlson" To: Cc: Jeff King Subject: [PATCH v2 2/5] t1300: add test for urlmatch with multiple wildcards Date: Thu, 20 Feb 2020 02:24:10 +0000 Message-Id: <20200220022413.258026-3-sandals@crustytoothpaste.net> X-Mailer: git-send-email 2.25.1.481.gfbce0eb801 In-Reply-To: <20200220022413.258026-1-sandals@crustytoothpaste.net> References: <20200220022413.258026-1-sandals@crustytoothpaste.net> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: brian m. carlson Our urlmatch code handles multiple wildcards, but we don't currently have a test that checks this code path. Add a test that we handle this case correctly to avoid any regressions. Signed-off-by: brian m. carlson --- t/t1300-config.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 5464c46c18..97ebfe1f9d 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1408,6 +1408,8 @@ test_expect_success 'urlmatch favors more specific URLs' ' cookieFile = /tmp/wildcard.txt [http "https://*.example.com/wildcardwithsubdomain"] cookieFile = /tmp/wildcardwithsubdomain.txt + [http "https://*.example.*"] + cookieFile = /tmp/multiwildcard.txt [http "https://trailing.example.com"] cookieFile = /tmp/trailing.txt [http "https://user@*.example.com/"] @@ -1454,6 +1456,10 @@ test_expect_success 'urlmatch favors more specific URLs' ' echo http.cookiefile /tmp/sub.txt >expect && git config --get-urlmatch HTTP https://user@sub.example.com >actual && + test_cmp expect actual && + + echo http.cookiefile /tmp/multiwildcard.txt >expect && + git config --get-urlmatch HTTP https://wildcard.example.org >actual && test_cmp expect actual ' From patchwork Thu Feb 20 02:24:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "brian m. carlson" X-Patchwork-Id: 11393073 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3456913A4 for ; Thu, 20 Feb 2020 02:24:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1589624671 for ; Thu, 20 Feb 2020 02:24:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (3072-bit key) header.d=crustytoothpaste.net header.i=@crustytoothpaste.net header.b="ZWSHy/Ha" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727727AbgBTCYj (ORCPT ); Wed, 19 Feb 2020 21:24:39 -0500 Received: from injection.crustytoothpaste.net ([192.241.140.119]:36870 "EHLO injection.crustytoothpaste.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727476AbgBTCYi (ORCPT ); Wed, 19 Feb 2020 21:24:38 -0500 Received: from camp.crustytoothpaste.net (unknown [IPv6:2001:470:b978:101:b610:a2f0:36c1:12e3]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by injection.crustytoothpaste.net (Postfix) with ESMTPSA id EA4BF609CF; Thu, 20 Feb 2020 02:24:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crustytoothpaste.net; s=default; t=1582165477; bh=Zbi7iUCs9WhQX0Liy/cCTUqWMrsXcVXnsNcCJQuTdeY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Reply-To: Subject:Date:To:CC:Resent-Date:Resent-From:Resent-To:Resent-Cc: In-Reply-To:References:Content-Type:Content-Disposition; b=ZWSHy/HaiMErvAodZAU4rL2fr+YjoNrIfSWupSwaV3FDBQNZGSA9eSed7yl7S+0Gm aAg80zHXxOK0ftPUTd9fNCPsCYUFm5XV8FZrAo11EcTTxGeH6/K83/2vhqyifBGohy r1seke7ZsXRrNLUH/15w1g6QUwItFDDsb1X4jfWzbWlfEKViW0UE6S2Sl0n2fDrtrv x6ig6XQGSPp0kEDlaNcGxuMYK52MTzElXgq6wptojEelm8ull6qjsR+3cSpFk9wRkl FzN/hQR0G3Zqn2TMss5OND0M4JEB0zvi7xzuJj0M4f37W3aeWurq5x8tuiDhYXhYjN k3hPy3TYQjQgbhEG2pX1LgPkdjDXAOciVui9HFICI6l209lRDRDJIS3suxnW0gMbtF f/42dU+UiolRDjjA3m+hZXOhLd2TlWNW3ZFO/Xa8p5ekgQwwut05rcCHgtDeJWhYHJ fc18TfT8BCCYwS4dtXThw6/nlEcLdkj7rbQapgqpiHMaATwckxN From: "brian m. carlson" To: Cc: Jeff King Subject: [PATCH v2 3/5] t0300: add tests for some additional cases Date: Thu, 20 Feb 2020 02:24:11 +0000 Message-Id: <20200220022413.258026-4-sandals@crustytoothpaste.net> X-Mailer: git-send-email 2.25.1.481.gfbce0eb801 In-Reply-To: <20200220022413.258026-1-sandals@crustytoothpaste.net> References: <20200220022413.258026-1-sandals@crustytoothpaste.net> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: brian m. carlson There are some tricky cases in our credential helpers that we don't have test cases for. To help prevent regressions, let's add some for these cases: * If there are multiple configured credential helpers, one without a path and one with a path, we want to invoke both of them. * If there are percent-encoded values in the URL, we handle them properly. * And finally, if there is a username in the remote URL, we want to honor that over what the configuration tells us. Finally, there's an additional case that we'd like to test for as well, but that currently fails. In all other situations in our configuration, we pick the last configuration setting that's provided. However, we fail to do that for credential.username, where we pick the first setting instead. Let's add a failing test that we have the consistent behavior here, since that's the documented, expected behavior. Signed-off-by: brian m. carlson --- t/t0300-credentials.sh | 108 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 82eaaea0f4..4593a0cd3d 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -240,6 +240,57 @@ test_expect_success 'do not match configured credential' ' EOF ' +test_expect_success 'match multiple configured helpers' ' + test_config credential.helper "verbatim \"\" \"\"" && + test_config credential.https://example.com.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=example.com + path=repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + +test_expect_success 'match multiple configured helpers with URLs' ' + test_config credential.https://example.com/repo.git.helper "verbatim \"\" \"\"" && + test_config credential.https://example.com.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=example.com + path=repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + +test_expect_success 'match percent-encoded values' ' + test_config credential.https://example.com/%2566.git.helper "$HELPER" && + check fill <<-\EOF + url=https://example.com/%2566.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + EOF +' + test_expect_success 'pull username from config' ' test_config credential.https://example.com.username foo && check fill <<-\EOF @@ -255,6 +306,63 @@ test_expect_success 'pull username from config' ' EOF ' +test_expect_success 'honors username from URL over helper (URL)' ' + test_config credential.https://example.com.username bob && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + url=https://alice@example.com + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + +test_expect_success 'honors username from URL over helper (components)' ' + test_config credential.https://example.com.username bob && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + protocol=https + host=example.com + username=alice + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + +test_expect_failure 'last matching username wins' ' + test_config credential.https://example.com/path.git.username bob && + test_config credential.https://example.com.username alice && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + url=https://example.com/path.git + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + test_expect_success 'http paths can be part of context' ' check fill "verbatim foo bar" <<-\EOF && protocol=https From patchwork Thu Feb 20 02:24:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "brian m. carlson" X-Patchwork-Id: 11393069 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4A9A613A4 for ; Thu, 20 Feb 2020 02:24:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2BF8E24670 for ; Thu, 20 Feb 2020 02:24:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (3072-bit key) header.d=crustytoothpaste.net header.i=@crustytoothpaste.net header.b="1hQzxZnt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727786AbgBTCYj (ORCPT ); Wed, 19 Feb 2020 21:24:39 -0500 Received: from injection.crustytoothpaste.net ([192.241.140.119]:36874 "EHLO injection.crustytoothpaste.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727370AbgBTCYi (ORCPT ); Wed, 19 Feb 2020 21:24:38 -0500 Received: from camp.crustytoothpaste.net (unknown [IPv6:2001:470:b978:101:b610:a2f0:36c1:12e3]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by injection.crustytoothpaste.net (Postfix) with ESMTPSA id 5E748609D3; Thu, 20 Feb 2020 02:24:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crustytoothpaste.net; s=default; t=1582165477; bh=cyN8Yrdhl1vk3x6bkWZcXAjr2EMB4rP/WfmINvg/Dbk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Reply-To: Subject:Date:To:CC:Resent-Date:Resent-From:Resent-To:Resent-Cc: In-Reply-To:References:Content-Type:Content-Disposition; b=1hQzxZntai33pMZQQl6zs1gve3lO+jpiecOuxdlVDyLO1dWnhv6OHU3UWBamABYj7 lPIUZgJG7Fv6tEN5+y5VbekAHkLeD9spmHm5lrR68M0/cZNRklVktaFdxKLg+kS0wy TT1szCJktVnvIoOIYvGzHwjAsq5jd8k2T/xZ7BH+U8z5+krrJEkLKsWjTvFM4PVDxo puhIdK5rKBeAjxQFYvv3Ovr0528yZ92+Sxo9YC+v8PxGVR95Zt0J3TDdw5135Kh4Cl NhMoIrMykJPKXvVtGWZxfCY+Dv7Rh/XasmbvE7UQ2Ew7owlkh6p+/6oztiWZ5ExsbT fhtltpqdKmqwaGOunDccVFa3EysNdZJYYTrfZt5i3YZjDMErxSx7wSgLrta7E+61Be CGFvqvi75VxyehEdZescz5QmTikYBGkcK9TGwXuvTG6vPYxMDm5MrjU4B2WCyS0hQB gv0/Hh5w4MfMtbIarlj7Y/AVRlwJbhv2JKOf2KdBsq6euLu2l0t From: "brian m. carlson" To: Cc: Jeff King Subject: [PATCH v2 4/5] credential: use the last matching username in the config Date: Thu, 20 Feb 2020 02:24:12 +0000 Message-Id: <20200220022413.258026-5-sandals@crustytoothpaste.net> X-Mailer: git-send-email 2.25.1.481.gfbce0eb801 In-Reply-To: <20200220022413.258026-1-sandals@crustytoothpaste.net> References: <20200220022413.258026-1-sandals@crustytoothpaste.net> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: brian m. carlson Everywhere else in the codebase, we use the rule that the last matching configuration option is the one that takes effect. This is helpful because it allows more specific configuration settings (e.g., per-repo configuration) to override less specific settings (e.g., per-user configuration). However, in the credential code, we didn't honor this setting, and instead picked the first setting we had, and stuck with it. This was likely to ensure we picked the value from the URL, which we want to honor over the configuration. It's possible to do both, though, so let's check if the value is the one we've gotten over our protocol connection, which if present will have come from the URL, and keep it if so. Otherwise, let's overwrite the value with the latest version we've got from the configuration, so we keep the last configuration value. Signed-off-by: brian m. carlson --- credential.c | 9 ++++++++- credential.h | 3 ++- t/t0300-credentials.sh | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/credential.c b/credential.c index 62be651b03..5701e32792 100644 --- a/credential.c +++ b/credential.c @@ -71,8 +71,10 @@ static int credential_config_callback(const char *var, const char *value, else string_list_clear(&c->helpers, 0); } else if (!strcmp(key, "username")) { - if (!c->username) + if (!c->username_from_proto) { + free(c->username); c->username = xstrdup(value); + } } else if (!strcmp(key, "usehttppath")) c->use_http_path = git_config_bool(var, value); @@ -163,6 +165,7 @@ int credential_read(struct credential *c, FILE *fp) if (!strcmp(key, "username")) { free(c->username); c->username = xstrdup(value); + c->username_from_proto = 1; } else if (!strcmp(key, "password")) { free(c->password); c->password = xstrdup(value); @@ -349,10 +352,14 @@ void credential_from_url(struct credential *c, const char *url) else if (!colon || at <= colon) { /* Case (2) */ c->username = url_decode_mem(cp, at - cp); + if (c->username && *c->username) + c->username_from_proto = 1; host = at + 1; } else { /* Case (3) */ c->username = url_decode_mem(cp, colon - cp); + if (c->username && *c->username) + c->username_from_proto = 1; c->password = url_decode_mem(colon + 1, at - (colon + 1)); host = at + 1; } diff --git a/credential.h b/credential.h index a5a3ee9bb8..fec7815dd0 100644 --- a/credential.h +++ b/credential.h @@ -118,7 +118,8 @@ struct credential { unsigned approved:1, configured:1, quit:1, - use_http_path:1; + use_http_path:1, + username_from_proto:1; char *username; char *password; diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 4593a0cd3d..8f87599056 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -344,7 +344,7 @@ test_expect_success 'honors username from URL over helper (components)' ' EOF ' -test_expect_failure 'last matching username wins' ' +test_expect_success 'last matching username wins' ' test_config credential.https://example.com/path.git.username bob && test_config credential.https://example.com.username alice && test_config credential.https://example.com.helper "verbatim \"\" bar" && From patchwork Thu Feb 20 02:24:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "brian m. carlson" X-Patchwork-Id: 11393075 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2F3AC930 for ; Thu, 20 Feb 2020 02:24:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0932724670 for ; Thu, 20 Feb 2020 02:24:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (3072-bit key) header.d=crustytoothpaste.net header.i=@crustytoothpaste.net header.b="h4YgD2FH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727421AbgBTCYn (ORCPT ); Wed, 19 Feb 2020 21:24:43 -0500 Received: from injection.crustytoothpaste.net ([192.241.140.119]:36878 "EHLO injection.crustytoothpaste.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727691AbgBTCYj (ORCPT ); Wed, 19 Feb 2020 21:24:39 -0500 Received: from camp.crustytoothpaste.net (unknown [IPv6:2001:470:b978:101:b610:a2f0:36c1:12e3]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by injection.crustytoothpaste.net (Postfix) with ESMTPSA id C6D0760CF2; Thu, 20 Feb 2020 02:24:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crustytoothpaste.net; s=default; t=1582165478; bh=29Py2g5Hh7ZkCVn7lQaxX3CTed5DJDABtVkK4NzfDK0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Reply-To: Subject:Date:To:CC:Resent-Date:Resent-From:Resent-To:Resent-Cc: In-Reply-To:References:Content-Type:Content-Disposition; b=h4YgD2FH6BE72chV1LzjRexkkMLRRxt4E3mSzK7UX7POf1d9rDO15ECfbbWdksXS2 alg6730+k3jc69FhaOZe/tqFTv1j8pbZ3doehPe+Px/c9BTdolTJiTQYKIVvS6NkNw g5gE3qlNlKiM5WHlpmAhFCu4OgrHWRQvwgejGqcOuFCP1xmhHTDK5C4fHbS4HGgbL8 JZg8T9rTU2seRG+lr7YuW/vHF8l8jSeazQYdWXMmzGS21q0vKq8rLPkOU8aZ3uko1r KcqbCggiOcWi/BWzB4tpf1Pww/zfFXVc8vTbi+6DR3AD3SxMG6zT+BwK03G/5d89AZ 10/MovYbGYUfb+040gxUjAkCKMvN4Th+nIf/s9s1JkT+5GiTCor2H11ubq/Il5xrnc ig3Lf9A33HMGrx/yFonfkV5VJcLj3QulZCzJDp0mZ2RcTRjI2ljj2JpbvkfngC9w1Q BpaJxkzOqxQf9LPDRs7PgjTse3gNT9MfiTz3QZhuJooQlaKjBVu From: "brian m. carlson" To: Cc: Jeff King Subject: [PATCH v2 5/5] credential: allow wildcard patterns when matching config Date: Thu, 20 Feb 2020 02:24:13 +0000 Message-Id: <20200220022413.258026-6-sandals@crustytoothpaste.net> X-Mailer: git-send-email 2.25.1.481.gfbce0eb801 In-Reply-To: <20200220022413.258026-1-sandals@crustytoothpaste.net> References: <20200220022413.258026-1-sandals@crustytoothpaste.net> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: brian m. carlson In some cases, a user will want to use a specific credential helper for a wildcard pattern, such as https://*.corp.example.com. We have code that handles this already with the urlmatch code, so let's use that instead of our custom code. Since the urlmatch code is a superset of our current matching in terms of capabilities, there shouldn't be any cases of things that matched previously that don't match now. However, in addition to wildcard matching, we now use partial path matching, which can cause slightly different behavior in the case that a helper applies to the prefix (considering path components) of the remote URL. While different, this is probably the behavior people were wanting anyway. Since we're using the urlmatch code, we need to encode the components we've gotten into a URL to match, so add a function to percent-encode data and format the URL with it. We now also no longer need to the custom code to match URLs, so let's remove it. Additionally, the urlmatch code always looks for the best match, whereas we want all matches for credential helpers to preserve existing behavior. Let's add an optional field, select_fn, that lets us control which items we want (in this case, all of them) and default it to the best-match code that already exists for other users. Signed-off-by: brian m. carlson --- Documentation/gitcredentials.txt | 4 +- credential.c | 66 +++++++++++++++++++++++--------- strbuf.c | 15 ++++++++ strbuf.h | 6 +++ t/t0300-credentials.sh | 20 ++++++++++ urlmatch.c | 4 +- urlmatch.h | 9 +++++ 7 files changed, 103 insertions(+), 21 deletions(-) diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt index 5b9d14fb1f..1814d2d23c 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.txt @@ -131,7 +131,9 @@ context would not match: because the hostnames differ. Nor would it match `foo.example.com`; Git compares hostnames exactly, without considering whether two hosts are part of the same domain. Likewise, a config entry for `http://example.com` would not -match: Git compares the protocols exactly. +match: Git compares the protocols exactly. However, you may use wildcards in +the domain name and other pattern matching techniques as with the `http..*` +options. If the "pattern" URL does include a path component, then this too must match exactly: the context `https://example.com/bar/baz.git` will match a config diff --git a/credential.c b/credential.c index 5701e32792..77dfde44e3 100644 --- a/credential.c +++ b/credential.c @@ -6,6 +6,7 @@ #include "url.h" #include "prompt.h" #include "sigchain.h" +#include "urlmatch.h" void credential_init(struct credential *c) { @@ -40,7 +41,7 @@ static int credential_config_callback(const char *var, const char *value, void *data) { struct credential *c = data; - const char *key, *dot; + const char *key; if (!skip_prefix(var, "credential.", &key)) return 0; @@ -48,23 +49,6 @@ static int credential_config_callback(const char *var, const char *value, if (!value) return config_error_nonbool(var); - dot = strrchr(key, '.'); - if (dot) { - struct credential want = CREDENTIAL_INIT; - char *url = xmemdupz(key, dot - key); - int matched; - - credential_from_url(&want, url); - matched = credential_match(&want, c); - - credential_clear(&want); - free(url); - - if (!matched) - return 0; - key = dot + 1; - } - if (!strcmp(key, "helper")) { if (*value) string_list_append(&c->helpers, value); @@ -89,11 +73,38 @@ static int proto_is_http(const char *s) return !strcmp(s, "https") || !strcmp(s, "http"); } +static void credential_describe(struct credential *c, struct strbuf *out); +static void credential_format(struct credential *c, struct strbuf *out); + +static int select_all(const struct urlmatch_item *a, + const struct urlmatch_item *b) +{ + return 0; +} + static void credential_apply_config(struct credential *c) { + char *normalized_url; + struct urlmatch_config config = { STRING_LIST_INIT_DUP }; + struct strbuf url = STRBUF_INIT; + if (c->configured) return; - git_config(credential_config_callback, c); + + config.section = "credential"; + config.key = NULL; + config.collect_fn = credential_config_callback; + config.cascade_fn = NULL; + config.select_fn = select_all; + config.cb = c; + + credential_format(c, &url); + normalized_url = url_normalize(url.buf, &config.url); + + git_config(urlmatch_config_entry, &config); + free(normalized_url); + strbuf_release(&url); + c->configured = 1; if (!c->use_http_path && proto_is_http(c->protocol)) { @@ -114,6 +125,23 @@ static void credential_describe(struct credential *c, struct strbuf *out) strbuf_addf(out, "/%s", c->path); } +static void credential_format(struct credential *c, struct strbuf *out) +{ + if (!c->protocol) + return; + strbuf_addf(out, "%s://", c->protocol); + if (c->username && *c->username) { + strbuf_add_percentencode(out, c->username); + strbuf_addch(out, '@'); + } + if (c->host) + strbuf_addstr(out, c->host); + if (c->path) { + strbuf_addch(out, '/'); + strbuf_add_percentencode(out, c->path); + } +} + static char *credential_ask_one(const char *what, struct credential *c, int flags) { diff --git a/strbuf.c b/strbuf.c index f19da55b07..bb0065ccaf 100644 --- a/strbuf.c +++ b/strbuf.c @@ -479,6 +479,21 @@ void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src) } } +#define URL_UNSAFE_CHARS " <>\"%{}|\\^`:/?#[]@!$&'()*+,;=" + +void strbuf_add_percentencode(struct strbuf *dst, const char *src) +{ + size_t i, len = strlen(src); + + for (i = 0; i < len; i++) { + unsigned char ch = src[i]; + if (ch <= 0x1F || ch >= 0x7F || strchr(URL_UNSAFE_CHARS, ch)) + strbuf_addf(dst, "%%%02X", (unsigned char)ch); + else + strbuf_addch(dst, ch); + } +} + size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) { size_t res; diff --git a/strbuf.h b/strbuf.h index aae7ac3a82..ce8e49c0b2 100644 --- a/strbuf.h +++ b/strbuf.h @@ -378,6 +378,12 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb, */ void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src); +/** + * Append the contents of a string to a strbuf, percent-encoding any characters + * that are needed to be encoded for a URL. + */ +void strbuf_add_percentencode(struct strbuf *dst, const char *src); + /** * Append the given byte size as a human-readable string (i.e. 12.23 KiB, * 3.50 MiB). diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 8f87599056..39f097ea9e 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -397,6 +397,26 @@ test_expect_success 'http paths can be part of context' ' EOF ' +test_expect_success 'context uses urlmatch' ' + test_config "credential.https://*.org.useHttpPath" true && + check fill "verbatim foo bar" <<-\EOF + protocol=https + host=example.org + path=foo.git + -- + protocol=https + host=example.org + path=foo.git + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.org + verbatim: path=foo.git + EOF +' + test_expect_success 'helpers can abort the process' ' test_must_fail git \ -c credential.helper="!f() { echo quit=1; }; f" \ diff --git a/urlmatch.c b/urlmatch.c index 3e42bd7504..29272a5c4f 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -557,6 +557,8 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb) const char *key, *dot; struct strbuf synthkey = STRBUF_INIT; int retval; + int (*select_fn)(const struct urlmatch_item *a, const struct urlmatch_item *b) = + collect->select_fn ? collect->select_fn : cmp_matches; if (!skip_prefix(var, collect->section, &key) || *(key++) != '.') { if (collect->cascade_fn) @@ -587,7 +589,7 @@ int urlmatch_config_entry(const char *var, const char *value, void *cb) if (!item->util) { item->util = xcalloc(1, sizeof(matched)); } else { - if (cmp_matches(&matched, item->util) < 0) + if (select_fn(&matched, item->util) < 0) /* * Our match is worse than the old one, * we cannot use it. diff --git a/urlmatch.h b/urlmatch.h index eed5f29235..2407520731 100644 --- a/urlmatch.h +++ b/urlmatch.h @@ -50,6 +50,15 @@ struct urlmatch_config { void *cb; int (*collect_fn)(const char *var, const char *value, void *cb); int (*cascade_fn)(const char *var, const char *value, void *cb); + /* + * Compare the two matches, the one just discovered and the existing + * best match and return a negative value if the found item is to be + * rejected or a non-negative value if it is to be accepted. If this + * field is set to NULL, use the default comparison technique, which + * checks to ses if found is better (according to the urlmatch + * specificity rules) than existing. + */ + int (*select_fn)(const struct urlmatch_item *found, const struct urlmatch_item *existing); }; int urlmatch_config_entry(const char *var, const char *value, void *cb);