185 lines
5.4 KiB
C++
185 lines
5.4 KiB
C++
#include "keytar.h"
|
|
|
|
// This is needed to make the builds on Ubuntu 14.04 / libsecret v0.16 work.
|
|
// The API we use has already stabilized.
|
|
#define SECRET_API_SUBJECT_TO_CHANGE
|
|
#include <libsecret/secret.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
namespace keytar {
|
|
|
|
namespace {
|
|
|
|
static const SecretSchema schema = {
|
|
"org.freedesktop.Secret.Generic", SECRET_SCHEMA_NONE, {
|
|
{ "service", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
{ "account", SECRET_SCHEMA_ATTRIBUTE_STRING }
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
KEYTAR_OP_RESULT SetPassword(const std::string& service,
|
|
const std::string& account,
|
|
const std::string& password,
|
|
std::string* errStr) {
|
|
GError* error = NULL;
|
|
|
|
secret_password_store_sync(
|
|
&schema, // The schema.
|
|
SECRET_COLLECTION_DEFAULT, // Default collection.
|
|
(service + "/" + account).c_str(), // The label.
|
|
password.c_str(), // The password.
|
|
NULL, // Cancellable. (unneeded)
|
|
&error, // Reference to the error.
|
|
"service", service.c_str(),
|
|
"account", account.c_str(),
|
|
NULL); // End of arguments.
|
|
|
|
if (error != NULL) {
|
|
*errStr = std::string(error->message);
|
|
g_error_free(error);
|
|
return FAIL_ERROR;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
KEYTAR_OP_RESULT GetPassword(const std::string& service,
|
|
const std::string& account,
|
|
std::string* password,
|
|
std::string* errStr) {
|
|
GError* error = NULL;
|
|
|
|
gchar* raw_password = secret_password_lookup_sync(
|
|
&schema, // The schema.
|
|
NULL, // Cancellable. (unneeded)
|
|
&error, // Reference to the error.
|
|
"service", service.c_str(),
|
|
"account", account.c_str(),
|
|
NULL); // End of arguments.
|
|
|
|
if (error != NULL) {
|
|
*errStr = std::string(error->message);
|
|
g_error_free(error);
|
|
return FAIL_ERROR;
|
|
}
|
|
|
|
if (raw_password == NULL)
|
|
return FAIL_NONFATAL;
|
|
|
|
*password = raw_password;
|
|
secret_password_free(raw_password);
|
|
return SUCCESS;
|
|
}
|
|
|
|
KEYTAR_OP_RESULT DeletePassword(const std::string& service,
|
|
const std::string& account,
|
|
std::string* errStr) {
|
|
GError* error = NULL;
|
|
|
|
gboolean result = secret_password_clear_sync(
|
|
&schema, // The schema.
|
|
NULL, // Cancellable. (unneeded)
|
|
&error, // Reference to the error.
|
|
"service", service.c_str(),
|
|
"account", account.c_str(),
|
|
NULL); // End of arguments.
|
|
|
|
if (error != NULL) {
|
|
*errStr = std::string(error->message);
|
|
g_error_free(error);
|
|
return FAIL_ERROR;
|
|
}
|
|
|
|
if (!result)
|
|
return FAIL_NONFATAL;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
KEYTAR_OP_RESULT FindPassword(const std::string& service,
|
|
std::string* password,
|
|
std::string* errStr) {
|
|
GError* error = NULL;
|
|
|
|
gchar* raw_password = secret_password_lookup_sync(
|
|
&schema, // The schema.
|
|
NULL, // Cancellable. (unneeded)
|
|
&error, // Reference to the error.
|
|
"service", service.c_str(),
|
|
NULL); // End of arguments.
|
|
|
|
if (error != NULL) {
|
|
*errStr = std::string(error->message);
|
|
g_error_free(error);
|
|
return FAIL_ERROR;
|
|
}
|
|
|
|
if (raw_password == NULL)
|
|
return FAIL_NONFATAL;
|
|
|
|
*password = raw_password;
|
|
secret_password_free(raw_password);
|
|
return SUCCESS;
|
|
}
|
|
|
|
KEYTAR_OP_RESULT FindCredentials(const std::string& service,
|
|
std::vector<Credentials>* credentials,
|
|
std::string* errStr) {
|
|
GError* error = NULL;
|
|
|
|
GHashTable* attributes = g_hash_table_new(NULL, NULL);
|
|
g_hash_table_replace(attributes,
|
|
(gpointer) "service",
|
|
(gpointer) service.c_str());
|
|
|
|
GList* items = secret_service_search_sync(
|
|
NULL,
|
|
&schema, // The schema.
|
|
attributes,
|
|
static_cast<SecretSearchFlags>(SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK |
|
|
SECRET_SEARCH_LOAD_SECRETS),
|
|
NULL, // Cancellable. (unneeded)
|
|
&error); // Reference to the error.
|
|
|
|
g_hash_table_destroy(attributes);
|
|
|
|
if (error != NULL) {
|
|
*errStr = std::string(error->message);
|
|
g_error_free(error);
|
|
return FAIL_ERROR;
|
|
}
|
|
|
|
GList* current = items;
|
|
for (current = items; current != NULL; current = current->next) {
|
|
SecretItem* item = reinterpret_cast<SecretItem*>(current->data);
|
|
|
|
GHashTable* itemAttrs = secret_item_get_attributes(item);
|
|
char* account = strdup(
|
|
reinterpret_cast<char*>(g_hash_table_lookup(itemAttrs, "account")));
|
|
|
|
SecretValue* secret = secret_item_get_secret(item);
|
|
char* password = strdup(secret_value_get_text(secret));
|
|
|
|
if (account == NULL || password == NULL) {
|
|
if (account)
|
|
free(account);
|
|
|
|
if (password)
|
|
free(password);
|
|
|
|
continue;
|
|
}
|
|
|
|
credentials->push_back(Credentials(account, password));
|
|
free(account);
|
|
free(password);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
} // namespace keytar
|