[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [ksecrets] /: Working on api tests
From:       Valentin Rusu <kde () rusu ! info>
Date:       2015-08-12 15:30:42
Message-ID: E1ZPXzG-0007WM-BC () scm ! kde ! org
[Download RAW message or body]

Git commit 19576a02138dd21beaf943b4d4a400b188ebc9c4 by Valentin Rusu.
Committed on 12/08/2015 at 15:29.
Pushed by vrusu into branch 'master'.

Working on api tests

M  +7    -1    autotests/api/ksecretsservice-test.cpp
M  +1    -1    src/runtime/ksecrets_store/CMakeLists.txt
R  +43   -30   src/runtime/ksecrets_store/ksecrets_credentials.cpp [from: \
src/runtime/ksecrets_store/ksecrets_credentials.c - 078% similarity] M  +1    -1    \
src/runtime/ksecrets_store/ksecrets_credentials.h M  +136  -95   \
src/runtime/pam-ksecrets/pam_ksecrets.c

http://commits.kde.org/ksecrets/19576a02138dd21beaf943b4d4a400b188ebc9c4

diff --git a/autotests/api/ksecretsservice-test.cpp b/autotests/api/ksecretsservice-test.cpp
index c16c424..27d967f 100644
--- a/autotests/api/ksecretsservice-test.cpp
+++ b/autotests/api/ksecretsservice-test.cpp
@@ -48,6 +48,7 @@ KSecretServiceTest::KSecretServiceTest(QObject* parent)
 
 KSecrets::CollectionPtr collection;
 KSharedConfig::Ptr sharedConfig;
+QString secretsFilePath;
 
 void KSecretServiceTest::initTestCase()
 {
@@ -58,6 +59,11 @@ void KSecretServiceTest::initTestCase()
     QStandardPaths::setTestModeEnabled(true);
     sharedConfig = KSharedConfig::openConfig(QLatin1String("ksecretsrc"));
 
+    secretsFilePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
+    QVERIFY(QDir::home().mkpath(secretsFilePath));
+    secretsFilePath += QLatin1Literal("/ksecrets-test.data");
+    qDebug() << "secrets store path: " << secretsFilePath;
+
     setupKeyring();
 
     collection = KSecrets::Service::findCollection(
@@ -170,7 +176,7 @@ void KSecretServiceTest::setupKeyring()
     QVERIFY(-1 == key);
 
     /* now go setup user's keyring */
-    QVERIFY(kss_set_credentials(testUser.constData(), testPass.constData()));
+    QVERIFY(kss_set_credentials(testUser.constData(), testPass.constData(), \
secretsFilePath.toLocal8Bit().constData()));  
     // the right keys should be present into the kernel keyring
     key = request_key("user", KEYNAME_ENCRYPTING, 0, KEY_SPEC_SESSION_KEYRING);
diff --git a/src/runtime/ksecrets_store/CMakeLists.txt \
b/src/runtime/ksecrets_store/CMakeLists.txt index 82b5ad1..36fd30d 100644
--- a/src/runtime/ksecrets_store/CMakeLists.txt
+++ b/src/runtime/ksecrets_store/CMakeLists.txt
@@ -9,7 +9,7 @@ ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX KSECRETS_BACKEND
                   PACKAGE_VERSION_FILE \
"${CMAKE_CURRENT_BINARY_DIR}/KF5SecretsStoreConfigVersion.cmake")  
 set(ksecrets_store_SRC
-    ksecrets_credentials.c
+    ksecrets_credentials.cpp
     ksecrets_store.cpp)
 
 add_library(ksecrets_store SHARED ${ksecrets_store_SRC})
diff --git a/src/runtime/ksecrets_store/ksecrets_credentials.c \
b/src/runtime/ksecrets_store/ksecrets_credentials.cpp similarity index 78%
rename from src/runtime/ksecrets_store/ksecrets_credentials.c
rename to src/runtime/ksecrets_store/ksecrets_credentials.cpp
index 155796a..96e4107 100644
--- a/src/runtime/ksecrets_store/ksecrets_credentials.c
+++ b/src/runtime/ksecrets_store/ksecrets_credentials.cpp
@@ -18,6 +18,7 @@
  * Boston, MA 02110-1301, USA.
  */
 #include "ksecrets_credentials.h"
+#include "ksecrets_store.h"
 
 #include <unistd.h>
 #include <errno.h>
@@ -28,7 +29,9 @@
 #include <linux/limits.h>
 #include <pwd.h>
 #include <string.h>
+extern "C" {
 #include <keyutils.h>
+}
 
 #define GCRPYT_NO_DEPRECATED
 #include <gcrypt.h>
@@ -42,14 +45,16 @@
 #define KSECRETS_ITERATIONS 50000
 
 /* these functions are implemented in config.cpp next to this file */
-extern const char* prepare_secret_file_location(const char*);
-extern const char* get_keyname_encrypting();
-extern const char* get_keyname_mac();
+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 FALSE 0
+#define TRUE 1
+#define UNUSED(x) (void)(x)
 
-int kss_init_gcry()
+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)) {
@@ -69,14 +74,15 @@ int kss_init_gcry()
     return 1;
 }
 
-int kss_derive_keys(const char* salt, const char* password, char* encryption_key, char* \
mac_key, size_t keySize) +extern "C"
+int KSECRETS_STORE_EXPORT kss_derive_keys(const char* salt, const char* password, 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 == password) {
         syslog(KSS_LOG_INFO, "NULL password given. ksecrets will not be available.");
-        return false;
+        return FALSE;
     }
 
     /* generate both encryption and MAC key in one go */
@@ -84,24 +90,25 @@ int kss_derive_keys(const char* salt, const char* password, char* \
                encryption_key
     gcryerr = gcry_kdf_derive(password, strlen(password), GCRY_KDF_ITERSALTED_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", gcryerr, \
                gcry_strsource(gcryerr), gcry_strerror(gcryerr));
-        return false;
+        return FALSE;
     }
 
     memcpy(encryption_key, keys, keySize);
     memcpy(mac_key, keys + keySize, keySize);
     syslog(KSS_LOG_INFO, "successuflly generated ksecrets keys from user password.");
 
-    return true;
+    return TRUE;
 }
 
-int kss_store_keys(const char* encryption_key, const char* mac_key, size_t keySize)
+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 = get_keyname_encrypting();
     ks = add_key("user", key_name, encryption_key, keySize, KEY_SPEC_SESSION_KEYRING);
     if (-1 == ks) {
         syslog(KSS_LOG_ERR, "ksecrets: cannot store encryption key in kernel keyring: errno=%d \
                (%m)", errno);
-        return false;
+        return FALSE;
     }
     syslog(KSS_LOG_DEBUG, "ksecrets: encrpyting key now in kernel keyring with id %d and desc \
%s", ks, key_name);  
@@ -109,10 +116,10 @@ int kss_store_keys(const char* encryption_key, const char* mac_key, \
                size_t keySi
     ks = add_key("user", key_name, mac_key, keySize, KEY_SPEC_SESSION_KEYRING);
     if (-1 == ks) {
         syslog(KSS_LOG_ERR, "ksecrets: cannot store mac key in kernel keyring: errno=%d (%m)", \
                errno);
-        return false;
+        return FALSE;
     }
     syslog(KSS_LOG_DEBUG, "ksecrets: mac key now in kernel keyring with id %d and desc %s", \
                ks, key_name);
-    return true;
+    return TRUE;
 }
 
 int kss_keys_already_there()
@@ -121,61 +128,67 @@ int kss_keys_already_there()
     key = request_key("user", get_keyname_encrypting(), 0, KEY_SPEC_SESSION_KEYRING);
     if (-1 == key) {
         syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m), so assuming ksecrets not \
                yet loaded", errno);
-        return false;
+        return FALSE;
     }
     syslog(KSS_LOG_DEBUG, "ksecrets: keys already in keyring");
-    return true;
+    return TRUE;
 }
 
-int kss_set_credentials(const char* user_name, const char* password)
+extern "C"
+int KSECRETS_STORE_EXPORT kss_set_credentials(const char* user_name, const char* password, \
const char* path)  {
-    syslog(KSS_LOG_DEBUG, "kss_set_credentials for %s", user_name);
+    UNUSED(user_name);
     if (kss_keys_already_there())
-        return true;
+        return TRUE;
 
+    KSecretsStore secretsStore;
+    auto setupres = secretsStore.setup(path, password);
 
-    return true;
+    return setupres.get() ? 1 : 0;
 }
 
-int kss_delete_credentials()
+extern "C"
+int KSECRETS_STORE_EXPORT kss_delete_credentials()
 {
     syslog(KSS_LOG_INFO, "kss_delete_credentials");
     key_serial_t key;
     key = request_key("user", get_keyname_encrypting(), 0, KEY_SPEC_SESSION_KEYRING);
     if (-1 == key) {
         syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m), cannot purge encrypting \
                key", errno);
-        return false;
+        return FALSE;
     }
     long res = keyctl(KEYCTL_REVOKE, key);
     if (-1 == res) {
         syslog(KSS_LOG_DEBUG, "removing key failed with errno %d (%m), cannot purge encrypting \
                key", errno);
-        return false;
+        return FALSE;
     }
 
     key = request_key("user", get_keyname_mac(), 0, KEY_SPEC_SESSION_KEYRING);
     if (-1 == key) {
         syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m), cannot purge mac key", \
                errno);
-        return false;
+        return FALSE;
     }
     res = keyctl(KEYCTL_REVOKE, key);
     if (-1 == res) {
         syslog(KSS_LOG_DEBUG, "removing key failed with errno %d (%m), cannot purge mac key", \
                errno);
-        return false;
+        return FALSE;
     }
-    return true;
+    return TRUE;
 }
 
-int kss_can_change_password()
+extern "C"
+int KSECRETS_STORE_EXPORT kss_can_change_password()
 {
     /* nothing to do for the moment */
     syslog(KSS_LOG_INFO, "kss_can_change_password");
-    return true;
+    return TRUE;
 }
 
-int kss_change_password(const char* new_password)
+extern "C"
+int KSECRETS_STORE_EXPORT kss_change_password(const char* new_password)
 {
     syslog(LOG_INFO, "kss_change_password");
-    return true;
+    return TRUE;
 }
 /* vim: tw=220 ts=4
 */
diff --git a/src/runtime/ksecrets_store/ksecrets_credentials.h \
b/src/runtime/ksecrets_store/ksecrets_credentials.h index 0242a24..2b979b5 100644
--- a/src/runtime/ksecrets_store/ksecrets_credentials.h
+++ b/src/runtime/ksecrets_store/ksecrets_credentials.h
@@ -27,7 +27,7 @@
 extern "C" {
 #endif
 
-int kss_set_credentials(const char* user_name, const char* password);
+int kss_set_credentials(const char* user_name, const char* password, const char* path);
 
 int kss_delete_credentials();
 
diff --git a/src/runtime/pam-ksecrets/pam_ksecrets.c b/src/runtime/pam-ksecrets/pam_ksecrets.c
index eaf8f21..bb97632 100644
--- a/src/runtime/pam-ksecrets/pam_ksecrets.c
+++ b/src/runtime/pam-ksecrets/pam_ksecrets.c
@@ -9,133 +9,174 @@
 #include <security/pam_ext.h>
 #include <security/pam_appl.h>
 #include <security/pam_modules.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+#include <linux/limits.h>
+#include <string.h>
 
 #define UNUSED(x) (void)(x)
 
 const char* password;
 
-/* these extern functions are implemented in ksecrets_store_bridge.cpp */
-extern int kss_set_credentials(const char*, const char*);
-extern int kss_delete_credentials();
-extern int kss_can_change_password();
-extern int kss_change_password(const char*);
-
 PAM_EXTERN int pam_sm_authenticate(
     pam_handle_t* pamh, int flags, int argc, const char** argv)
 {
-  pam_syslog(pamh, LOG_INFO, "pam_sm_authenticate flags=%X", flags);
-  UNUSED(flags);
-  UNUSED(argc);
-  UNUSED(argv);
-
-  password = 0;
-  int result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);
-  if (result != PAM_SUCCESS) {
-    pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
-        pam_strerror(pamh, result));
-  }
-
-  /* this module does not participate to the user authentication process */
-  return PAM_IGNORE;
+    pam_syslog(pamh, LOG_INFO, "pam_sm_authenticate flags=%X", flags);
+    UNUSED(flags);
+    UNUSED(argc);
+    UNUSED(argv);
+
+    password = 0;
+    int result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);
+    if (result != PAM_SUCCESS) {
+        pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
+            pam_strerror(pamh, result));
+    }
+
+    /* this module does not participate to the user authentication process */
+    return PAM_IGNORE;
 }
 
+/**
+ * The module PAM module configuration should specify the location of the
+ * secrets file. The location should contain only the part of the path
+ * relative to the user's $HOME directory. So, if you'd like to have secrets
+ * managed in, say, $HOME/owncloud/ksecrets.data then the pam configuration
+ * file should contain something like this:
+ *
+ * auth required pam_ksecrets.so owncloud/ksecrets.data
+ *
+ * As you may have guessed, the configuration will be the same for all the
+ * users, and that cannot be changed from one user to another, at least not in
+ * this version of pam_ksecrets.
+ *
+ * If nothing is specified, then the default path will be
+ * $HOME/.local/share/ksecrets/ksecrets.data
+ *
+ * The location should point to an actual file. If it's a symlink, then the
+ * store handling routine will fail.
+ */
 PAM_EXTERN int pam_sm_setcred(
     pam_handle_t* pamh, int flags, int argc, const char** argv)
 {
-  UNUSED(argc);
-  UNUSED(argv);
-  pam_syslog(pamh, LOG_INFO, "pam_sm_setcred flags=%X", flags);
-  if (flags & PAM_ESTABLISH_CRED) {
-    if (0 == password)
-      return PAM_CRED_UNAVAIL;
-
-    const char* user_name;
-    user_name = 0;
-    int result = pam_get_item(pamh, PAM_USER, (const void**)&user_name);
-    if (result != PAM_SUCCESS) {
-      pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
-          pam_strerror(pamh, result));
+    UNUSED(argc);
+    UNUSED(argv);
+    pam_syslog(pamh, LOG_INFO, "pam_sm_setcred flags=%X", flags);
+    if (flags & PAM_ESTABLISH_CRED) {
+        if (0 == password)
+            return PAM_CRED_UNAVAIL;
+
+        const char* user_name;
+        user_name = 0;
+        int result = pam_get_item(pamh, PAM_USER, (const void**)&user_name);
+        if (result != PAM_SUCCESS) {
+            pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
+                pam_strerror(pamh, result));
+            return PAM_CRED_UNAVAIL;
+        }
+
+        struct passwd *pwd;
+        pwd = getpwnam(user_name);
+        if (pwd == 0) {
+            pam_syslog(pamh, LOG_ERR, "Couldn't get user passwd info %d (%m)", errno);
+            return PAM_CRED_ERR;
+        }
+
+        char secrets_path[PATH_MAX];
+        memset(secrets_path, 0, sizeof(secrets_path)/sizeof(secrets_path[0]));
+        strncpy(secrets_path, pwd->pw_dir, PATH_MAX);
+        static const char *defaultPath = ".local/share/ksecrets/ksecrets.data";
+        if (argc == 1 && argv[0] != 0) {
+            strncat(secrets_path, argv[0], PATH_MAX - strlen(secrets_path) -1);
+        } else {
+            strncat(secrets_path, defaultPath, PATH_MAX - strlen(secrets_path) -1);
+        }
+        pam_syslog(pamh, LOG_INFO, "ksecrets: setting secrets path to %s", secrets_path);
+
+        if (!kss_set_credentials(user_name, password, secrets_path)) {
+            pam_syslog(
+                pamh, LOG_ERR, "ksecrets credentials could not be set.");
+            return PAM_CRED_ERR;
+        }
+        return PAM_SUCCESS;
     }
-    if (!kss_set_credentials(user_name, password)) {
-      pam_syslog(pamh, LOG_ERR, "ksecrets credentials could not be set.");
-      return PAM_CRED_ERR;
+    if (flags & PAM_DELETE_CRED) {
+        kss_delete_credentials();
     }
-    return PAM_SUCCESS;
-  }
-  if (flags & PAM_DELETE_CRED) {
-    kss_delete_credentials();
-  }
-  return PAM_IGNORE;
+    return PAM_IGNORE;
 }
 
 PAM_EXTERN int pam_sm_open_session(
     pam_handle_t* pamh, int flags, int argc, const char** argv)
 {
-  UNUSED(pamh);
-  UNUSED(flags);
-  UNUSED(argc);
-  UNUSED(argv);
-  /* not used */
-  return PAM_IGNORE;
+    UNUSED(pamh);
+    UNUSED(flags);
+    UNUSED(argc);
+    UNUSED(argv);
+    /* not used */
+    return PAM_IGNORE;
 }
 
 PAM_EXTERN int pam_sm_close_session(
     pam_handle_t* pamh, int flags, int argc, const char** argv)
 {
-  UNUSED(pamh);
-  UNUSED(flags);
-  UNUSED(argc);
-  UNUSED(argv);
-  /* not used */
-  return PAM_SUCCESS;
+    UNUSED(pamh);
+    UNUSED(flags);
+    UNUSED(argc);
+    UNUSED(argv);
+    /* not used */
+    return PAM_SUCCESS;
 }
 
 PAM_EXTERN int pam_sm_chauthtok(
     pam_handle_t* pamh, int flags, int argc, const char** argv)
 {
-  UNUSED(argc);
-  UNUSED(argv);
-  pam_syslog(pamh, LOG_INFO, "pam_sm_chauthtok flags=%X", flags);
-
-  if (flags & PAM_PRELIM_CHECK) {
-    pam_syslog(pamh, LOG_INFO, "pam_sm_chauthtok preliminary check");
-    if (kss_can_change_password()) {
-      return PAM_SUCCESS;
-    }
-    else {
-      pam_syslog(pamh, LOG_ERR, "pam_sm_chauthtok prelimnary check failed "
-                                "because ksecrets cannot be locked");
-      return PAM_AUTHTOK_LOCK_BUSY;
-    }
-  }
-
-  if (flags & PAM_UPDATE_AUTHTOK) {
-    pam_syslog(pamh, LOG_INFO,
-        "pam_sm_chauthtok attempt updating ksecret service key");
-
-    const char* password;
-    password = 0;
-    int result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);
-    if (result != PAM_SUCCESS) {
-      pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
-          pam_strerror(pamh, result));
-      return PAM_IGNORE;
-    }
-
-    if (0 == password) {
-      pam_syslog(
-          pamh, LOG_WARNING, "pam_sm_authenticate got NULL password! ");
-      return PAM_AUTHTOK_ERR;
+    UNUSED(argc);
+    UNUSED(argv);
+    pam_syslog(pamh, LOG_INFO, "pam_sm_chauthtok flags=%X", flags);
+
+    if (flags & PAM_PRELIM_CHECK) {
+        pam_syslog(pamh, LOG_INFO, "pam_sm_chauthtok preliminary check");
+        if (kss_can_change_password()) {
+            return PAM_SUCCESS;
+        }
+        else {
+            pam_syslog(pamh, LOG_ERR,
+                "pam_sm_chauthtok prelimnary check failed "
+                "because ksecrets cannot be locked");
+            return PAM_AUTHTOK_LOCK_BUSY;
+        }
     }
 
-    if (kss_change_password(password))
-      return PAM_SUCCESS;
-    else {
-      pam_syslog(pamh, LOG_ERR, "ksecrets service failed to update the keys. "
-                                "Aborting password change.");
-      return PAM_AUTHTOK_ERR;
+    if (flags & PAM_UPDATE_AUTHTOK) {
+        pam_syslog(pamh, LOG_INFO,
+            "pam_sm_chauthtok attempt updating ksecret service key");
+
+        const char* password;
+        password = 0;
+        int result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);
+        if (result != PAM_SUCCESS) {
+            pam_syslog(pamh, LOG_ERR, "Couldn't get password %s",
+                pam_strerror(pamh, result));
+            return PAM_IGNORE;
+        }
+
+        if (0 == password) {
+            pam_syslog(
+                pamh, LOG_WARNING, "pam_sm_authenticate got NULL password! ");
+            return PAM_AUTHTOK_ERR;
+        }
+
+        if (kss_change_password(password))
+            return PAM_SUCCESS;
+        else {
+            pam_syslog(pamh, LOG_ERR,
+                "ksecrets service failed to update the keys. "
+                "Aborting password change.");
+            return PAM_AUTHTOK_ERR;
+        }
     }
-  }
 
-  return PAM_IGNORE;
+    return PAM_IGNORE;
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic