From kde-commits Tue Aug 18 22:40:45 2015 From: Valentin Rusu Date: Tue, 18 Aug 2015 22:40:45 +0000 To: kde-commits Subject: [ksecrets] src/runtime/ksecrets_store: Introducting persistance logic base Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=143993765600998 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/ks= ecrets_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 =3D gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0); if (gcryerr !=3D 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* 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 available."); + 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_ITERSALTE= D_S2K, - GCRY_MD_SHA512, salt, 8, KSECRETS_ITERATIONS, 2 * keySize, key= s); + 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", - gcryerr, gcry_strsource(gcryerr), gcry_strerror(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 password."); + 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) +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_SESSION_KEYRIN= G); + 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)", @@ -111,17 +102,12 @@ int kss_store_keys( ks, key_name); = key_name =3D get_keyname_mac(); - ks =3D add_key( - "user", key_name, mac_key, keySize, KEY_SPEC_SESSION_KEYRING); + 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 keyring: errno=3D%d = (%m)", - errno); + 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); + 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, co= nst char* salt) // available and store the keys elsewhere char encryption_key[KSECRETS_KEYSIZE]; char mac_key[KSECRETS_KEYSIZE]; - auto res =3D kss_derive_keys( - salt, password.c_str(), encryption_key, mac_key, KSECRETS_KEYSIZE); + auto res =3D kss_derive_keys(salt, password.c_str(), encryption_key, m= ac_key, KSECRETS_KEYSIZE); if (res) return res; = @@ -142,8 +127,7 @@ int kss_set_credentials(const std::string& password, co= nst char* salt) int kss_keys_already_there() { key_serial_t key; - key =3D request_key( - "user", get_keyname_encrypting(), 0, KEY_SPEC_SESSION_KEYRING); + 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 " "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 =3D request_key("user", keyName, 0, KEY_SPEC_SESSION_KEYRING); if (-1 =3D=3D 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 =3D keyctl_read(key, buffer, bufferSize); if (bytes =3D=3D -1) { - syslog(KSS_LOG_ERR, "error reading key %s contents from the keyrin= g", - keyName); + syslog(KSS_LOG_ERR, "error reading key %s contents from the keyrin= g", keyName); return -1; } if ((size_t)bytes > bufferSize) { @@ -176,15 +157,9 @@ long kss_read_key(const char* keyName, char* buffer, s= ize_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_k= ey(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 voi= d* iv, size_t liv) { // FIXME perhaps all this initialization stuff could only be done once, // when password is setup - auto cryres - =3D gcry_cipher_open(hd, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CB= C, 0); + auto cryres =3D 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 =3D 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 =3D kss_read_encrypting_key( - encryptingKey, sizeof(encryptingKey) / sizeof(encryptingKey[0])); + auto keyres =3D kss_read_encrypting_key(encryptingKey, sizeof(encrypti= ngKey) / sizeof(encryptingKey[0])); if (!keyres) { - syslog( - KSS_LOG_ERR, "ksecrets: encrypting key not found in the keyrin= g"); + syslog(KSS_LOG_ERR, "ksecrets: encrypting key not found in the key= ring"); return keyres; } - cryres =3D gcry_cipher_setkey( - *hd, encryptingKey, sizeof(encryptingKey) / sizeof(encryptingKey[0= ])); + cryres =3D gcry_cipher_setkey(*hd, encryptingKey, sizeof(encryptingKey= ) / sizeof(encryptingKey[0])); if (cryres) { - syslog( - KSS_LOG_ERR, "ksecrets: gcry_cipher_setkey returned %d", cryre= s); + syslog(KSS_LOG_ERR, "ksecrets: gcry_cipher_setkey returned %d", cr= yres); 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, s= ize_t liv, const unsigned char* in, size_t lin) { gcry_cipher_hd_t hd; auto cryres =3D kss_cipher_setup(&hd, iv, liv); @@ -232,15 +199,13 @@ long kss_encrypt_buffer(unsigned char* out, size_t lo= ut, const void* iv, return cryres; // error already logged cryres =3D 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, s= ize_t liv, const unsigned char* in, size_t lin) { gcry_cipher_hd_t hd; auto cryres =3D kss_cipher_setup(&hd, iv, liv); @@ -248,13 +213,14 @@ long kss_decrypt_buffer(unsigned char* out, size_t lo= ut, const void* iv, return cryres; // error already logged cryres =3D 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 <=3D len_) { diff --git a/src/runtime/ksecrets_store/ksecrets_crypt.h b/src/runtime/ksec= rets_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&&) =3D default; + ~CryptBuffer(); = /** * @brief Allocate memory in multiples of cipher block len diff --git a/src/runtime/ksecrets_store/ksecrets_data.cpp b/src/runtime/kse= crets_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 +#include +#include = -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, s= ize_t liv, const unsigned char* in, size_t lin); +long kss_decrypt_buffer(unsigned char* out, size_t lout, const void* iv, s= ize_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 =3D nullptr; size_t liv =3D KSecretsFile::IV_SIZE; = +bool SecretsEntity::decrypt() +{ + if (isEmpty()) + return false; + if (unencrypted_.len_ > 0) + return true; // already decrpyted + if (encrypted_.len_ =3D=3D 0) + return false; // what to decrypt? + unencrypted_.allocate(encrypted_.len_); + auto dres =3D kss_decrypt_buffer(unencrypted_.data_, unencrypted_.len_= , iv, liv, encrypted_.data_, encrypted_.len_); + return dres =3D=3D 0; +} + +bool SecretsEntity::encrypt() +{ + // TODO + return false; +} + +bool SecretsEntity::write(KSecretsFile& file) +{ + bool res =3D false; + if (doBeforeWrite()) { + if (encrypt()) { + assert(state_ =3D=3D State::Encrypted); + if (file.write(encrypted_.len_)) { + if (encrypted_.len_ > 0) { + assert(encrypted_.data_ !=3D nullptr); + if (file.write(encrypted_.data_, encrypted_.len_)) { + res =3D true; + } + } + else { + res =3D true; + } + } + } + } + if (res) + return doAfterWrite(); + else + return res; +} + bool SecretsEntity::read(KSecretsFile& file) { if (iv =3D=3D nullptr) { iv =3D 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_ =3D=3D 0) - return false; // what to decrypt? - unencrypted_.allocate(encrypted_.len_); - auto dres =3D kss_decrypt_buffer(unencrypted_.data_, unencrypted_.len_= , iv, - liv, encrypted_.data_, encrypted_.len_); - return dres =3D=3D 0; } = -bool SecretsEntity::encrypt() +bool CollectionDirectory::hasEntry(const std::string& collName) const +{ + auto pos =3D std::find(entries_.begin(), entries_.end(), collName); + return pos !=3D entries_.end(); +} + +bool CollectionDirectory::doBeforeWrite() +{ + // TODO + return false; +} + +bool CollectionDirectory::doAfterRead() +{ + // TODO + return false; +} + +void SecretsCollection::setName(const std::string& name) { name_ =3D 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=3D220:ts=3D4 diff --git a/src/runtime/ksecrets_store/ksecrets_data.h b/src/runtime/ksecr= ets_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 #include +#include +#include = 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 so= me * plugin architecture, allowing users specify different encryption method= s. + * + * 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 generalizatio= n, + * as I cannot foresee the introduction of another file format (why should= I?) */ -struct SecretsEntity { +class SecretsEntity { +public: SecretsEntity(); - SecretsEntity(const SecretsEntity&) =3D delete; - SecretsEntity(SecretsEntity&&) =3D delete; virtual ~SecretsEntity(); = enum class State : std::uint8_t { @@ -48,6 +56,7 @@ struct SecretsEntity { }; = bool isEmpty() const noexcept { return state_ =3D=3D State::Empty; } + virtual bool hasNext() const noexcept { return true; } bool isDecrypted() const noexcept { return (static_cast(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 =3D 0; + + bool write(KSecretsFile&) noexcept; + virtual bool doBeforeWrite() noexcept =3D 0; + virtual bool doAfterWrite() noexcept { return true; } = State state_; CryptBuffer encrypted_; CryptBuffer unencrypted_; }; = -struct SecretsCollection : public SecretsEntity { +using SecretsEntityPtr =3D std::shared_ptr; + +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 =3D std::shared_ptr; + +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 entries_; }; = +using CollectionDirectoryPtr =3D std::shared_ptr; + +class SecretsItem : public SecretsEntity { +public: +private: + virtual bool doBeforeWrite() noexcept override; + virtual bool doAfterRead() noexcept override; +}; + +using SecretsItemPtr =3D std::shared_ptr; + +class SecretsEOF : public SecretsEntity { +private: + bool hasNext() const noexcept override { return false; } + virtual bool doBeforeWrite() noexcept override; + virtual bool doAfterRead() noexcept override; +}; + +using SecretsEOFPtr =3D std::shared_ptr; + #endif +// vim: tw=3D220:ts=3D4 diff --git a/src/runtime/ksecrets_store/ksecrets_file.cpp b/src/runtime/kse= crets_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 =3D ::write(file_, buf, len); + if (wres <0) { + return setFailState(errno); + } + if (static_cast(wres) < len) { + // no more space left on the file system + // FIXME we should prevent such an event by keeping versions of th= e secrets file + // TODO manage secrets file versions to prevent this kind of probl= em + 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.de= crypt(); } = +SecretsCollectionPtr KSecretsFile::createCollection(const std::string &col= lName) noexcept +{ + auto newColl =3D std::make_shared(); + newColl->setName(collName); + entities_.emplace_front(newColl); + return std::dynamic_pointer_cast(entities_.front()); +} + // vim: tw=3D220:ts=3D4 diff --git a/src/runtime/ksecrets_store/ksecrets_file.h b/src/runtime/ksecr= ets_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 -#include +#include = /** * @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 =3D std::pair; DirCollectionResult dirCollections() noexcept; + SecretsCollectionPtr createCollection(const std::string &collName) noe= xcept; = private: bool setFailState(int err, bool retval =3D false) noexcept @@ -70,7 +75,7 @@ private: bool readDirectory() noexcept; bool decryptEntity(SecretsEntity&) noexcept; = - using Entities =3D std::list; + using Entities =3D std::forward_list; = std::string filePath_; int file_; diff --git a/src/runtime/ksecrets_store/ksecrets_store.cpp b/src/runtime/ks= ecrets_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 +R mapSecretsFileFailure(KSecretsFile &file, R &&r) +{ + if (file.errnumber()) { + r.errno_ =3D file.errnumber(); + r.status_ =3D KSecretsStore::StoreStatus::SystemError; + } else { + if (file.eof()) { + r.status_ =3D KSecretsStore::StoreStatus::PrematureEndOfFileEn= countered; + } else { + r.status_ =3D KSecretsStore::StoreStatus::UnknownError; // rea= lly, we should get here very seldom + } + } + + return r; +} + KSecretsStore::CreateCollectionResult KSecretsStorePrivate::createCollecti= on(const std::string &collName) noexcept { KSecretsStore::CreateCollectionResult res; + auto cptr =3D std::make_shared(); + if (!cptr->createCollection(secretsFile_, collName)) { + return mapSecretsFileFailure(secretsFile_, res); + } + res.result_ =3D std::make_shared(cptr); + return res; +} = +bool KSecretsCollectionPrivate::createCollection(KSecretsFile &file, const= std::string &collName) +{ + bool res =3D false; + auto dir =3D file.dirCollections(); + if (dir.first) { + if (!dir.second->hasEntry(collName)) { + collection_data_ =3D file.createCollection(collName); + if (collection_data_ !=3D nullptr) { + res =3D true; + } + } + } return res; } = +KSecretsStore::Collection::Collection(KSecretsCollectionPrivatePtr dptr) := d(dptr) {} + KSecretsStore::ReadCollectionResult KSecretsStore::readCollection(const ch= ar*) const noexcept { // TODO diff --git a/src/runtime/ksecrets_store/ksecrets_store.h b/src/runtime/ksec= rets_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 = class KSecretsStorePrivate; +class KSecretsItemPrivate; +class KSecretsCollectionPrivate; + +using KSecretsItemPrivatePtr =3D std::shared_ptr; +using KSecretsCollectionPrivatePtr =3D std::shared_ptr; + = /** * 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 =3D std::map; = @@ -122,7 +125,7 @@ public: friend class KSecretsStore; = private: - std::shared_ptr d; + KSecretsItemPrivatePtr d; }; using ItemPtr =3D std::shared_ptr; = @@ -181,14 +184,16 @@ public: = bool deleteItem(ItemPtr) noexcept; = + Collection(KSecretsCollectionPrivatePtr dptr); protected: Collection(); Collection(const Collection&) =3D default; Collection& operator=3D(const Collection&) =3D default; friend class KSecretsStore; + friend class KSecretsStorePrivate; = private: - std::shared_ptr d; + KSecretsCollectionPrivatePtr d; }; using CollectionPtr =3D std::shared_ptr; = @@ -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/ks= ecrets_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 &co= llName); +private: + SecretsCollectionPtr collection_data_; }; = class KSecretsStorePrivate {