1
0
mirror of https://github.com/docker/docker-credential-helpers.git synced 2026-06-13 16:01:28 +05:30
Files
docker-credential-helpers/secretservice/secretservice.c
T
Moritz "WanzenBug" Wanzenböck 28e893e56d secretservice: fix null derefence on locked collections
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>
2025-02-19 15:56:07 +01:00

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]);
}
}