diff --git a/AppConfig.cpp b/AppConfig.cpp index 196a534..1700155 100644 --- a/AppConfig.cpp +++ b/AppConfig.cpp @@ -11,6 +11,7 @@ #include "global.h" #include #include +#include #include #include #include @@ -18,11 +19,15 @@ #include #include #include +#include using namespace std; +mutex gs_fileWriteMutex; + // Hard coded. File must be in WT_APP_ROOT #define JSON_CONFIG_FILE "k7config.json" + /* { "sCommonName" : { @@ -32,6 +37,7 @@ using namespace std; "canEditOwnerTrust" : true, "canEditUidValidity" : true, "canEditExpiryTime" : true, + "canCreateKeys" : true, "privKeyIds" : [ "fullKeyId1", "fullKeyId2" @@ -155,6 +161,56 @@ bool AppConfig::CanEditExpiryTime() const return cnObject.get("canEditExpiryTime"); } +bool AppConfig::CanCreateKeys() const +{ + const WString commonName = GetSubjectDnAttribute(WSslCertificate::DnAttributeName::CommonName); + if (!m_SubjectCNObject.contains(commonName.toUTF8())) + return false; + Json::Object cnObject = m_SubjectCNObject.get(commonName.toUTF8()); + if (!cnObject.contains("canCreateKeys")) + return false; + return cnObject.get("canCreateKeys"); +} + +bool AppConfig::UpdateSecretKeyOwnership(const WString& fpr, bool own) +{ + const WString commonName = GetSubjectDnAttribute(WSslCertificate::DnAttributeName::CommonName); + if (!m_SubjectCNObject.contains(commonName.toUTF8())) + return false; + Json::Object cnObject = m_SubjectCNObject.get(commonName.toUTF8()); + Json::Array aKeyId; + if (cnObject.contains("privKeyIds")) + { + aKeyId = cnObject.get("privKeyIds"); + cnObject.erase("privKeyIds"); + } + Json::Array::iterator it = std::find(aKeyId.begin(), aKeyId.end(), Json::Value(fpr)); + if (it == aKeyId.end()) + { + if (own) + aKeyId.push_back(Json::Value(fpr)); + else + return true; // We don't own it. + } + else + { + if (not own) + aKeyId.erase(it); + else + return true; // We already own it. + } + + // TODO : Do this **better**, without replacing sequentially up to root. + cnObject.insert(make_pair("privKeyIds", aKeyId)); + m_SubjectCNObject.erase(commonName.toUTF8()); + m_SubjectCNObject.insert(make_pair(commonName.toUTF8(), cnObject)); + m_RootObject.erase("sCommonName"); + m_RootObject.insert(make_pair("sCommonName", m_SubjectCNObject)); + + if (WriteTextFile(JSON_CONFIG_FILE, Json::serialize(m_RootObject))) + return LoadConfig(); + return false; +} vector AppConfig::PrivateKeyIds() const { @@ -186,3 +242,21 @@ const WString AppConfig::GetSubjectDnAttribute(const WSslCertificate::DnAttribut } return WString::Empty; } + +bool AppConfig::WriteTextFile(const WString& filePath, const WString& content) +{ + gs_fileWriteMutex.lock(); + ofstream osFile; + const WString f(WApplication::appRoot() + WString(filePath)); + osFile.open(f.toUTF8().c_str()); + if (!osFile.is_open()) + { + gs_fileWriteMutex.unlock(); + return false; + } + osFile << content.toUTF8(); + osFile.flush(); + osFile.close(); + gs_fileWriteMutex.unlock(); + return osFile.bad(); +} diff --git a/AppConfig.h b/AppConfig.h index 0e4715f..5ae1f68 100644 --- a/AppConfig.h +++ b/AppConfig.h @@ -60,6 +60,22 @@ public: * @return */ bool CanEditExpiryTime() const; + /** + * Allows to create keys. At the application level, it means creating a pair + * of secret and private keys. + * @return + */ + bool CanCreateKeys() const; + /** + * Disown the user of the secret key, or grants him ownership. It just adds + * or remove fpr from the private key array, without any further check. The + * application must call here when relevant. + * @param fpr + * @param own : if true, adds the fpr to the private key array if found. + * Else, removes the fpr if found. + * @return + */ + bool UpdateSecretKeyOwnership(const WString& fpr, bool own); /** * List of full private key identifiers. The user may delete these private keys. * Must be full keyid, short keyid or fingerprint. @@ -85,6 +101,8 @@ private: * @return */ const WString GetSubjectDnAttribute(const WSslCertificate::DnAttributeName& attrName) const; + + bool WriteTextFile(const WString& filePath, const WString& content); }; #endif /* APPCONFIG_H */