Re: [PATCH] credential/wincred: store password_expiry_utc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi M,

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

> From: M Hickford <mirth.hickford@xxxxxxxxx>
>
> Signed-off-by: M Hickford <mirth.hickford@xxxxxxxxx>
> ---
>     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
>




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux