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

List:       kde-commits
Subject:    [ksecrets] src/runtime/ksecrets_store: Introducting persistance logic base
From:       Valentin Rusu <kde () rusu ! info>
Date:       2015-08-18 22:40:45
Message-ID: E1ZRpYj-0003om-0M () scm ! kde ! org
[Download RAW message or body]

Git commit 1167bb267d28d40e150a4c788891fc5218e4a4c9 by Valentin Rusu.
Committed on 18/08/2015 at 22:40.
Pushed by vrusu into branch 'master'.

Introducting persistance logic base

M  +30   -64   src/runtime/ksecrets_store/ksecrets_crypt.cpp
M  +2    -1    src/runtime/ksecrets_store/ksecrets_crypt.h
M  +108  -23   src/runtime/ksecrets_store/ksecrets_data.cpp
M  +63   -7    src/runtime/ksecrets_store/ksecrets_data.h
M  +25   -0    src/runtime/ksecrets_store/ksecrets_file.cpp
M  +7    -2    src/runtime/ksecrets_store/ksecrets_file.h
M  +38   -0    src/runtime/ksecrets_store/ksecrets_store.cpp
M  +12   -5    src/runtime/ksecrets_store/ksecrets_store.h
M  +4    -0    src/runtime/ksecrets_store/ksecrets_store_p.h

http://commits.kde.org/ksecrets/1167bb267d28d40e150a4c788891fc5218e4a4c9

diff --git a/src/runtime/ksecrets_store/ksecrets_crypt.cpp \
b/src/runtime/ksecrets_store/ksecrets_crypt.cpp index a5a32f8..2b25867 100644
--- a/src/runtime/ksecrets_store/ksecrets_crypt.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_crypt.cpp
@@ -52,8 +52,7 @@ int kss_init_gcry()
     gcry_error_t gcryerr;
     gcryerr = gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
     if (gcryerr != 0) {
-        syslog(KSS_LOG_ERR, "ksecrets_store: cannot get secure memory: %d",
-            gcryerr);
+        syslog(KSS_LOG_ERR, "ksecrets_store: cannot get secure memory: %d", gcryerr);
         return 0;
     }
 
@@ -62,44 +61,36 @@ 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)
+int 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.");
+        syslog(KSS_LOG_INFO, "NULL password given. ksecrets will not be available.");
         return FALSE;
     }
 
     /* generate both encryption and MAC key in one go */
     char keys[2 * keySize];
-    gcryerr
-        = gcry_kdf_derive(password, strlen(password), GCRY_KDF_ITERSALTED_S2K,
-            GCRY_MD_SHA512, salt, 8, KSECRETS_ITERATIONS, 2 * keySize, keys);
+    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));
+        syslog(KSS_LOG_ERR, "key derivation failed: code 0x%0x: %s/%s", gcryerr, \
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 password.");
+    syslog(KSS_LOG_INFO, "successuflly generated ksecrets keys from user password.");
 
     return TRUE;
 }
 
-int kss_store_keys(
-    const char* encryption_key, const char* mac_key, size_t keySize)
+int 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);
+    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)",
@@ -111,17 +102,12 @@ int kss_store_keys(
         ks, key_name);
 
     key_name = get_keyname_mac();
-    ks = add_key(
-        "user", key_name, mac_key, keySize, KEY_SPEC_SESSION_KEYRING);
+    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);
+        syslog(KSS_LOG_ERR, "ksecrets: cannot store mac key in kernel keyring: errno=%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);
+    syslog(KSS_LOG_DEBUG, "ksecrets: mac key now in kernel keyring with id %d and desc %s", \
ks, key_name);  return TRUE;
 }
 
@@ -131,8 +117,7 @@ int kss_set_credentials(const std::string& password, const char* salt)
     // available and store the keys elsewhere
     char encryption_key[KSECRETS_KEYSIZE];
     char mac_key[KSECRETS_KEYSIZE];
-    auto res = kss_derive_keys(
-        salt, password.c_str(), encryption_key, mac_key, KSECRETS_KEYSIZE);
+    auto res = kss_derive_keys(salt, password.c_str(), encryption_key, mac_key, \
KSECRETS_KEYSIZE);  if (res)
         return res;
 
@@ -142,8 +127,7 @@ int kss_set_credentials(const std::string& password, const char* salt)
 int kss_keys_already_there()
 {
     key_serial_t key;
-    key = request_key(
-        "user", get_keyname_encrypting(), 0, KEY_SPEC_SESSION_KEYRING);
+    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",
@@ -159,15 +143,12 @@ long kss_read_key(const char* keyName, char* buffer, size_t bufferSize)
     key_serial_t key;
     key = request_key("user", keyName, 0, KEY_SPEC_SESSION_KEYRING);
     if (-1 == key) {
-        syslog(KSS_LOG_DEBUG,
-            "request_key failed with errno %d (%m) when reading MAC key %s",
-            errno, keyName);
+        syslog(KSS_LOG_DEBUG, "request_key failed with errno %d (%m) when reading MAC key %s", \
errno, keyName);  return -1;
     }
     auto bytes = keyctl_read(key, buffer, bufferSize);
     if (bytes == -1) {
-        syslog(KSS_LOG_ERR, "error reading key %s contents from the keyring",
-            keyName);
+        syslog(KSS_LOG_ERR, "error reading key %s contents from the keyring", keyName);
         return -1;
     }
     if ((size_t)bytes > bufferSize) {
@@ -176,15 +157,9 @@ long kss_read_key(const char* keyName, char* buffer, size_t bufferSize)
     return 0; // key contents correctly transffered into the buffer
 }
 
-long kss_read_mac_key(char* buffer, size_t bufferSize)
-{
-    return kss_read_key(get_keyname_mac(), buffer, bufferSize);
-}
+long kss_read_mac_key(char* buffer, size_t bufferSize) { return \
kss_read_key(get_keyname_mac(), buffer, bufferSize); }  
-long kss_read_encrypting_key(char* buffer, size_t bufferSize)
-{
-    return kss_read_key(get_keyname_encrypting(), buffer, bufferSize);
-}
+long kss_read_encrypting_key(char* buffer, size_t bufferSize) { return \
kss_read_key(get_keyname_encrypting(), buffer, bufferSize); }  
 #define ERRNO(cryres) gcry_err_code_to_errno(gcry_err_code(cryres))
 
@@ -192,39 +167,31 @@ long kss_cipher_setup(gcry_cipher_hd_t* hd, const void* iv, size_t liv)
 {
     // FIXME perhaps all this initialization stuff could only be done once,
     // when password is setup
-    auto cryres
-        = gcry_cipher_open(hd, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
+    auto cryres = gcry_cipher_open(hd, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
     if (cryres) {
-        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_open returned error %d",
-            cryres);
+        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_open returned error %d", cryres);
         return ERRNO(cryres);
     }
     cryres = gcry_cipher_setiv(*hd, iv, liv);
     if (cryres) {
-        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_setif returned error %d",
-            cryres);
+        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_setif returned error %d", cryres);
         return ERRNO(cryres);
     }
     char encryptingKey[KSECRETS_KEYSIZE];
-    auto keyres = kss_read_encrypting_key(
-        encryptingKey, sizeof(encryptingKey) / sizeof(encryptingKey[0]));
+    auto keyres = kss_read_encrypting_key(encryptingKey, sizeof(encryptingKey) / \
sizeof(encryptingKey[0]));  if (!keyres) {
-        syslog(
-            KSS_LOG_ERR, "ksecrets: encrypting key not found in the keyring");
+        syslog(KSS_LOG_ERR, "ksecrets: encrypting key not found in the keyring");
         return keyres;
     }
-    cryres = gcry_cipher_setkey(
-        *hd, encryptingKey, sizeof(encryptingKey) / sizeof(encryptingKey[0]));
+    cryres = gcry_cipher_setkey(*hd, encryptingKey, sizeof(encryptingKey) / \
sizeof(encryptingKey[0]));  if (cryres) {
-        syslog(
-            KSS_LOG_ERR, "ksecrets: gcry_cipher_setkey returned %d", cryres);
+        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_setkey returned %d", cryres);
         return ERRNO(cryres);
     }
     return 0;
 }
 
-long kss_encrypt_buffer(unsigned char* out, size_t lout, const void* iv,
-    size_t liv, const unsigned char* in, size_t lin)
+long kss_encrypt_buffer(unsigned char* out, size_t lout, const void* iv, size_t liv, const \
unsigned char* in, size_t lin)  {
     gcry_cipher_hd_t hd;
     auto cryres = kss_cipher_setup(&hd, iv, liv);
@@ -232,15 +199,13 @@ long kss_encrypt_buffer(unsigned char* out, size_t lout, const void* iv,
         return cryres; // error already logged
     cryres = gcry_cipher_encrypt(hd, out, lout, in, lin);
     if (cryres) {
-        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_encrypt returned %ld",
-            cryres);
+        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_encrypt returned %ld", cryres);
         return ERRNO(cryres);
     }
     return 0;
 }
 
-long kss_decrypt_buffer(unsigned char* out, size_t lout, const void* iv,
-    size_t liv, const unsigned char* in, size_t lin)
+long kss_decrypt_buffer(unsigned char* out, size_t lout, const void* iv, size_t liv, const \
unsigned char* in, size_t lin)  {
     gcry_cipher_hd_t hd;
     auto cryres = kss_cipher_setup(&hd, iv, liv);
@@ -248,13 +213,14 @@ long kss_decrypt_buffer(unsigned char* out, size_t lout, const void* iv,
         return cryres; // error already logged
     cryres = gcry_cipher_decrypt(hd, out, lout, in, lin);
     if (cryres) {
-        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_decrypt returned %ld",
-            cryres);
+        syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_decrypt returned %ld", cryres);
         return ERRNO(cryres);
     }
     return 0;
 }
 
+CryptBuffer::~CryptBuffer() { delete[] data_; }
+
 bool CryptBuffer::resize(size_t rlen)
 {
     if (rlen <= len_) {
diff --git a/src/runtime/ksecrets_store/ksecrets_crypt.h \
b/src/runtime/ksecrets_store/ksecrets_crypt.h index 86e1788..742e42e 100644
--- a/src/runtime/ksecrets_store/ksecrets_crypt.h
+++ b/src/runtime/ksecrets_store/ksecrets_crypt.h
@@ -29,7 +29,8 @@ struct CryptBuffer {
         , data_(nullptr)
     {
     }
-    ~CryptBuffer() { delete[] data_; }
+    CryptBuffer(CryptBuffer&&) = default;
+    ~CryptBuffer();
 
     /**
      * @brief Allocate memory in multiples of cipher block len
diff --git a/src/runtime/ksecrets_store/ksecrets_data.cpp \
b/src/runtime/ksecrets_store/ksecrets_data.cpp index 61a8f64..7c9aa81 100644
--- a/src/runtime/ksecrets_store/ksecrets_data.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_data.cpp
@@ -22,11 +22,11 @@
 #include "ksecrets_file.h"
 
 #include <unistd.h>
+#include <algorithm>
+#include <cassert>
 
-long kss_encrypt_buffer(unsigned char* out, size_t lout, const void* iv,
-    size_t liv, const unsigned char* in, size_t lin);
-long kss_decrypt_buffer(unsigned char* out, size_t lout, const void* iv,
-    size_t liv, const unsigned char* in, size_t lin);
+long kss_encrypt_buffer(unsigned char* out, size_t lout, const void* iv, size_t liv, const \
unsigned char* in, size_t lin); +long kss_decrypt_buffer(unsigned char* out, size_t lout, const \
void* iv, size_t liv, const unsigned char* in, size_t lin);  char* \
kss_alloc_crypt_buffer(size_t rlen);  
 SecretsEntity::SecretsEntity()
@@ -42,47 +42,132 @@ SecretsEntity::~SecretsEntity() {}
 const char* iv = nullptr;
 size_t liv = KSecretsFile::IV_SIZE;
 
+bool SecretsEntity::decrypt()
+{
+    if (isEmpty())
+        return false;
+    if (unencrypted_.len_ > 0)
+        return true; // already decrpyted
+    if (encrypted_.len_ == 0)
+        return false; // what to decrypt?
+    unencrypted_.allocate(encrypted_.len_);
+    auto dres = kss_decrypt_buffer(unencrypted_.data_, unencrypted_.len_, iv, liv, \
encrypted_.data_, encrypted_.len_); +    return dres == 0;
+}
+
+bool SecretsEntity::encrypt()
+{
+    // TODO
+    return false;
+}
+
+bool SecretsEntity::write(KSecretsFile& file)
+{
+    bool res = false;
+    if (doBeforeWrite()) {
+        if (encrypt()) {
+            assert(state_ == State::Encrypted);
+            if (file.write(encrypted_.len_)) {
+                if (encrypted_.len_ > 0) {
+                    assert(encrypted_.data_ != nullptr);
+                    if (file.write(encrypted_.data_, encrypted_.len_)) {
+                        res = true;
+                    }
+                }
+                else {
+                    res = true;
+                }
+            }
+        }
+    }
+    if (res)
+        return doAfterWrite();
+    else
+        return res;
+}
+
 bool SecretsEntity::read(KSecretsFile& file)
 {
     if (iv == nullptr) {
         iv = file.iv();
     }
+    if (!doBeforeRead())
+        return false;
 
-    size_t s;
-    if (!file.read(s)) {
+    encrypted_.empty();
+    size_t len;
+    if (!file.read(len))
         return false;
-    }
-    if (!encrypted_.allocate(s)) {
+
+    if (!encrypted_.allocate(len))
         return false;
+
+    if (len > 0) {
+        if (!file.read(encrypted_.data_, encrypted_.len_))
+            return false;
     }
 
-    return file.read(encrypted_.data_,
-        encrypted_.len_); // beware not to specify encrypted.size_ here
+    return doAfterRead();
 }
 
-bool SecretsEntity::decrypt()
+CollectionDirectory::CollectionDirectory()
 {
-    if (isEmpty())
-        return false;
-    if (unencrypted_.len_ > 0)
-        return true; // already decrpyted
-    if (encrypted_.len_ == 0)
-        return false; // what to decrypt?
-    unencrypted_.allocate(encrypted_.len_);
-    auto dres = kss_decrypt_buffer(unencrypted_.data_, unencrypted_.len_, iv,
-        liv, encrypted_.data_, encrypted_.len_);
-    return dres == 0;
 }
 
-bool SecretsEntity::encrypt()
+bool CollectionDirectory::hasEntry(const std::string& collName) const
+{
+    auto pos = std::find(entries_.begin(), entries_.end(), collName);
+    return pos != entries_.end();
+}
+
+bool CollectionDirectory::doBeforeWrite()
+{
+    // TODO
+    return false;
+}
+
+bool CollectionDirectory::doAfterRead()
+{
+    // TODO
+    return false;
+}
+
+void SecretsCollection::setName(const std::string& name) { name_ = name; }
+
+bool SecretsCollection::doBeforeWrite()
 {
     // TODO
     return false;
 }
 
-bool SecretsEntity::write(KSecretsFile &) const
+bool SecretsCollection::doAfterRead()
 {
     // TODO
     return false;
 }
+
+bool SecretsItem::doBeforeWrite()
+{
+    // TODO
+    return false;
+}
+
+bool SecretsItem::doAfterRead()
+{
+    // TODO
+    return false;
+}
+
+bool SecretsEOF::doBeforeWrite()
+{
+    // TODO
+    return false;
+}
+
+bool SecretsEOF::doAfterRead()
+{
+    // TODO
+    return false;
+}
+
 // vim: tw=220:ts=4
diff --git a/src/runtime/ksecrets_store/ksecrets_data.h \
b/src/runtime/ksecrets_store/ksecrets_data.h index dca51f7..a233c41 100644
--- a/src/runtime/ksecrets_store/ksecrets_data.h
+++ b/src/runtime/ksecrets_store/ksecrets_data.h
@@ -25,6 +25,8 @@
 
 #include <cstdint>
 #include <sys/types.h>
+#include <memory>
+#include <list>
 
 class KSecretsFile;
 
@@ -34,11 +36,17 @@ class KSecretsFile;
  * TODO this class uses routines from ksecrets_crypt.cpp file to handle
  * encrypting and decrypting of the files. It would be better to define some
  * plugin architecture, allowing users specify different encryption methods.
+ *
+ * TODO in the future, if the need arises to add another file format, this
+ *code
+ * could be easily refactored to use the "visitor" pattern and convert the
+ * read and write methods to use a generic type which would then be
+ * implemented by the KSecretsFile. For now, no need of such generalization,
+ * as I cannot foresee the introduction of another file format (why should I?)
  */
-struct SecretsEntity {
+class SecretsEntity {
+public:
     SecretsEntity();
-    SecretsEntity(const SecretsEntity&) = delete;
-    SecretsEntity(SecretsEntity&&) = delete;
     virtual ~SecretsEntity();
 
     enum class State : std::uint8_t {
@@ -48,6 +56,7 @@ struct SecretsEntity {
     };
 
     bool isEmpty() const noexcept { return state_ == State::Empty; }
+    virtual bool hasNext() const noexcept { return true; }
     bool isDecrypted() const noexcept
     {
         return (static_cast<std::uint8_t>(state_)
@@ -57,18 +66,65 @@ struct SecretsEntity {
     virtual bool decrypt() noexcept;
     virtual bool encrypt() noexcept;
 
-    virtual bool read(KSecretsFile&) noexcept;
-    virtual bool write(KSecretsFile&) const noexcept;
+    bool read(KSecretsFile&) noexcept;
+    virtual bool doBeforeRead() noexcept { return true; }
+    virtual bool doAfterRead() noexcept = 0;
+
+    bool write(KSecretsFile&) noexcept;
+    virtual bool doBeforeWrite() noexcept = 0;
+    virtual bool doAfterWrite() noexcept { return true; }
 
     State state_;
     CryptBuffer encrypted_;
     CryptBuffer unencrypted_;
 };
 
-struct SecretsCollection : public SecretsEntity {
+using SecretsEntityPtr = std::shared_ptr<SecretsEntity>;
+
+class SecretsCollection : public SecretsEntity {
+public:
+    void setName(const std::string&) noexcept;
+
+private:
+    virtual bool doBeforeWrite() noexcept override;
+    virtual bool doAfterRead() noexcept override;
+
+    std::string name_;
 };
 
-struct CollectionDirectory : public SecretsEntity {
+using SecretsCollectionPtr = std::shared_ptr<SecretsCollection>;
+
+class CollectionDirectory : public SecretsEntity {
+public:
+    CollectionDirectory();
+    bool hasEntry(const std::string&) const noexcept;
+
+private:
+    virtual bool doBeforeWrite() noexcept override;
+    virtual bool doAfterRead() noexcept override;
+
+    std::list<std::string> entries_;
 };
 
+using CollectionDirectoryPtr = std::shared_ptr<CollectionDirectory>;
+
+class SecretsItem : public SecretsEntity {
+public:
+private:
+    virtual bool doBeforeWrite() noexcept override;
+    virtual bool doAfterRead() noexcept override;
+};
+
+using SecretsItemPtr = std::shared_ptr<SecretsItem>;
+
+class SecretsEOF : public SecretsEntity {
+private:
+    bool hasNext() const noexcept override { return false; }
+    virtual bool doBeforeWrite() noexcept override;
+    virtual bool doAfterRead() noexcept override;
+};
+
+using SecretsEOFPtr = std::shared_ptr<SecretsEOF>;
+
 #endif
+// vim: tw=220:ts=4
diff --git a/src/runtime/ksecrets_store/ksecrets_file.cpp \
b/src/runtime/ksecrets_store/ksecrets_file.cpp index c3dc275..2fc075b 100644
--- a/src/runtime/ksecrets_store/ksecrets_file.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_file.cpp
@@ -141,6 +141,23 @@ int KSecretsFile::checkMAC() const
     return -1;
 }
 
+bool KSecretsFile::write(size_t s) { return write(&s, sizeof(size_t)); }
+
+bool KSecretsFile::write(const void* buf, size_t len)
+{
+    auto wres = ::write(file_, buf, len);
+    if (wres <0) {
+        return setFailState(errno);
+    }
+    if (static_cast<size_t>(wres) < len) {
+        // no more space left on the file system
+        // FIXME we should prevent such an event by keeping versions of the secrets file
+        // TODO manage secrets file versions to prevent this kind of problem
+        return setFailState(ENOSPC);
+    }
+    return true;
+}
+
 bool KSecretsFile::read(size_t& s) { return read(&s, sizeof(s)); }
 
 bool KSecretsFile::read(void* buf, size_t len)
@@ -184,4 +201,12 @@ bool KSecretsFile::readDirectory()
 
 bool KSecretsFile::decryptEntity(SecretsEntity& entity) { return entity.decrypt(); }
 
+SecretsCollectionPtr KSecretsFile::createCollection(const std::string &collName) noexcept
+{
+    auto newColl = std::make_shared<SecretsCollection>();
+    newColl->setName(collName);
+    entities_.emplace_front(newColl);
+    return std::dynamic_pointer_cast<SecretsCollection>(entities_.front());
+}
+
 // vim: tw=220:ts=4
diff --git a/src/runtime/ksecrets_store/ksecrets_file.h \
b/src/runtime/ksecrets_store/ksecrets_file.h index 5ed8c79..3c9b2e7 100644
--- a/src/runtime/ksecrets_store/ksecrets_file.h
+++ b/src/runtime/ksecrets_store/ksecrets_file.h
@@ -24,7 +24,7 @@
 #include "ksecrets_data.h"
 
 #include <memory>
-#include <list>
+#include <forward_list>
 
 /**
  * @brief This is the secrets file format handling class
@@ -53,9 +53,14 @@ public:
     int checkMAC() const noexcept;
     bool read(void* buf, size_t count);
     bool read(size_t&);
+    int errnumber() const noexcept { return errno_; }
+    bool eof() const noexcept { return eof_; }
+    bool write(const void *buf, size_t count);
+    bool write(size_t len);
 
     using DirCollectionResult = std::pair<bool, const CollectionDirectory*>;
     DirCollectionResult dirCollections() noexcept;
+    SecretsCollectionPtr createCollection(const std::string &collName) noexcept;
 
 private:
     bool setFailState(int err, bool retval = false) noexcept
@@ -70,7 +75,7 @@ private:
     bool readDirectory() noexcept;
     bool decryptEntity(SecretsEntity&) noexcept;
 
-    using Entities = std::list<SecretsEntity*>;
+    using Entities = std::forward_list<SecretsEntityPtr>;
 
     std::string filePath_;
     int file_;
diff --git a/src/runtime/ksecrets_store/ksecrets_store.cpp \
b/src/runtime/ksecrets_store/ksecrets_store.cpp index 8e4bf00..b88b83d 100644
--- a/src/runtime/ksecrets_store/ksecrets_store.cpp
+++ b/src/runtime/ksecrets_store/ksecrets_store.cpp
@@ -170,13 +170,51 @@ KSecretsStore::CreateCollectionResult \
KSecretsStore::createCollection(const char  return d->createCollection(collName);
 }
 
+template <class R>
+R mapSecretsFileFailure(KSecretsFile &file, R &&r)
+{
+    if (file.errnumber()) {
+        r.errno_ = file.errnumber();
+        r.status_ = KSecretsStore::StoreStatus::SystemError;
+    } else {
+        if (file.eof()) {
+            r.status_ = KSecretsStore::StoreStatus::PrematureEndOfFileEncountered;
+        } else {
+            r.status_ = KSecretsStore::StoreStatus::UnknownError; // really, we should get \
here very seldom +        }
+    }
+
+    return r;
+}
+
 KSecretsStore::CreateCollectionResult KSecretsStorePrivate::createCollection(const std::string \
&collName) noexcept  {
     KSecretsStore::CreateCollectionResult res;
+    auto cptr = std::make_shared<KSecretsCollectionPrivate>();
+    if (!cptr->createCollection(secretsFile_, collName)) {
+        return mapSecretsFileFailure(secretsFile_, res);
+    }
+    res.result_ = std::make_shared<KSecretsStore::Collection>(cptr);
+    return res;
+}
 
+bool KSecretsCollectionPrivate::createCollection(KSecretsFile &file, const std::string \
&collName) +{
+    bool res = false;
+    auto dir =  file.dirCollections();
+    if (dir.first) {
+        if (!dir.second->hasEntry(collName)) {
+            collection_data_ = file.createCollection(collName);
+            if (collection_data_ != nullptr) {
+                res = true;
+            }
+        }
+    }
     return res;
 }
 
+KSecretsStore::Collection::Collection(KSecretsCollectionPrivatePtr dptr) : d(dptr) {}
+
 KSecretsStore::ReadCollectionResult KSecretsStore::readCollection(const char*) const noexcept
 {
     // TODO
diff --git a/src/runtime/ksecrets_store/ksecrets_store.h \
b/src/runtime/ksecrets_store/ksecrets_store.h index 6b899b0..136b0c1 100644
--- a/src/runtime/ksecrets_store/ksecrets_store.h
+++ b/src/runtime/ksecrets_store/ksecrets_store.h
@@ -31,6 +31,12 @@
 #include <future>
 
 class KSecretsStorePrivate;
+class KSecretsItemPrivate;
+class KSecretsCollectionPrivate;
+
+using KSecretsItemPrivatePtr = std::shared_ptr<KSecretsItemPrivate>;
+using KSecretsCollectionPrivatePtr = std::shared_ptr<KSecretsCollectionPrivate>;
+
 
 /**
  * Secrets storage for KSecrets Service.
@@ -72,9 +78,6 @@ class KSecretsStorePrivate;
  *       would be destroyed, releasing the file, upon block exit.
  */
 class KSECRETS_STORE_EXPORT KSecretsStore {
-    class ItemPrivate;
-    class CollectionPrivate;
-
 public:
     using AttributesMap = std::map<std::string, std::string>;
 
@@ -122,7 +125,7 @@ public:
         friend class KSecretsStore;
 
     private:
-        std::shared_ptr<ItemPrivate> d;
+        KSecretsItemPrivatePtr d;
     };
     using ItemPtr = std::shared_ptr<Item>;
 
@@ -181,14 +184,16 @@ public:
 
         bool deleteItem(ItemPtr) noexcept;
 
+        Collection(KSecretsCollectionPrivatePtr dptr);
     protected:
         Collection();
         Collection(const Collection&) = default;
         Collection& operator=(const Collection&) = default;
         friend class KSecretsStore;
+        friend class KSecretsStorePrivate;
 
     private:
-        std::shared_ptr<CollectionPrivate> d;
+        KSecretsCollectionPrivatePtr d;
     };
     using CollectionPtr = std::shared_ptr<Collection>;
 
@@ -221,6 +226,8 @@ public:
         CannotOpenFile,
         CannotLockFile,
         CannotReadFile,
+        PrematureEndOfFileEncountered,
+        UnknownError,
         SystemError
     };
 
diff --git a/src/runtime/ksecrets_store/ksecrets_store_p.h \
b/src/runtime/ksecrets_store/ksecrets_store_p.h index c8f8aaa..e3461c1 100644
--- a/src/runtime/ksecrets_store/ksecrets_store_p.h
+++ b/src/runtime/ksecrets_store/ksecrets_store_p.h
@@ -52,6 +52,10 @@ class KSecretsItemPrivate : public TimeStamped {
 };
 
 class KSecretsCollectionPrivate : public TimeStamped {
+public:
+    bool createCollection(KSecretsFile &secretsFile, const std::string &collName);
+private:
+    SecretsCollectionPtr collection_data_;
 };
 
 class KSecretsStorePrivate {


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

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