39
char *path;
40
char *username;
41
char *password;
42
+ char *password_expiry_utc;
43
+ char *oauth_refresh_token;
44
};
45
46
#define CREDENTIAL_INIT { 0 }
56
57
/* ----------------- Secret Service functions ----------------- */
58
59
+static const SecretSchema schema = {
60
+ "org.git.Password",
61
+ /* Ignore schema name during search for backwards compatibility */
62
+ SECRET_SCHEMA_DONT_MATCH_NAME,
63
+ {
64
+ /*
65
+ * libsecret assumes attribute values are non-confidential and
66
+ * unchanging, so we can't include oauth_refresh_token or
67
+ * password_expiry_utc.
68
+ */
69
+ { "user", SECRET_SCHEMA_ATTRIBUTE_STRING },
70
+ { "object", SECRET_SCHEMA_ATTRIBUTE_STRING },
71
+ { "protocol", SECRET_SCHEMA_ATTRIBUTE_STRING },
72
+ { "port", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
73
+ { "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
74
+ { NULL, 0 },
75
+ }
76
+};
77
+
78
static char *make_label(struct credential *c)
79
{
80
if (c->port)
122
123
attributes = make_attr_list(c);
124
items = secret_service_search_sync(service,
104
- SECRET_SCHEMA_COMPAT_NETWORK,
125
+ &schema,
126
attributes,
127
SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_UNLOCK,
128
NULL,
138
SecretItem *item;
139
SecretValue *secret;
140
const char *s;
141
+ gchar **parts;
142
143
item = items->data;
144
secret = secret_item_get_secret(item);
152
153
s = secret_value_get_text(secret);
154
if (s) {
133
- g_free(c->password);
134
- c->password = g_strdup(s);
155
+ /*
156
+ * Passwords and other attributes encoded in following format:
157
+ * hunter2
158
+ * password_expiry_utc=1684189401
159
+ * oauth_refresh_token=xyzzy
160
+ */
161
+ parts = g_strsplit(s, "\n", 0);
162
+ if (g_strv_length(parts) >= 1) {
163
+ g_free(c->password);
164
+ c->password = g_strdup(parts[0]);
165
+ }
166
+ for (int i = 1; i < g_strv_length(parts); i++) {
167
+ if (g_str_has_prefix(parts[i], "password_expiry_utc=")) {
168
+ g_free(c->password_expiry_utc);
169
+ c->password_expiry_utc = g_strdup(&parts[i][20]);
170
+ } else if (g_str_has_prefix(parts[i], "oauth_refresh_token=")) {
171
+ g_free(c->oauth_refresh_token);
172
+ c->oauth_refresh_token = g_strdup(&parts[i][20]);
173
+ }
174
+ }
175
+ g_strfreev(parts);
176
}
177
178
g_hash_table_unref(attributes);
189
char *label = NULL;
190
GHashTable *attributes = NULL;
191
GError *error = NULL;
192
+ GString *secret = NULL;
193
194
/*
195
* Sanity check that what we are storing is actually sensible.
204
205
label = make_label(c);
206
attributes = make_attr_list(c);
165
- secret_password_storev_sync(SECRET_SCHEMA_COMPAT_NETWORK,
207
+ secret = g_string_new(c->password);
208
+ if (c->password_expiry_utc) {
209
+ g_string_append_printf(secret, "\npassword_expiry_utc=%s",
210
+ c->password_expiry_utc);
211
+ }
212
+ if (c->oauth_refresh_token) {
213
+ g_string_append_printf(secret, "\noauth_refresh_token=%s",
214
+ c->oauth_refresh_token);
215
+ }
216
+ secret_password_storev_sync(&schema,
217
attributes,
218
NULL,
219
label,
169
- c->password,
220
+ secret->str,
221
NULL,
222
&error);
223
+ g_string_free(secret, TRUE);
224
g_free(label);
225
g_hash_table_unref(attributes);
226
250
return EXIT_FAILURE;
251
252
attributes = make_attr_list(c);
201
- secret_password_clearv_sync(SECRET_SCHEMA_COMPAT_NETWORK,
253
+ secret_password_clearv_sync(&schema,
254
attributes,
255
NULL,
256
&error);
290
g_free(c->path);
291
g_free(c->username);
292
g_free(c->password);
293
+ g_free(c->password_expiry_utc);
294
+ g_free(c->oauth_refresh_token);
295
296
credential_init(c);
297
}
338
} else if (!strcmp(key, "username")) {
339
g_free(c->username);
340
c->username = g_strdup(value);
341
+ } else if (!strcmp(key, "password_expiry_utc")) {
342
+ g_free(c->password_expiry_utc);
343
+ c->password_expiry_utc = g_strdup(value);
344
} else if (!strcmp(key, "password")) {
345
g_free(c->password);
346
c->password = g_strdup(value);
347
while (*value)
348
*value++ = '\0';
349
+ } else if (!strcmp(key, "oauth_refresh_token")) {
350
+ g_free(c->oauth_refresh_token);
351
+ c->oauth_refresh_token = g_strdup(value);
352
+ while (*value)
353
+ *value++ = '\0';
354
}
355
/*
356
* Ignore other lines; we don't know what they mean, but
376
/* only write username/password, if set */
377
credential_write_item(stdout, "username", c->username);
378
credential_write_item(stdout, "password", c->password);
379
+ credential_write_item(stdout, "password_expiry_utc",
380
+ c->password_expiry_utc);
381
+ credential_write_item(stdout, "oauth_refresh_token",
382
+ c->oauth_refresh_token);
383
}
384
385
static void usage(const char *name)