From kde-commits Sat Aug 15 14:17:46 2015 From: Valentin Rusu Date: Sat, 15 Aug 2015 14:17:46 +0000 To: kde-commits Subject: [ksecrets] src/runtime: Some refactoring and notes Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=143964827531860 Git commit 4e3eaa8a9fd55ecca1c0bf43bf54f76397d4a923 by Valentin Rusu. Committed on 14/08/2015 at 10:02. Pushed by vrusu into branch 'master'. Some refactoring and notes M +1 -0 src/runtime/ksecrets_store/CMakeLists.txt A +36 -0 src/runtime/ksecrets_store/defines.h [License: LGPL (v2+= )] M +4 -98 src/runtime/ksecrets_store/ksecrets_credentials.cpp A +116 -0 src/runtime/ksecrets_store/ksecrets_crypt.cpp [License: = LGPL (v2+)] M +0 -2 src/runtime/ksecrets_store/ksecrets_store.cpp M +6 -0 src/runtime/pam_ksecrets/pam_ksecrets.c http://commits.kde.org/ksecrets/4e3eaa8a9fd55ecca1c0bf43bf54f76397d4a923 diff --git a/src/runtime/ksecrets_store/CMakeLists.txt b/src/runtime/ksecre= ts_store/CMakeLists.txt index 36fd30d..688f065 100644 --- a/src/runtime/ksecrets_store/CMakeLists.txt +++ b/src/runtime/ksecrets_store/CMakeLists.txt @@ -9,6 +9,7 @@ ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KSECRETS_B= ACKEND PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5Sec= retsStoreConfigVersion.cmake") = set(ksecrets_store_SRC + ksecrets_crypt.cpp ksecrets_credentials.cpp ksecrets_store.cpp) = diff --git a/src/runtime/ksecrets_store/defines.h b/src/runtime/ksecrets_st= ore/defines.h new file mode 100644 index 0000000..6e6e4a9 --- /dev/null +++ b/src/runtime/ksecrets_store/defines.h @@ -0,0 +1,36 @@ +/* + This file is part of the KDE Libraries + + Copyright (C) 2015 Valentin Rusu (valir@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public Lice= nse + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KSECRETS_DEFINES_H +#define KSECRETS_DEFINES_H + +#include + +#define KSS_LOG_DEBUG (LOG_AUTH | LOG_DEBUG) +#define KSS_LOG_INFO (LOG_AUTH | LOG_INFO) +#define KSS_LOG_ERR (LOG_AUTH | LOG_ERR) + +#define KSECRETS_ITERATIONS 50000 + +#define FALSE 0 +#define TRUE 1 +#define UNUSED(x) (void)(x) + +#endif diff --git a/src/runtime/ksecrets_store/ksecrets_credentials.cpp b/src/runt= ime/ksecrets_store/ksecrets_credentials.cpp index 135db0a..53180c0 100644 --- a/src/runtime/ksecrets_store/ksecrets_credentials.cpp +++ b/src/runtime/ksecrets_store/ksecrets_credentials.cpp @@ -19,6 +19,7 @@ */ #include "ksecrets_credentials.h" #include "ksecrets_store.h" +#include "defines.h" = #include #include @@ -33,106 +34,11 @@ extern "C" { #include } = -#define GCRPYT_NO_DEPRECATED -#include = -#define GCRYPT_REQUIRED_VERSION "1.6.0" +const char* get_keyname_encrypting(); +const char* get_keyname_mac(); +int kss_keys_already_there(); = -#define KSS_LOG_DEBUG (LOG_AUTH | LOG_DEBUG) -#define KSS_LOG_INFO (LOG_AUTH | LOG_INFO) -#define KSS_LOG_ERR (LOG_AUTH | LOG_ERR) - -#define KSECRETS_ITERATIONS 50000 - -/* these functions are implemented in config.cpp next to this file */ -extern "C" const char* prepare_secret_file_location(const char*); -extern "C" const char* get_keyname_encrypting(); -extern "C" const char* get_keyname_mac(); - -#define FALSE 0 -#define TRUE 1 -#define UNUSED(x) (void)(x) - -extern "C" -int KSECRETS_STORE_EXPORT kss_init_gcry() -{ - syslog(KSS_LOG_DEBUG, "ksecrets: setting-up grypt library"); - if (!gcry_check_version(GCRYPT_REQUIRED_VERSION)) { - syslog(KSS_LOG_ERR, "ksecrets_store: libcrypt version is too old"); - return 0; - } - - gcry_error_t gcryerr; - gcryerr =3D gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0); - if (gcryerr !=3D 0) { - syslog(KSS_LOG_ERR, "ksecrets_store: cannot get secure memory: %d"= , gcryerr); - return 0; - } - - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - syslog(KSS_LOG_DEBUG, "gcrypt library now set-up"); - return 1; -} - -extern "C" -int KSECRETS_STORE_EXPORT kss_derive_keys(const char* salt, const char* pa= ssword, char* encryption_key, char* mac_key, size_t keySize) -{ - gpg_error_t gcryerr; - - syslog(KSS_LOG_INFO, "kss_set_credentials: attempting keys generation"= ); - if (0 =3D=3D password) { - syslog(KSS_LOG_INFO, "NULL password given. ksecrets will not be av= ailable."); - return FALSE; - } - - /* generate both encryption and MAC key in one go */ - char keys[2 * keySize]; - gcryerr =3D gcry_kdf_derive(password, strlen(password), GCRY_KDF_ITERS= ALTED_S2K, GCRY_MD_SHA512, salt, 8, KSECRETS_ITERATIONS, 2 * keySize, keys); - if (gcryerr) { - syslog(KSS_LOG_ERR, "key derivation failed: code 0x%0x: %s/%s", gc= ryerr, gcry_strsource(gcryerr), gcry_strerror(gcryerr)); - return FALSE; - } - - memcpy(encryption_key, keys, keySize); - memcpy(mac_key, keys + keySize, keySize); - syslog(KSS_LOG_INFO, "successuflly generated ksecrets keys from user p= assword."); - - return TRUE; -} - -extern "C" -int KSECRETS_STORE_EXPORT kss_store_keys(const char* encryption_key, const= char* mac_key, size_t keySize) -{ - key_serial_t ks; - const char* key_name =3D get_keyname_encrypting(); - ks =3D add_key("user", key_name, encryption_key, keySize, KEY_SPEC_SES= SION_KEYRING); - if (-1 =3D=3D ks) { - syslog(KSS_LOG_ERR, "ksecrets: cannot store encryption key in kern= el keyring: errno=3D%d (%m)", errno); - return FALSE; - } - syslog(KSS_LOG_DEBUG, "ksecrets: encrpyting key now in kernel keyring = with id %d and desc %s", ks, key_name); - - key_name =3D get_keyname_mac(); - ks =3D add_key("user", key_name, mac_key, keySize, KEY_SPEC_SESSION_KE= YRING); - if (-1 =3D=3D ks) { - syslog(KSS_LOG_ERR, "ksecrets: cannot store mac key in kernel keyr= ing: errno=3D%d (%m)", errno); - return FALSE; - } - syslog(KSS_LOG_DEBUG, "ksecrets: mac key now in kernel keyring with id= %d and desc %s", ks, key_name); - return TRUE; -} - -int kss_keys_already_there() -{ - key_serial_t key; - key =3D request_key("user", get_keyname_encrypting(), 0, KEY_SPEC_SESS= ION_KEYRING); - if (-1 =3D=3D key) { - syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m), so a= ssuming ksecrets not yet loaded", errno); - return FALSE; - } - syslog(KSS_LOG_DEBUG, "ksecrets: keys already in keyring"); - return TRUE; -} = extern "C" int KSECRETS_STORE_EXPORT kss_set_credentials(const char* user_name, const= char* password, const char* path) diff --git a/src/runtime/ksecrets_store/ksecrets_crypt.cpp b/src/runtime/ks= ecrets_store/ksecrets_crypt.cpp new file mode 100644 index 0000000..c087cbb --- /dev/null +++ b/src/runtime/ksecrets_store/ksecrets_crypt.cpp @@ -0,0 +1,116 @@ +/* + This file is part of the KDE Libraries + + Copyright (C) 2015 Valentin Rusu (valir@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public Lice= nse + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "defines.h" + +#include +#include + +extern "C" { +#include +} + +#define GCRPYT_NO_DEPRECATED +#include + +#define GCRYPT_REQUIRED_VERSION "1.6.0" + +const char* get_keyname_encrypting(); +const char* get_keyname_mac(); + +int kss_init_gcry() +{ + syslog(KSS_LOG_DEBUG, "ksecrets: setting-up grypt library"); + if (!gcry_check_version(GCRYPT_REQUIRED_VERSION)) { + syslog(KSS_LOG_ERR, "ksecrets_store: libcrypt version is too old"); + return 0; + } + + gcry_error_t gcryerr; + gcryerr =3D gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0); + if (gcryerr !=3D 0) { + syslog(KSS_LOG_ERR, "ksecrets_store: cannot get secure memory: %d"= , gcryerr); + return 0; + } + + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + syslog(KSS_LOG_DEBUG, "gcrypt library now set-up"); + return 1; +} + +int kss_derive_keys(const char* salt, const char* password, char* encrypti= on_key, char* mac_key, size_t keySize) +{ + gpg_error_t gcryerr; + + syslog(KSS_LOG_INFO, "kss_set_credentials: attempting keys generation"= ); + if (0 =3D=3D password) { + syslog(KSS_LOG_INFO, "NULL password given. ksecrets will not be av= ailable."); + return FALSE; + } + + /* generate both encryption and MAC key in one go */ + char keys[2 * keySize]; + gcryerr =3D gcry_kdf_derive(password, strlen(password), GCRY_KDF_ITERS= ALTED_S2K, GCRY_MD_SHA512, salt, 8, KSECRETS_ITERATIONS, 2 * keySize, keys); + if (gcryerr) { + syslog(KSS_LOG_ERR, "key derivation failed: code 0x%0x: %s/%s", gc= ryerr, gcry_strsource(gcryerr), gcry_strerror(gcryerr)); + return FALSE; + } + + memcpy(encryption_key, keys, keySize); + memcpy(mac_key, keys + keySize, keySize); + syslog(KSS_LOG_INFO, "successuflly generated ksecrets keys from user p= assword."); + + return TRUE; +} + +int kss_store_keys(const char* encryption_key, const char* mac_key, size_t= keySize) +{ + key_serial_t ks; + const char* key_name =3D get_keyname_encrypting(); + ks =3D add_key("user", key_name, encryption_key, keySize, KEY_SPEC_SES= SION_KEYRING); + if (-1 =3D=3D ks) { + syslog(KSS_LOG_ERR, "ksecrets: cannot store encryption key in kern= el keyring: errno=3D%d (%m)", errno); + return FALSE; + } + syslog(KSS_LOG_DEBUG, "ksecrets: encrpyting key now in kernel keyring = with id %d and desc %s", ks, key_name); + + key_name =3D get_keyname_mac(); + ks =3D add_key("user", key_name, mac_key, keySize, KEY_SPEC_SESSION_KE= YRING); + if (-1 =3D=3D ks) { + syslog(KSS_LOG_ERR, "ksecrets: cannot store mac key in kernel keyr= ing: errno=3D%d (%m)", errno); + return FALSE; + } + syslog(KSS_LOG_DEBUG, "ksecrets: mac key now in kernel keyring with id= %d and desc %s", ks, key_name); + return TRUE; +} + +int kss_keys_already_there() +{ + key_serial_t key; + key =3D request_key("user", get_keyname_encrypting(), 0, KEY_SPEC_SESS= ION_KEYRING); + if (-1 =3D=3D key) { + syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m), so a= ssuming ksecrets not yet loaded", errno); + return FALSE; + } + syslog(KSS_LOG_DEBUG, "ksecrets: keys already in keyring"); + return TRUE; +} + diff --git a/src/runtime/ksecrets_store/ksecrets_store.cpp b/src/runtime/ks= ecrets_store/ksecrets_store.cpp index 290ee00..4f8dde9 100644 --- a/src/runtime/ksecrets_store/ksecrets_store.cpp +++ b/src/runtime/ksecrets_store/ksecrets_store.cpp @@ -40,13 +40,11 @@ const char* keyNameEncrypting =3D nullptr; const char* keyNameMac =3D nullptr; = -extern "C" { bool kss_init_gcry(); bool kss_derive_keys(const char* salt, const char* password, char* encrypt= ion_key, char* mac_key, size_t); bool kss_store_keys(const char* encryption_key, const char* mac_key, size_= t keySize); const char* get_keyname_encrypting() { return keyNameEncrypting; } const char* get_keyname_mac() { return keyNameMac; } -} = KSecretsStorePrivate::KSecretsStorePrivate(KSecretsStore* b) : b_(b) diff --git a/src/runtime/pam_ksecrets/pam_ksecrets.c b/src/runtime/pam_ksec= rets/pam_ksecrets.c index bb97632..c32cfc1 100644 --- a/src/runtime/pam_ksecrets/pam_ksecrets.c +++ b/src/runtime/pam_ksecrets/pam_ksecrets.c @@ -54,6 +54,12 @@ PAM_EXTERN int pam_sm_authenticate( * If nothing is specified, then the default path will be * $HOME/.local/share/ksecrets/ksecrets.data * + * FIXME see how this could be simplified or how one could add a configura= tion + * file handling here. Handling configuration files is DE specific and this + * pam module tries to stay as generic as possible. Perhaps we could add h= ere + * a DE-specific plugin that would retrieve values from the DE-specific co= nfiguration + * files, using the DE-specific configuration handling libraries. + * * The location should point to an actual file. If it's a symlink, then the * store handling routine will fail. */