@@ -35,7 +35,7 @@ static void *xmalloc(size_t size)
35
35
}
36
36
37
37
static WCHAR * wusername , * password , * protocol , * host , * path , target [1024 ],
38
- * password_expiry_utc ;
38
+ * password_expiry_utc , * oauth_refresh_token ;
39
39
40
40
static void write_item (const char * what , LPCWSTR wbuf , int wlen )
41
41
{
@@ -140,6 +140,11 @@ static void get_credential(void)
140
140
DWORD num_creds ;
141
141
int i ;
142
142
CREDENTIAL_ATTRIBUTEW * attr ;
143
+ WCHAR * secret ;
144
+ WCHAR * line ;
145
+ WCHAR * remaining_lines ;
146
+ WCHAR * part ;
147
+ WCHAR * remaining_parts ;
143
148
144
149
if (!CredEnumerateW (L"git:*" , 0 , & num_creds , & creds ))
145
150
return ;
@@ -149,9 +154,24 @@ static void get_credential(void)
149
154
if (match_cred (creds [i ], 0 )) {
150
155
write_item ("username" , creds [i ]-> UserName ,
151
156
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
+ }
155
175
for (int j = 0 ; j < creds [i ]-> AttributeCount ; j ++ ) {
156
176
attr = creds [i ]-> Attributes + j ;
157
177
if (!wcscmp (attr -> Keyword , L"git_password_expiry_utc" )) {
@@ -170,16 +190,26 @@ static void store_credential(void)
170
190
{
171
191
CREDENTIALW cred ;
172
192
CREDENTIAL_ATTRIBUTEW expiry_attr ;
193
+ WCHAR * secret ;
194
+ int wlen ;
173
195
174
196
if (!wusername || !password )
175
197
return ;
176
198
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
+
177
207
cred .Flags = 0 ;
178
208
cred .Type = CRED_TYPE_GENERIC ;
179
209
cred .TargetName = target ;
180
210
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 ) ;
183
213
cred .Persist = CRED_PERSIST_LOCAL_MACHINE ;
184
214
cred .AttributeCount = 0 ;
185
215
cred .Attributes = NULL ;
@@ -194,6 +224,8 @@ static void store_credential(void)
194
224
cred .TargetAlias = NULL ;
195
225
cred .UserName = wusername ;
196
226
227
+ free (secret );
228
+
197
229
if (!CredWriteW (& cred , 0 ))
198
230
die ("CredWrite failed" );
199
231
}
@@ -265,6 +297,8 @@ static void read_credential(void)
265
297
password = utf8_to_utf16_dup (v );
266
298
else if (!strcmp (buf , "password_expiry_utc" ))
267
299
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 );
268
302
/*
269
303
* Ignore other lines; we don't know what they mean, but
270
304
* this future-proofs us when later versions of git do
0 commit comments