35
}
36
37
static WCHAR *wusername, *password, *protocol, *host, *path, target[1024],
38
- *password_expiry_utc;
38
+ *password_expiry_utc, *oauth_refresh_token;
39
40
static void write_item(const char *what, LPCWSTR wbuf, int wlen)
41
{
128
DWORD num_creds;
129
int i;
130
CREDENTIAL_ATTRIBUTEW *attr;
131
+ WCHAR *secret;
132
+ WCHAR *line;
133
+ WCHAR *remaining_lines;
134
+ WCHAR *part;
135
+ WCHAR *remaining_parts;
136
137
if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
138
return;
142
if (match_cred(creds[i])) {
143
write_item("username", creds[i]->UserName,
144
creds[i]->UserName ? wcslen(creds[i]->UserName) : 0);
140
- write_item("password",
141
- (LPCWSTR)creds[i]->CredentialBlob,
142
- creds[i]->CredentialBlobSize / sizeof(WCHAR));
145
+ if (creds[i]->CredentialBlobSize > 0) {
146
+ secret = xmalloc(creds[i]->CredentialBlobSize);
147
+ wcsncpy_s(secret, creds[i]->CredentialBlobSize, (LPCWSTR)creds[i]->CredentialBlob, creds[i]->CredentialBlobSize / sizeof(WCHAR));
148
+ line = wcstok_s(secret, L"\r\n", &remaining_lines);
149
+ write_item("password", line, line ? wcslen(line) : 0);
150
+ while(line != NULL) {
151
+ part = wcstok_s(line, L"=", &remaining_parts);
152
+ if (!wcscmp(part, L"oauth_refresh_token")) {
153
+ write_item("oauth_refresh_token", remaining_parts, remaining_parts ? wcslen(remaining_parts) : 0);
154
+ }
155
+ line = wcstok_s(NULL, L"\r\n", &remaining_lines);
156
+ }
157
+ free(secret);
158
+ } else {
159
+ write_item("password",
160
+ (LPCWSTR)creds[i]->CredentialBlob,
161
+ creds[i]->CredentialBlobSize / sizeof(WCHAR));
162
+ }
163
for (int j = 0; j < creds[i]->AttributeCount; j++) {
164
attr = creds[i]->Attributes + j;
165
if (!wcscmp(attr->Keyword, L"git_password_expiry_utc")) {
178
{
179
CREDENTIALW cred;
180
CREDENTIAL_ATTRIBUTEW expiry_attr;
181
+ WCHAR *secret;
182
+ int wlen;
183
184
if (!wusername || !password)
185
return;
186
187
+ if (oauth_refresh_token) {
188
+ wlen = _scwprintf(L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
189
+ secret = xmalloc(sizeof(WCHAR) * wlen);
190
+ _snwprintf_s(secret, sizeof(WCHAR) * wlen, wlen, L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
191
+ } else {
192
+ secret = _wcsdup(password);
193
+ }
194
+
195
cred.Flags = 0;
196
cred.Type = CRED_TYPE_GENERIC;
197
cred.TargetName = target;
198
cred.Comment = L"saved by git-credential-wincred";
169
- cred.CredentialBlobSize = (wcslen(password)) * sizeof(WCHAR);
170
- cred.CredentialBlob = (LPVOID)password;
199
+ cred.CredentialBlobSize = wcslen(secret) * sizeof(WCHAR);
200
+ cred.CredentialBlob = (LPVOID)_wcsdup(secret);
201
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
202
cred.AttributeCount = 0;
203
cred.Attributes = NULL;
212
cred.TargetAlias = NULL;
213
cred.UserName = wusername;
214
215
+ free(secret);
216
+
217
if (!CredWriteW(&cred, 0))
218
die("CredWrite failed");
219
}
285
password = utf8_to_utf16_dup(v);
286
else if (!strcmp(buf, "password_expiry_utc"))
287
password_expiry_utc = utf8_to_utf16_dup(v);
288
+ else if (!strcmp(buf, "oauth_refresh_token"))
289
+ oauth_refresh_token = utf8_to_utf16_dup(v);
290
/*
291
* Ignore other lines; we don't know what they mean, but
292
* this future-proofs us when later versions of git do