Skip to content

Commit ccd7741

Browse files
authored
Default to libsecret if not Win32 or Apple, allow using it on Apple as an option (#48)
* CMakeLists: improve platform logic * Allow using libsecret on macOS
1 parent aca9e1c commit ccd7741

File tree

2 files changed

+76
-66
lines changed

2 files changed

+76
-66
lines changed

CMakeLists.txt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ include(CMakePackageConfigHelpers)
2525
include(GNUInstallDirs)
2626
include(CTest)
2727

28+
if(APPLE)
29+
option(USE_LIBSECRET "Use libsecret on macOS instead of Apple keychain" OFF)
30+
endif()
31+
2832
#libnick Setup
2933
add_compile_definitions(SQLITE_HAS_CODEC)
3034
if(NOT WIN32)
@@ -94,8 +98,11 @@ endif()
9498
if(WIN32)
9599
find_package(sqlcipher CONFIG REQUIRED)
96100
target_link_libraries(${PROJECT_NAME} PUBLIC sqlcipher::sqlcipher Advapi32 Dnsapi Dwmapi Gdiplus Kernel32 Shell32 UxTheme)
97-
elseif(LINUX)
101+
elseif(APPLE)
98102
set(THREADS_PREFER_PTHREAD_FLAG ON)
103+
find_library(CF_LIBRARY CoreFoundation)
104+
find_library(CS_LIBRARY CoreServices)
105+
find_library(IOKIT_LIBRARY IOKit)
99106
find_package(Threads REQUIRED)
100107
find_package(OpenSSL REQUIRED)
101108
find_package(PkgConfig REQUIRED)
@@ -104,14 +111,16 @@ elseif(LINUX)
104111
pkg_check_modules(gmodule REQUIRED IMPORTED_TARGET gmodule-2.0)
105112
pkg_check_modules(gobject REQUIRED IMPORTED_TARGET gobject-2.0)
106113
pkg_check_modules(gthread REQUIRED IMPORTED_TARGET gthread-2.0)
107-
pkg_check_modules(libsecret REQUIRED IMPORTED_TARGET libsecret-1)
108-
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads OpenSSL::SSL OpenSSL::Crypto PkgConfig::glib PkgConfig::gio PkgConfig::gmodule PkgConfig::gobject PkgConfig::gthread PkgConfig::libsecret)
109-
elseif(APPLE)
114+
if(USE_LIBSECRET)
115+
pkg_check_modules(libsecret REQUIRED IMPORTED_TARGET libsecret-1)
116+
add_compile_definitions(APPLE_USE_LIBSECRET)
117+
target_link_libraries(${PROJECT_NAME} PUBLIC ${CF_LIBRARY} ${CS_LIBRARY} ${IOKIT_LIBRARY} Threads::Threads OpenSSL::SSL OpenSSL::Crypto PkgConfig::glib PkgConfig::gio PkgConfig::gmodule PkgConfig::gobject PkgConfig::gthread PkgConfig::libsecret)
118+
else()
119+
find_library(SECURITY_LIBRARY Security)
120+
target_link_libraries(${PROJECT_NAME} PUBLIC ${CF_LIBRARY} ${CS_LIBRARY} ${IOKIT_LIBRARY} ${SECURITY_LIBRARY} Threads::Threads OpenSSL::SSL OpenSSL::Crypto PkgConfig::glib PkgConfig::gio PkgConfig::gmodule PkgConfig::gobject PkgConfig::gthread)
121+
endif()
122+
else()
110123
set(THREADS_PREFER_PTHREAD_FLAG ON)
111-
find_library(CF_LIBRARY CoreFoundation)
112-
find_library(CS_LIBRARY CoreServices)
113-
find_library(IOKIT_LIBRARY IOKit)
114-
find_library(SECURITY_LIBRARY Security)
115124
find_package(Threads REQUIRED)
116125
find_package(OpenSSL REQUIRED)
117126
find_package(PkgConfig REQUIRED)
@@ -120,7 +129,8 @@ elseif(APPLE)
120129
pkg_check_modules(gmodule REQUIRED IMPORTED_TARGET gmodule-2.0)
121130
pkg_check_modules(gobject REQUIRED IMPORTED_TARGET gobject-2.0)
122131
pkg_check_modules(gthread REQUIRED IMPORTED_TARGET gthread-2.0)
123-
target_link_libraries(${PROJECT_NAME} PUBLIC ${CF_LIBRARY} ${CS_LIBRARY} ${IOKIT_LIBRARY} ${SECURITY_LIBRARY} Threads::Threads OpenSSL::SSL OpenSSL::Crypto PkgConfig::glib PkgConfig::gio PkgConfig::gmodule PkgConfig::gobject PkgConfig::gthread)
132+
pkg_check_modules(libsecret REQUIRED IMPORTED_TARGET libsecret-1)
133+
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads OpenSSL::SSL OpenSSL::Crypto PkgConfig::glib PkgConfig::gio PkgConfig::gmodule PkgConfig::gobject PkgConfig::gthread PkgConfig::libsecret)
124134
endif()
125135

126136
#libnick Install

src/keyring/systemcredentials.cpp

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@
55
#ifdef _WIN32
66
#include <windows.h>
77
#include <wincred.h>
8-
#elif defined(__linux__)
9-
#include <libsecret/secret.h>
10-
#elif defined(__APPLE__)
8+
#elif defined(__APPLE__) && !defined(APPLE_USE_LIBSECRET)
119
#include <CoreFoundation/CoreFoundation.h>
1210
#include <Security/Security.h>
11+
#else
12+
#include <libsecret/secret.h>
1313
#endif
1414

1515
using namespace Nickvision::Helpers;
1616

1717
namespace Nickvision::Keyring
1818
{
19-
#ifdef __linux__
19+
#if !defined(_WIN32) && (!defined(__APPLE__) || defined(APPLE_USE_LIBSECRET))
2020
static const SecretSchema KEYRING_SCHEMA = { "org.nickvision.libnick", SECRET_SCHEMA_NONE, { { "application", SECRET_SCHEMA_ATTRIBUTE_STRING }, { "NULL", SECRET_SCHEMA_ATTRIBUTE_STRING } } };
2121
#endif
2222

@@ -37,20 +37,7 @@ namespace Nickvision::Keyring
3737
return Credential{ StringHelpers::str(credName), StringHelpers::str(credUrl), StringHelpers::str(credUsername), StringHelpers::str(credPassword) };
3838
}
3939
}
40-
#elif defined(__linux__)
41-
GError* error{ nullptr };
42-
char* password{ secret_password_lookup_sync(&KEYRING_SCHEMA, nullptr, &error, "application", name.c_str(), nullptr) };
43-
if (!error && password)
44-
{
45-
Credential c{ name, "", "default", password };
46-
secret_password_free(password);
47-
return c;
48-
}
49-
if (error)
50-
{
51-
g_error_free(error);
52-
}
53-
#elif defined(__APPLE__)
40+
#elif defined(__APPLE__) && !defined(APPLE_USE_LIBSECRET)
5441
CFStringRef nameRef{ CFStringCreateWithCString(nullptr, name.c_str(), kCFStringEncodingUTF8) };
5542
CFMutableDictionaryRef query{ CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
5643
CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
@@ -86,6 +73,19 @@ namespace Nickvision::Keyring
8673
}
8774
CFRelease(query);
8875
CFRelease(nameRef);
76+
#else
77+
GError* error{ nullptr };
78+
char* password{ secret_password_lookup_sync(&KEYRING_SCHEMA, nullptr, &error, "application", name.c_str(), nullptr) };
79+
if (!error && password)
80+
{
81+
Credential c{ name, "", "default", password };
82+
secret_password_free(password);
83+
return c;
84+
}
85+
if (error)
86+
{
87+
g_error_free(error);
88+
}
8989
#endif
9090
return std::nullopt;
9191
}
@@ -123,16 +123,7 @@ namespace Nickvision::Keyring
123123
cred.CredentialBlobSize = static_cast<unsigned long>(password.size() * sizeof(wchar_t));
124124
cred.CredentialBlob = LPBYTE(password.c_str());
125125
return CredWriteW(&cred, 0);
126-
#elif defined(__linux__)
127-
GError* error{ nullptr };
128-
secret_password_store_sync(&KEYRING_SCHEMA, SECRET_COLLECTION_DEFAULT, credential.getName().c_str(), credential.getPassword().c_str(), nullptr, &error, "application", credential.getName().c_str(), nullptr);
129-
if (error)
130-
{
131-
g_error_free(error);
132-
return false;
133-
}
134-
return true;
135-
#elif defined(__APPLE__)
126+
#elif defined(__APPLE__) && !defined(APPLE_USE_LIBSECRET)
136127
CFStringRef name{ CFStringCreateWithCString(nullptr, credential.getName().c_str(), kCFStringEncodingUTF8) };
137128
CFStringRef uri{ CFStringCreateWithCString(nullptr, credential.getUri().c_str(), kCFStringEncodingUTF8) };
138129
CFStringRef username{ CFStringCreateWithCString(nullptr, credential.getUsername().c_str(), kCFStringEncodingUTF8) };
@@ -153,6 +144,15 @@ namespace Nickvision::Keyring
153144
CFRelease(name);
154145
CFRelease(query);
155146
return status == errSecSuccess;
147+
#else
148+
GError* error{ nullptr };
149+
secret_password_store_sync(&KEYRING_SCHEMA, SECRET_COLLECTION_DEFAULT, credential.getName().c_str(), credential.getPassword().c_str(), nullptr, &error, "application", credential.getName().c_str(), nullptr);
150+
if (error)
151+
{
152+
g_error_free(error);
153+
return false;
154+
}
155+
return true;
156156
#endif
157157
}
158158

@@ -183,25 +183,7 @@ namespace Nickvision::Keyring
183183
CredFree(cred);
184184
return res;
185185
}
186-
#elif defined(__linux__)
187-
GError* error{ nullptr };
188-
char* password{ secret_password_lookup_sync(&KEYRING_SCHEMA, nullptr, &error, "application", credential.getName().c_str(), nullptr) };
189-
if (!error && password)
190-
{
191-
secret_password_free(password);
192-
secret_password_store_sync(&KEYRING_SCHEMA, SECRET_COLLECTION_DEFAULT, credential.getName().c_str(), credential.getPassword().c_str(), nullptr, &error, "application", credential.getName().c_str(), nullptr);
193-
if (error)
194-
{
195-
g_error_free(error);
196-
return false;
197-
}
198-
return true;
199-
}
200-
if (error)
201-
{
202-
g_error_free(error);
203-
}
204-
#elif defined(__APPLE__)
186+
#elif defined(__APPLE__) && !defined(APPLE_USE_LIBSECRET)
205187
CFStringRef name{ CFStringCreateWithCString(nullptr, credential.getName().c_str(), kCFStringEncodingUTF8) };
206188
CFMutableDictionaryRef query{ CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
207189
CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
@@ -233,6 +215,24 @@ namespace Nickvision::Keyring
233215
}
234216
CFRelease(query);
235217
CFRelease(name);
218+
#else
219+
GError* error{ nullptr };
220+
char* password{ secret_password_lookup_sync(&KEYRING_SCHEMA, nullptr, &error, "application", credential.getName().c_str(), nullptr) };
221+
if (!error && password)
222+
{
223+
secret_password_free(password);
224+
secret_password_store_sync(&KEYRING_SCHEMA, SECRET_COLLECTION_DEFAULT, credential.getName().c_str(), credential.getPassword().c_str(), nullptr, &error, "application", credential.getName().c_str(), nullptr);
225+
if (error)
226+
{
227+
g_error_free(error);
228+
return false;
229+
}
230+
return true;
231+
}
232+
if (error)
233+
{
234+
g_error_free(error);
235+
}
236236
#endif
237237
return false;
238238
}
@@ -242,7 +242,16 @@ namespace Nickvision::Keyring
242242
#ifdef _WIN32
243243
std::wstring wName{ StringHelpers::wstr(name) };
244244
return CredDeleteW(wName.c_str(), CRED_TYPE_GENERIC, 0);
245-
#elif defined(__linux__)
245+
#elif defined(__APPLE__) && !defined(APPLE_USE_LIBSECRET)
246+
CFStringRef nameRef{ CFStringCreateWithCString(nullptr, name.c_str(), kCFStringEncodingUTF8) };
247+
CFMutableDictionaryRef query{ CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
248+
CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
249+
CFDictionaryAddValue(query, kSecAttrService, nameRef);
250+
OSStatus status{ SecItemDelete(query) };
251+
CFRelease(query);
252+
CFRelease(nameRef);
253+
return status == errSecSuccess;
254+
#else
246255
GError* error{ nullptr };
247256
bool res{ secret_password_clear_sync(&KEYRING_SCHEMA, nullptr, &error, "application", name.c_str(), nullptr) };
248257
if (!error)
@@ -254,15 +263,6 @@ namespace Nickvision::Keyring
254263
g_error_free(error);
255264
}
256265
return false;
257-
#elif defined(__APPLE__)
258-
CFStringRef nameRef{ CFStringCreateWithCString(nullptr, name.c_str(), kCFStringEncodingUTF8) };
259-
CFMutableDictionaryRef query{ CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
260-
CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
261-
CFDictionaryAddValue(query, kSecAttrService, nameRef);
262-
OSStatus status{ SecItemDelete(query) };
263-
CFRelease(query);
264-
CFRelease(nameRef);
265-
return status == errSecSuccess;
266266
#endif
267267
}
268268
}

0 commit comments

Comments
 (0)