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
>
next prev parent 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).