Skip to content

Commit

Permalink
(WIP) SystemCredentials API (#1)
Browse files Browse the repository at this point in the history
* Keyring - Start SystemCredentials API

* Keyring - Implement SystemCredentials for Windows

* Keyring - dbus --> libsecret

* Keyring - Implement SystemCredentials for Linux

* Update systemcredentials.cpp

* Update systemcredentials.cpp

* Update systemcredentials.cpp
  • Loading branch information
nlogozzo authored Dec 1, 2023
1 parent a8f057b commit 0da55c8
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 6 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_library (${PROJECT_NAME} SHARED
src/helpers/webhelpers.cpp
src/keyring/credential.cpp
src/keyring/passwordgenerator.cpp
src/keyring/systemcredentials.cpp
src/update/updater.cpp
src/appinfo.cpp
src/aura.cpp
Expand All @@ -48,8 +49,8 @@ target_link_libraries(${PROJECT_NAME} PUBLIC sqlcipher::sqlcipher)
find_package(SQLiteCpp REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC SQLiteCpp)
if(LINUX)
find_package(DBus1 REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC dbus-1)
find_package(libsecret REQUIRED CONFIG)
target_link_libraries(${PROJECT_NAME} PUBLIC libsecret::libsecret)
endif()

#libaura Install
Expand Down
2 changes: 1 addition & 1 deletion conanfile-linux.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ libcurl/8.4.0
maddy/1.3.0
sqlcipher/4.5.1
sqlitecpp/3.3.1
dbus/1.15.8
libsecret/0.20.5

[generators]
CMakeDeps
Expand Down
6 changes: 3 additions & 3 deletions include/keyring/credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Nickvision::Aura::Keyring
* @brief Constructs a credential.
* @param id The id of the credential
* @param name The name of the credential
* @param uri The uri of the credential
* @param uri The uri of the credential (can also be used as a comment for the Credential)
* @param username The username of the credential
* @param password The password of the credential
*/
Expand Down Expand Up @@ -45,12 +45,12 @@ namespace Nickvision::Aura::Keyring
*/
void setName(const std::string& name);
/**
* @brief Gets the uri of the credential
* @brief Gets the uri of the credential (can also be used as a comment for the Credential)
* @return The uri of the credential
*/
const std::string& getUri() const;
/**
* @brief Sets the uri of the credential
* @brief Sets the uri of the credential (can also be used as a comment for the Credential)
* @param uri The uri of the credential
*/
void setUri(const std::string& uri);
Expand Down
30 changes: 30 additions & 0 deletions include/keyring/systemcredentials.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef SYSTEMCREDENTIALS_H
#define SYSTEMCREDENTIALS_H

#include <optional>
#include <string>
#include "credential.h"

namespace Nickvision::Aura::Keyring::SystemCredentials
{
/**
* @brief Gets a credential from the system's credential manager.
* @param name The name of the credential
* @return The Credential object, if found
*/
std::optional<Credential> getCredential(const std::string& name);
/**
* @brief Adds a new credential with a random password to the system's credential manager.
* @param name The name of the credential
* @return The new Credential object, if successful
*/
std::optional<Credential> addNewCredential(const std::string& name);
/**
* @brief Deletes a Credential from the system's credential manager
* @param credential The Credential to delete
* @return True if successful, else false
*/
bool deleteCredential(const Credential& credential);
}

#endif //SYSTEMCREDENTIALS_H
93 changes: 93 additions & 0 deletions src/keyring/systemcredentials.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "keyring/systemcredentials.h"
#include <vector>
#include "keyring/passwordgenerator.h"
#ifdef _WIN32
#include <windows.h>
#include <wincred.h>
#else
#include <libsecret/secret.h>
#endif

namespace Nickvision::Aura::Keyring
{
#ifndef _WIN32
static const SecretSchema KEYRING_SCHEMA = { "org.nickvision.aura.keyring", SECRET_SCHEMA_NONE, { { "application", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "NULL", SECRET_SCHEMA_ATTRIBUTE_STRING } } };
#endif

std::optional<Credential> SystemCredentials::getCredential(const std::string& name)
{
#ifdef _WIN32
CREDENTIALA* cred{ nullptr };
if (CredReadA(name.c_str(), CRED_TYPE_GENERIC, 0, &cred))
{
if (cred->CredentialBlob)
{
Credential c{ cred->TargetName, cred->Comment, cred->UserName, LPCSTR(cred->CredentialBlob) };
CredFree(cred);
return c;
}
}
#else
GError* error{ nullptr };
char* password = secret_password_lookup_sync(&KEYRING_SCHEMA, nullptr, &error, "application", name.c_str(), NULL);
if (!error && password)
{
Credential c{ name, "", "default", password };
secret_password_free(password);
return c;
}
g_error_free(error);
#endif
return std::nullopt;
}

std::optional<Credential> SystemCredentials::addNewCredential(const std::string& name)
{
PasswordGenerator passGen;
Credential c{ name, "", "NickvisionKeyring", passGen.next() };
#ifdef _WIN32
CREDENTIALA* cred{ new CREDENTIALA() };
cred->AttributeCount = 0;
cred->Attributes = nullptr;
cred->Comment = nullptr;
cred->Type = CRED_TYPE_GENERIC;
cred->Persist = CRED_PERSIST_LOCAL_MACHINE;
cred->TargetName = LPSTR(c.getName().c_str());
cred->UserName = LPSTR(c.getUsername().c_str());
cred->CredentialBlobSize = (unsigned long)c.getPassword().size();
cred->CredentialBlob = LPBYTE(c.getPassword().c_str());
bool res = CredWriteA(cred, 0);
CredFree(cred);
if (!res)
{
return std::nullopt;
}
return c;
#else
GError* error{ nullptr };
secret_password_store_sync(&KEYRING_SCHEMA, SECRET_COLLECTION_DEFAULT, c.getName().c_str(), c.getPassword().c_str(), nullptr, &error, "application", c.getName().c_str(), NULL);
if (error)
{
g_error_free(error);
return std::nullopt;
}
return c;
#endif
}

bool SystemCredentials::deleteCredential(const Credential& credential)
{
#ifdef _WIN32
return CredDeleteA(credential.getName().c_str(), CRED_TYPE_GENERIC, 0);
#else
GError* error{ nullptr };
bool res = secret_password_clear_sync(&KEYRING_SCHEMA, nullptr, &error, "application", credential.getName().c_str(), NULL);
if (!error)
{
return res;
}
g_error_free(error);
#endif
return false;
}
}

0 comments on commit 0da55c8

Please sign in to comment.