mirror of
https://github.com/docker/docker-credential-helpers.git
synced 2026-06-13 16:01:28 +05:30
28e893e56d
secret_item_get_secret() may return null if an item is locked or not loaded. While we set SECRET_SEARCH_LOAD_SECRETS and SECRET_SEARCH_UNLOCK, there may still be locked items, for example the user may refuse the unlock request. So we still need to check if the secret data is NULL before we can try to reference it. Signed-off-by: Moritz "WanzenBug" Wanzenböck <moritz@wanzenbug.xyz>
165 lines
4.7 KiB
C
165 lines
4.7 KiB
C
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "secretservice.h"
|
|
|
|
const SecretSchema *docker_get_schema(void)
|
|
{
|
|
static const SecretSchema docker_schema = {
|
|
"io.docker.Credentials", SECRET_SCHEMA_NONE,
|
|
{
|
|
{ "label", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
{ "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
{ "username", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
{ "docker_cli", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
{ "NULL", 0 },
|
|
}
|
|
};
|
|
return &docker_schema;
|
|
}
|
|
|
|
GError *add(char *label, char *server, char *username, char *secret, char *displaylabel) {
|
|
GError *err = NULL;
|
|
|
|
secret_password_store_sync (DOCKER_SCHEMA, SECRET_COLLECTION_DEFAULT,
|
|
displaylabel, secret, NULL, &err,
|
|
"label", label,
|
|
"server", server,
|
|
"username", username,
|
|
"docker_cli", "1",
|
|
NULL);
|
|
return err;
|
|
}
|
|
|
|
GError *delete(char *server) {
|
|
GError *err = NULL;
|
|
|
|
secret_password_clear_sync(DOCKER_SCHEMA, NULL, &err,
|
|
"server", server,
|
|
"docker_cli", "1",
|
|
NULL);
|
|
if (err != NULL)
|
|
return err;
|
|
return NULL;
|
|
}
|
|
|
|
char *get_attribute(const char *attribute, SecretItem *item) {
|
|
GHashTable *attributes;
|
|
GHashTableIter iter;
|
|
gchar *value, *key;
|
|
|
|
attributes = secret_item_get_attributes(item);
|
|
g_hash_table_iter_init(&iter, attributes);
|
|
while (g_hash_table_iter_next(&iter, (void **)&key, (void **)&value)) {
|
|
if (strncmp(key, attribute, strlen(key)) == 0)
|
|
return (char *)value;
|
|
}
|
|
g_hash_table_unref(attributes);
|
|
return NULL;
|
|
}
|
|
|
|
GError *get(char *server, char **username, char **secret) {
|
|
GError *err = NULL;
|
|
GHashTable *attributes;
|
|
SecretService *service;
|
|
GList *items, *l;
|
|
SecretSearchFlags flags = SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK;
|
|
SecretValue *secretValue;
|
|
gsize length;
|
|
gchar *value;
|
|
|
|
attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
|
g_hash_table_insert(attributes, g_strdup("server"), g_strdup(server));
|
|
g_hash_table_insert(attributes, g_strdup("docker_cli"), g_strdup("1"));
|
|
|
|
service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &err);
|
|
if (err == NULL) {
|
|
items = secret_service_search_sync(service, DOCKER_SCHEMA, attributes, flags, NULL, &err);
|
|
if (err == NULL) {
|
|
for (l = items; l != NULL; l = g_list_next(l)) {
|
|
value = secret_item_get_schema_name(l->data);
|
|
if (strncmp(value, "io.docker.Credentials", strlen(value)) != 0) {
|
|
g_free(value);
|
|
continue;
|
|
}
|
|
g_free(value);
|
|
secretValue = secret_item_get_secret(l->data);
|
|
if (secretValue == NULL) {
|
|
continue;
|
|
}
|
|
if (secret != NULL) {
|
|
*secret = strdup(secret_value_get(secretValue, &length));
|
|
secret_value_unref(secretValue);
|
|
}
|
|
*username = get_attribute("username", l->data);
|
|
}
|
|
g_list_free_full(items, g_object_unref);
|
|
}
|
|
g_object_unref(service);
|
|
}
|
|
g_hash_table_unref(attributes);
|
|
if (err != NULL) {
|
|
return err;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
GError *list(char *ref_label, char *** paths, char *** accts, unsigned int *list_l) {
|
|
GList *items;
|
|
GError *err = NULL;
|
|
SecretService *service;
|
|
SecretSearchFlags flags = SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK;
|
|
GHashTable *attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
|
|
|
// List credentials with the right label only
|
|
g_hash_table_insert(attributes, g_strdup("label"), g_strdup(ref_label));
|
|
|
|
service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &err);
|
|
if (err != NULL) {
|
|
return err;
|
|
}
|
|
|
|
items = secret_service_search_sync(service, NULL, attributes, flags, NULL, &err);
|
|
int numKeys = g_list_length(items);
|
|
if (err != NULL) {
|
|
return err;
|
|
}
|
|
|
|
char **tmp_paths = (char **) calloc(1,(int)sizeof(char *)*numKeys);
|
|
char **tmp_accts = (char **) calloc(1,(int)sizeof(char *)*numKeys);
|
|
|
|
// items now contains our keys from the gnome keyring
|
|
// we will now put it in our two lists to return it to go
|
|
GList *current;
|
|
int listNumber = 0;
|
|
for(current = items; current!=NULL; current = current->next) {
|
|
char *pathTmp = secret_item_get_label(current->data);
|
|
// you cannot have a key without a label in the gnome keyring
|
|
char *acctTmp = get_attribute("username",current->data);
|
|
if (acctTmp==NULL) {
|
|
acctTmp = "account not defined";
|
|
}
|
|
|
|
tmp_paths[listNumber] = (char *) calloc(1, sizeof(char)*(strlen(pathTmp)+1));
|
|
tmp_accts[listNumber] = (char *) calloc(1, sizeof(char)*(strlen(acctTmp)+1));
|
|
|
|
memcpy(tmp_paths[listNumber], pathTmp, sizeof(char)*(strlen(pathTmp)+1));
|
|
memcpy(tmp_accts[listNumber], acctTmp, sizeof(char)*(strlen(acctTmp)+1));
|
|
|
|
listNumber = listNumber + 1;
|
|
}
|
|
|
|
*paths = (char **) realloc(tmp_paths, (int)sizeof(char *)*listNumber);
|
|
*accts = (char **) realloc(tmp_accts, (int)sizeof(char *)*listNumber);
|
|
|
|
*list_l = listNumber;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void freeListData(char *** data, unsigned int length) {
|
|
int i;
|
|
for(i=0; i<length; i++) {
|
|
free((*data)[i]);
|
|
}
|
|
}
|