diff mbox series

[v2] credential/wincred: store password_expiry_utc

Message ID pull.1477.v2.git.git.1680200278780.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series [v2] credential/wincred: store password_expiry_utc | expand

Commit Message

M Hickford March 30, 2023, 6:17 p.m. UTC
From: M Hickford <mirth.hickford@gmail.com>

This attribute is important when storing OAuth credentials which may
expire after as little as one hour. See
https://github.com/git/git/commit/d208bfdfef97a1e8fb746763b5057e0ad91e283b

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
    
    [1] make CC="zig cc -target x86_64-windows-gnu" [2]
    https://github.com/wine-mirror/wine/blob/bf9d15e3b1a29f73fedda0c34547a9b29d5e2789/dlls/advapi32/cred.c#L181-L186

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1477%2Fhickford%2Fwincred-expiry-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1477/hickford/wincred-expiry-v2
Pull-Request: https://github.com/git/git/pull/1477

Range-diff vs v1:

 1:  05340715ef2 ! 1:  51a9039bd15 credential/wincred: store password_expiry_utc
     @@ Metadata
       ## Commit message ##
          credential/wincred: store password_expiry_utc
      
     +    This attribute is important when storing OAuth credentials which may
     +    expire after as little as one hour. See
     +    https://github.com/git/git/commit/d208bfdfef97a1e8fb746763b5057e0ad91e283b
     +
          Signed-off-by: M Hickford <mirth.hickford@gmail.com>
      
       ## contrib/credential/wincred/git-credential-wincred.c ##
     @@ contrib/credential/wincred/git-credential-wincred.c: static void get_credential(
       			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;
      +				}
     -+				attr++;
      +			}
       			break;
       		}


 .../wincred/git-credential-wincred.c          | 25 +++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)


base-commit: 8d90352acc5c855620042fdcc6092f23a276af6d

Comments

Junio C Hamano March 30, 2023, 7:19 p.m. UTC | #1
"M Hickford via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: M Hickford <mirth.hickford@gmail.com>
>
> This attribute is important when storing OAuth credentials which may
> expire after as little as one hour. See
> https://github.com/git/git/commit/d208bfdfef97a1e8fb746763b5057e0ad91e283b

Readers do not have to visit GitHub at all, and proposed log message
shouldn't force them to.  Refer to an existing commit in this
project like so instead:

    ... as one hour.  d208bfdf (credential: new attribute
    password_expiry_utc, 2023-02-18) added support for this
    attribute in general so that individual credential backend like
    wincred can use it.

>     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:

I cannot be one to help testing but ...

> @@ -292,7 +313,7 @@ int main(int argc, char *argv[])
>  	    "usage: git credential-wincred <get|store|erase>\n";
>  
>  	if (!argv[1])
> -		die(usage);
> +		die("%s", usage);

... this is a nice one.  Logically it may belong to a separate
topic, but it is small and obvious enough that it is OK to do as a
"while at it" clean-up.
M Hickford April 3, 2023, 7 a.m. UTC | #2
On Thu, 30 Mar 2023 at 20:20, Junio C Hamano <gitster@pobox.com> wrote:
>
> "M Hickford via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: M Hickford <mirth.hickford@gmail.com>
> >
> > This attribute is important when storing OAuth credentials which may
> > expire after as little as one hour. See
> > https://github.com/git/git/commit/d208bfdfef97a1e8fb746763b5057e0ad91e283b
>
> Readers do not have to visit GitHub at all, and proposed log message
> shouldn't force them to.  Refer to an existing commit in this
> project like so instead:
>
>     ... as one hour.  d208bfdf (credential: new attribute
>     password_expiry_utc, 2023-02-18) added support for this
>     attribute in general so that individual credential backend like
>     wincred can use it.
>

Thanks Junio for the example. I'll update the commit message in patch v3.
diff mbox series

Patch

diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index ead6e267c78..7b4e7fae675 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -91,7 +91,8 @@  static void load_cred_funcs(void)
 		die("failed to load functions");
 }
 
-static WCHAR *wusername, *password, *protocol, *host, *path, target[1024];
+static WCHAR *wusername, *password, *protocol, *host, *path, target[1024],
+	*password_expiry_utc;
 
 static void write_item(const char *what, LPCWSTR wbuf, int wlen)
 {
@@ -183,6 +184,7 @@  static void get_credential(void)
 	CREDENTIALW **creds;
 	DWORD num_creds;
 	int i;
+	CREDENTIAL_ATTRIBUTEW *attr;
 
 	if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
 		return;
@@ -195,6 +197,14 @@  static void get_credential(void)
 			write_item("password",
 				(LPCWSTR)creds[i]->CredentialBlob,
 				creds[i]->CredentialBlobSize / sizeof(WCHAR));
+			for (int j = 0; j < creds[i]->AttributeCount; j++) {
+				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;
+				}
+			}
 			break;
 		}
 
@@ -204,6 +214,7 @@  static void get_credential(void)
 static void store_credential(void)
 {
 	CREDENTIALW cred;
+	CREDENTIAL_ATTRIBUTEW expiry_attr;
 
 	if (!wusername || !password)
 		return;
@@ -217,6 +228,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 +297,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 +313,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);