@@ -35,7 +35,7 @@ static void *xmalloc(size_t size)
3535}
3636
3737static WCHAR * wusername , * password , * protocol , * host , * path , target [1024 ],
38- * password_expiry_utc ;
38+ * password_expiry_utc , * oauth_refresh_token ;
3939
4040static void write_item (const char * what , LPCWSTR wbuf , int wlen )
4141{
@@ -140,6 +140,11 @@ static void get_credential(void)
140140 DWORD num_creds ;
141141 int i ;
142142 CREDENTIAL_ATTRIBUTEW * attr ;
143+ WCHAR * secret ;
144+ WCHAR * line ;
145+ WCHAR * remaining_lines ;
146+ WCHAR * part ;
147+ WCHAR * remaining_parts ;
143148
144149 if (!CredEnumerateW (L"git:*" , 0 , & num_creds , & creds ))
145150 return ;
@@ -149,9 +154,24 @@ static void get_credential(void)
149154 if (match_cred (creds [i ], 0 )) {
150155 write_item ("username" , creds [i ]-> UserName ,
151156 creds [i ]-> UserName ? wcslen (creds [i ]-> UserName ) : 0 );
152- write_item ("password" ,
153- (LPCWSTR )creds [i ]-> CredentialBlob ,
154- creds [i ]-> CredentialBlobSize / sizeof (WCHAR ));
157+ if (creds [i ]-> CredentialBlobSize > 0 ) {
158+ secret = xmalloc (creds [i ]-> CredentialBlobSize );
159+ wcsncpy_s (secret , creds [i ]-> CredentialBlobSize , (LPCWSTR )creds [i ]-> CredentialBlob , creds [i ]-> CredentialBlobSize / sizeof (WCHAR ));
160+ line = wcstok_s (secret , L"\r\n" , & remaining_lines );
161+ write_item ("password" , line , line ? wcslen (line ) : 0 );
162+ while (line != NULL ) {
163+ part = wcstok_s (line , L"=" , & remaining_parts );
164+ if (!wcscmp (part , L"oauth_refresh_token" )) {
165+ write_item ("oauth_refresh_token" , remaining_parts , remaining_parts ? wcslen (remaining_parts ) : 0 );
166+ }
167+ line = wcstok_s (NULL , L"\r\n" , & remaining_lines );
168+ }
169+ free (secret );
170+ } else {
171+ write_item ("password" ,
172+ (LPCWSTR )creds [i ]-> CredentialBlob ,
173+ creds [i ]-> CredentialBlobSize / sizeof (WCHAR ));
174+ }
155175 for (int j = 0 ; j < creds [i ]-> AttributeCount ; j ++ ) {
156176 attr = creds [i ]-> Attributes + j ;
157177 if (!wcscmp (attr -> Keyword , L"git_password_expiry_utc" )) {
@@ -170,16 +190,26 @@ static void store_credential(void)
170190{
171191 CREDENTIALW cred ;
172192 CREDENTIAL_ATTRIBUTEW expiry_attr ;
193+ WCHAR * secret ;
194+ int wlen ;
173195
174196 if (!wusername || !password )
175197 return ;
176198
199+ if (oauth_refresh_token ) {
200+ wlen = _scwprintf (L"%s\r\noauth_refresh_token=%s" , password , oauth_refresh_token );
201+ secret = xmalloc (sizeof (WCHAR ) * wlen );
202+ _snwprintf_s (secret , sizeof (WCHAR ) * wlen , wlen , L"%s\r\noauth_refresh_token=%s" , password , oauth_refresh_token );
203+ } else {
204+ secret = _wcsdup (password );
205+ }
206+
177207 cred .Flags = 0 ;
178208 cred .Type = CRED_TYPE_GENERIC ;
179209 cred .TargetName = target ;
180210 cred .Comment = L"saved by git-credential-wincred" ;
181- cred .CredentialBlobSize = ( wcslen (password ) ) * sizeof (WCHAR );
182- cred .CredentialBlob = (LPVOID )password ;
211+ cred .CredentialBlobSize = wcslen (secret ) * sizeof (WCHAR );
212+ cred .CredentialBlob = (LPVOID )_wcsdup ( secret ) ;
183213 cred .Persist = CRED_PERSIST_LOCAL_MACHINE ;
184214 cred .AttributeCount = 0 ;
185215 cred .Attributes = NULL ;
@@ -194,6 +224,8 @@ static void store_credential(void)
194224 cred .TargetAlias = NULL ;
195225 cred .UserName = wusername ;
196226
227+ free (secret );
228+
197229 if (!CredWriteW (& cred , 0 ))
198230 die ("CredWrite failed" );
199231}
@@ -265,6 +297,8 @@ static void read_credential(void)
265297 password = utf8_to_utf16_dup (v );
266298 else if (!strcmp (buf , "password_expiry_utc" ))
267299 password_expiry_utc = utf8_to_utf16_dup (v );
300+ else if (!strcmp (buf , "oauth_refresh_token" ))
301+ oauth_refresh_token = utf8_to_utf16_dup (v );
268302 /*
269303 * Ignore other lines; we don't know what they mean, but
270304 * this future-proofs us when later versions of git do
0 commit comments