summaryrefslogtreecommitdiff
path: root/vendor/github.com/docker/docker-credential-helpers/secretservice
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/docker/docker-credential-helpers/secretservice')
-rw-r--r--vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.c162
-rw-r--r--vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.go118
-rw-r--r--vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.h13
3 files changed, 293 insertions, 0 deletions
diff --git a/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.c b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.c
new file mode 100644
index 000000000..35dea92da
--- /dev/null
+++ b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.c
@@ -0,0 +1,162 @@
+#include <string.h>
+#include <stdlib.h>
+#include "secretservice_linux.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) {
+ GError *err = NULL;
+
+ secret_password_store_sync (DOCKER_SCHEMA, SECRET_COLLECTION_DEFAULT,
+ server, 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 (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]);
+ }
+ free(*data);
+}
diff --git a/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.go b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.go
new file mode 100644
index 000000000..95a1310b6
--- /dev/null
+++ b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.go
@@ -0,0 +1,118 @@
+package secretservice
+
+/*
+#cgo pkg-config: libsecret-1
+
+#include "secretservice_linux.h"
+#include <stdlib.h>
+*/
+import "C"
+import (
+ "errors"
+ "unsafe"
+
+ "github.com/docker/docker-credential-helpers/credentials"
+)
+
+// Secretservice handles secrets using Linux secret-service as a store.
+type Secretservice struct{}
+
+// Add adds new credentials to the keychain.
+func (h Secretservice) Add(creds *credentials.Credentials) error {
+ if creds == nil {
+ return errors.New("missing credentials")
+ }
+ credsLabel := C.CString(credentials.CredsLabel)
+ defer C.free(unsafe.Pointer(credsLabel))
+ server := C.CString(creds.ServerURL)
+ defer C.free(unsafe.Pointer(server))
+ username := C.CString(creds.Username)
+ defer C.free(unsafe.Pointer(username))
+ secret := C.CString(creds.Secret)
+ defer C.free(unsafe.Pointer(secret))
+
+ if err := C.add(credsLabel, server, username, secret); err != nil {
+ defer C.g_error_free(err)
+ errMsg := (*C.char)(unsafe.Pointer(err.message))
+ return errors.New(C.GoString(errMsg))
+ }
+ return nil
+}
+
+// Delete removes credentials from the store.
+func (h Secretservice) Delete(serverURL string) error {
+ if serverURL == "" {
+ return errors.New("missing server url")
+ }
+ server := C.CString(serverURL)
+ defer C.free(unsafe.Pointer(server))
+
+ if err := C.delete(server); err != nil {
+ defer C.g_error_free(err)
+ errMsg := (*C.char)(unsafe.Pointer(err.message))
+ return errors.New(C.GoString(errMsg))
+ }
+ return nil
+}
+
+// Get returns the username and secret to use for a given registry server URL.
+func (h Secretservice) Get(serverURL string) (string, string, error) {
+ if serverURL == "" {
+ return "", "", errors.New("missing server url")
+ }
+ var username *C.char
+ defer C.free(unsafe.Pointer(username))
+ var secret *C.char
+ defer C.free(unsafe.Pointer(secret))
+ server := C.CString(serverURL)
+ defer C.free(unsafe.Pointer(server))
+
+ err := C.get(server, &username, &secret)
+ if err != nil {
+ defer C.g_error_free(err)
+ errMsg := (*C.char)(unsafe.Pointer(err.message))
+ return "", "", errors.New(C.GoString(errMsg))
+ }
+ user := C.GoString(username)
+ pass := C.GoString(secret)
+ if pass == "" {
+ return "", "", credentials.NewErrCredentialsNotFound()
+ }
+ return user, pass, nil
+}
+
+// List returns the stored URLs and corresponding usernames for a given credentials label
+func (h Secretservice) List() (map[string]string, error) {
+ credsLabelC := C.CString(credentials.CredsLabel)
+ defer C.free(unsafe.Pointer(credsLabelC))
+
+ var pathsC **C.char
+ defer C.free(unsafe.Pointer(pathsC))
+ var acctsC **C.char
+ defer C.free(unsafe.Pointer(acctsC))
+ var listLenC C.uint
+ err := C.list(credsLabelC, &pathsC, &acctsC, &listLenC)
+ if err != nil {
+ defer C.free(unsafe.Pointer(err))
+ return nil, errors.New("Error from list function in secretservice_linux.c likely due to error in secretservice library")
+ }
+ defer C.freeListData(&pathsC, listLenC)
+ defer C.freeListData(&acctsC, listLenC)
+
+ resp := make(map[string]string)
+
+ listLen := int(listLenC)
+ if listLen == 0 {
+ return resp, nil
+ }
+ // The maximum capacity of the following two slices is limited to (2^29)-1 to remain compatible
+ // with 32-bit platforms. The size of a `*C.char` (a pointer) is 4 Byte on a 32-bit system
+ // and (2^29)*4 == math.MaxInt32 + 1. -- See issue golang/go#13656
+ pathTmp := (*[(1 << 29) - 1]*C.char)(unsafe.Pointer(pathsC))[:listLen:listLen]
+ acctTmp := (*[(1 << 29) - 1]*C.char)(unsafe.Pointer(acctsC))[:listLen:listLen]
+ for i := 0; i < listLen; i++ {
+ resp[C.GoString(pathTmp[i])] = C.GoString(acctTmp[i])
+ }
+
+ return resp, nil
+}
diff --git a/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.h b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.h
new file mode 100644
index 000000000..a28179db3
--- /dev/null
+++ b/vendor/github.com/docker/docker-credential-helpers/secretservice/secretservice_linux.h
@@ -0,0 +1,13 @@
+#define SECRET_WITH_UNSTABLE 1
+#define SECRET_API_SUBJECT_TO_CHANGE 1
+#include <libsecret/secret.h>
+
+const SecretSchema *docker_get_schema(void) G_GNUC_CONST;
+
+#define DOCKER_SCHEMA docker_get_schema()
+
+GError *add(char *label, char *server, char *username, char *secret);
+GError *delete(char *server);
+GError *get(char *server, char **username, char **secret);
+GError *list(char *label, char *** paths, char *** accts, unsigned int *list_l);
+void freeListData(char *** data, unsigned int length);