git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: M Hickford via GitGitGadget <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org, "Johannes Sixt [ ]" <j6t@kdbg.org>,
	"Harshil Jani [ ]" <harshiljani2002@gmail.com>,
	"Jakub Bereżański" <kuba@berezanscy.pl>,
	"Karsten Blees" <blees@dcon.de>,
	"Erik Faye-Lund" <kusmabite@gmail.com>,
	"Javier Roucher Iglesias"
	<Javier.Roucher-Iglesias@ensimag.imag.fr>,
	"M Hickford" <mirth.hickford@gmail.com>,
	"M Hickford" <mirth.hickford@gmail.com>
Subject: Re: [PATCH] credential/wincred: store password_expiry_utc
Date: Tue, 28 Mar 2023 14:14:18 +0200 (CEST)	[thread overview]
Message-ID: <35e1ebe6-e15b-1712-f030-70ab708740db@gmx.de> (raw)
In-Reply-To: <pull.1477.git.git.1679729956620.gitgitgadget@gmail.com>

Hi M,

On Sat, 25 Mar 2023, M Hickford via GitGitGadget wrote:

> From: M Hickford <mirth.hickford@gmail.com>
>
> Signed-off-by: M Hickford <mirth.hickford@gmail.com>
> ---
>     credential/wincred: store password_expiry_utc
>
>     Help wanted from a Windows user to test. I tried testing on Linux with
>     Wine after cross-compiling [1] but Wine has incomplete support for
>     wincred.h [2]. To test:
>
>     cd contrib/credential/wincred/
>     make
>     echo host=example.com\nprotocol=https\nusername=tim\npassword=xyzzy\npassword_expiry_utc=2000 | ./git-credential-wincred.exe store
>     echo host=example.com\nprotocol=https | ./git-credential-wincred.exe get
>
>
>     Output of second command should include line password_expiry_utc=2000

Sadly, no, it's empty:

	$ cd contrib/credential/wincred/
	$ make
	cc     git-credential-wincred.c   -o git-credential-wincred.exe
	$ echo host=example.com\nprotocol=https\nusername=tim\npassword=xyzzy\npassword_expiry_utc=2000 | ./git-credential-wincred.exe store
	$ echo host=example.com\nprotocol=https | ./git-credential-wincred.exe get

The reason is that `echo` does not interpret the escaped `n`, it does not
even get the backslash because Bash eats it first.

But even with `printf` it does not work:

	$ printf 'host=example.com\nprotocol=https\nusername=tim\npassword=xyzzy\npassword_expiry_utc=2000\n' | ./git-credential-wincred.exe store
	$ printf 'host=example.com\nprotocol=https\n' | ./git-credential-wincred.exe get                                        username=tim
	password=xyzzy

And the reason is...

> @@ -195,6 +197,15 @@ static void get_credential(void)
>  			write_item("password",
>  				(LPCWSTR)creds[i]->CredentialBlob,
>  				creds[i]->CredentialBlobSize / sizeof(WCHAR));
> +			attr = creds[i]->Attributes;
> +			for (int j = 0; j < creds[i]->AttributeCount; j++) {
> +				if (wcscmp(attr->Keyword, L"git_password_expiry_utc")) {

				  ^^^^^^

... here. Note how the return value of `wcscmp()` needs to be non-zero to
enter the conditional block? But `wcscmp()` returns 0 if there are no
differences between the two provided strings.

That's not the only bug, though. While the loop iterates over all of the
attributes, the `attr` variable is unchanged, and always points to the
first attribute. You have to access it as `creds[i]->Attributes[j]`,
though, see e.g.
https://github.com/sandboxie-plus/Sandboxie/blob/f2a357f9222b81e7bdc994e5d9824790a1b5d826/Sandboxie/core/dll/cred.c#L324

So with this patch on top of your patch, it works for me:

-- snip --
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index 9be892610d0..1aa840e31a0 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -197,9 +197,9 @@ static void get_credential(void)
 			write_item("password",
 				(LPCWSTR)creds[i]->CredentialBlob,
 				creds[i]->CredentialBlobSize / sizeof(WCHAR));
-			attr = creds[i]->Attributes;
 			for (int j = 0; j < creds[i]->AttributeCount; j++) {
-				if (wcscmp(attr->Keyword, L"git_password_expiry_utc")) {
+				attr = creds[i]->Attributes + j;
+				if (!wcscmp(attr->Keyword, L"git_password_expiry_utc")) {
 					write_item("password_expiry_utc", (LPCWSTR)attr->Value,
 					attr->ValueSize / sizeof(WCHAR));
 					break;
-- snap --

But I have to wonder: why even bother with `git-wincred`? This credential
helper is so ridiculously limited in its capabilities, it does not even
support any host that is remotely close to safe (no 2FA, no OAuth, just
passwords). So I would be just as happy if I weren't asked to spend my
time to review changes to a credential helper I'd much rather see retired
than actively worked on.

Ciao,
Johannes

> +					write_item("password_expiry_utc", (LPCWSTR)attr->Value,
> +					attr->ValueSize / sizeof(WCHAR));
> +					break;
> +				}
> +				attr++;
> +			}
>  			break;
>  		}
>
> @@ -204,6 +215,7 @@ static void get_credential(void)
>  static void store_credential(void)
>  {
>  	CREDENTIALW cred;
> +	CREDENTIAL_ATTRIBUTEW expiry_attr;
>
>  	if (!wusername || !password)
>  		return;
> @@ -217,6 +229,14 @@ static void store_credential(void)
>  	cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
>  	cred.AttributeCount = 0;
>  	cred.Attributes = NULL;
> +	if (password_expiry_utc != NULL) {
> +		expiry_attr.Keyword = L"git_password_expiry_utc";
> +		expiry_attr.Value = (LPVOID)password_expiry_utc;
> +		expiry_attr.ValueSize = (wcslen(password_expiry_utc)) * sizeof(WCHAR);
> +		expiry_attr.Flags = 0;
> +		cred.Attributes = &expiry_attr;
> +		cred.AttributeCount = 1;
> +	}
>  	cred.TargetAlias = NULL;
>  	cred.UserName = wusername;
>
> @@ -278,6 +298,8 @@ static void read_credential(void)
>  			wusername = utf8_to_utf16_dup(v);
>  		} else if (!strcmp(buf, "password"))
>  			password = utf8_to_utf16_dup(v);
> +		else if (!strcmp(buf, "password_expiry_utc"))
> +			password_expiry_utc = utf8_to_utf16_dup(v);
>  		/*
>  		 * Ignore other lines; we don't know what they mean, but
>  		 * this future-proofs us when later versions of git do
> @@ -292,7 +314,7 @@ int main(int argc, char *argv[])
>  	    "usage: git credential-wincred <get|store|erase>\n";
>
>  	if (!argv[1])
> -		die(usage);
> +		die("%s", usage);
>
>  	/* git use binary pipes to avoid CRLF-issues */
>  	_setmode(_fileno(stdin), _O_BINARY);
>
> base-commit: 27d43aaaf50ef0ae014b88bba294f93658016a2e
> --
> gitgitgadget
>

  reply	other threads:[~2023-03-28 12:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-25  7:39 [PATCH] credential/wincred: store password_expiry_utc M Hickford via GitGitGadget
2023-03-28 12:14 ` Johannes Schindelin [this message]
2023-03-30  5:50   ` M Hickford
2023-05-01 22:25     ` Junio C Hamano
2023-05-02  9:38       ` M Hickford
2023-05-02 17:43       ` Johannes Sixt
2023-05-02 18:16         ` Felipe Contreras
2023-03-30 18:17 ` [PATCH v2] " M Hickford via GitGitGadget
2023-03-30 19:19   ` Junio C Hamano
2023-04-03  7:00     ` M Hickford
2023-04-03  7:47   ` [PATCH v3] " M Hickford via GitGitGadget

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=35e1ebe6-e15b-1712-f030-70ab708740db@gmx.de \
    --to=johannes.schindelin@gmx.de \
    --cc=Javier.Roucher-Iglesias@ensimag.imag.fr \
    --cc=blees@dcon.de \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=harshiljani2002@gmail.com \
    --cc=j6t@kdbg.org \
    --cc=kuba@berezanscy.pl \
    --cc=kusmabite@gmail.com \
    --cc=mirth.hickford@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).