Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-06-02 02:22:40

0001 #include "CondCore/CondDB/interface/CredentialStore.h"
0002 #include "CondCore/CondDB/interface/Cipher.h"
0003 #include "CondCore/CondDB/interface/Exception.h"
0004 #include "CondCore/CondDB/interface/Auth.h"
0005 //
0006 #include "CoralBase/AttributeList.h"
0007 #include "CoralBase/Attribute.h"
0008 #include "CoralKernel/Context.h"
0009 #include "CoralCommon/URIParser.h"
0010 #include "RelationalAccess/AuthenticationCredentials.h"
0011 #include "RelationalAccess/IBulkOperation.h"
0012 #include "RelationalAccess/IConnection.h"
0013 #include "RelationalAccess/ISession.h"
0014 #include "RelationalAccess/IRelationalService.h"
0015 #include "RelationalAccess/IRelationalDomain.h"
0016 #include "RelationalAccess/ITransaction.h"
0017 #include "RelationalAccess/ISchema.h"
0018 #include "RelationalAccess/ITable.h"
0019 #include "RelationalAccess/TableDescription.h"
0020 #include "RelationalAccess/ITableDataEditor.h"
0021 #include "RelationalAccess/ITablePrivilegeManager.h"
0022 #include "RelationalAccess/IQuery.h"
0023 #include "RelationalAccess/ICursor.h"
0024 //
0025 #include "RelationalAccess/AuthenticationCredentials.h"
0026 //
0027 #include <filesystem>
0028 #include <fstream>
0029 #include <sstream>
0030 
0031 static const std::string serviceName = "CondAuthenticationService";
0032 
0033 coral_bridge::AuthenticationCredentialSet::AuthenticationCredentialSet() : m_data() {}
0034 
0035 coral_bridge::AuthenticationCredentialSet::~AuthenticationCredentialSet() { reset(); }
0036 
0037 void coral_bridge::AuthenticationCredentialSet::reset() {
0038   for (auto iData = m_data.begin(); iData != m_data.end(); ++iData)
0039     delete iData->second;
0040   m_data.clear();
0041 }
0042 
0043 void coral_bridge::AuthenticationCredentialSet::registerItem(const std::string& connectionString,
0044                                                              const std::string& itemName,
0045                                                              const std::string& itemValue) {
0046   registerItem(connectionString, cond::auth::COND_DEFAULT_ROLE, itemName, itemValue);
0047 }
0048 
0049 void coral_bridge::AuthenticationCredentialSet::registerItem(const std::string& connectionString,
0050                                                              const std::string& role,
0051                                                              const std::string& itemName,
0052                                                              const std::string& itemValue) {
0053   std::pair<std::string, std::string> connKey(connectionString, role);
0054   std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>::iterator iData =
0055       m_data.find(connKey);
0056   if (iData == m_data.end()) {
0057     iData = m_data.insert(std::make_pair(connKey, new coral::AuthenticationCredentials(serviceName))).first;
0058   }
0059   iData = m_data.insert(std::make_pair(connKey, new coral::AuthenticationCredentials(serviceName))).first;
0060   iData->second->registerItem(itemName, itemValue);
0061 }
0062 
0063 void coral_bridge::AuthenticationCredentialSet::registerCredentials(const std::string& connectionString,
0064                                                                     const std::string& userName,
0065                                                                     const std::string& password) {
0066   registerCredentials(connectionString, cond::auth::COND_DEFAULT_ROLE, userName, password);
0067 }
0068 
0069 void coral_bridge::AuthenticationCredentialSet::registerCredentials(const std::string& connectionString,
0070                                                                     const std::string& role,
0071                                                                     const std::string& userName,
0072                                                                     const std::string& password) {
0073   std::pair<std::string, std::string> connKey(connectionString, role);
0074   std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>::iterator iData =
0075       m_data.find(connKey);
0076   if (iData != m_data.end()) {
0077     delete iData->second;
0078     m_data.erase(connKey);
0079   }
0080   iData = m_data.insert(std::make_pair(connKey, new coral::AuthenticationCredentials(serviceName))).first;
0081   iData->second->registerItem(coral::IAuthenticationCredentials::userItem(), userName);
0082   iData->second->registerItem(coral::IAuthenticationCredentials::passwordItem(), password);
0083 }
0084 
0085 void coral_bridge::AuthenticationCredentialSet::import(const AuthenticationCredentialSet& data) {
0086   for (std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>::const_iterator iData =
0087            data.m_data.begin();
0088        iData != data.m_data.end();
0089        ++iData) {
0090     registerCredentials(iData->first.first,
0091                         iData->first.second,
0092                         iData->second->valueForItem(coral::IAuthenticationCredentials::userItem()),
0093                         iData->second->valueForItem(coral::IAuthenticationCredentials::passwordItem()));
0094   }
0095 }
0096 
0097 const coral::IAuthenticationCredentials* coral_bridge::AuthenticationCredentialSet::get(
0098     const std::string& connectionString) const {
0099   return get(connectionString, cond::auth::COND_DEFAULT_ROLE);
0100 }
0101 
0102 const coral::IAuthenticationCredentials* coral_bridge::AuthenticationCredentialSet::get(
0103     const std::string& connectionString, const std::string& role) const {
0104   const coral::IAuthenticationCredentials* ret = nullptr;
0105   std::pair<std::string, std::string> connKey(connectionString, role);
0106   std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>::const_iterator iData =
0107       m_data.find(connKey);
0108   if (iData != m_data.end()) {
0109     ret = iData->second;
0110   }
0111   return ret;
0112 }
0113 
0114 const std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>&
0115 coral_bridge::AuthenticationCredentialSet::data() const {
0116   return m_data;
0117 }
0118 
0119 static const std::string TABLE_PREFIX("DB_");
0120 static const std::string LEGACY_TABLE_PREFIX("COND_");
0121 static const std::string SEQUENCE_TABLE("CREDENTIAL_SEQUENCE");
0122 static const std::string SEQUENCE_NAME_COL("NAME");
0123 static const std::string SEQUENCE_VALUE_COL("VALUE");
0124 
0125 static const std::string AUTHENTICATION_TABLE("AUTHENTICATION");
0126 static const std::string PRINCIPAL_ID_COL("P_ID");
0127 static const std::string PRINCIPAL_NAME_COL("P_NAME");
0128 static const std::string VERIFICATION_COL("CRED0");
0129 static const std::string PRINCIPAL_KEY_COL("CRED1");
0130 static const std::string ADMIN_KEY_COL("CRED2");
0131 
0132 static const std::string AUTHORIZATION_TABLE("AUTHORIZATION");
0133 static const std::string AUTH_ID_COL("AUTH_ID");
0134 static const std::string P_ID_COL("P_ID");
0135 static const std::string ROLE_COL("C_ROLE");
0136 static const std::string SCHEMA_COL("C_SCHEMA");
0137 static const std::string AUTH_KEY_COL("CRED3");
0138 static const std::string C_ID_COL("C_ID");
0139 
0140 static const std::string CREDENTIAL_TABLE("CREDENTIAL");
0141 static const std::string CONNECTION_ID_COL("CONN_ID");
0142 static const std::string CONNECTION_LABEL_COL("CONN_LABEL");
0143 static const std::string USERNAME_COL("CRED4");
0144 static const std::string PASSWORD_COL("CRED5");
0145 static const std::string VERIFICATION_KEY_COL("CRED6");
0146 static const std::string CONNECTION_KEY_COL("CRED7");
0147 
0148 const std::string DEFAULT_DATA_SOURCE("Cond_Default_Authentication");
0149 
0150 std::string tname(const std::string& tableName, const std::string& schemaVersion) {
0151   std::string prefix(TABLE_PREFIX);
0152   if (schemaVersion.empty())
0153     prefix = LEGACY_TABLE_PREFIX;
0154   return prefix + tableName;
0155 }
0156 
0157 // implementation functions and helpers
0158 namespace cond {
0159 
0160   std::string schemaLabel(const std::string& serviceName, const std::string& userName) {
0161     std::string ret = userName;
0162     if (!serviceName.empty()) {
0163       ret += "@" + serviceName;
0164       ret = to_lower(ret);
0165     }
0166     return ret;
0167   }
0168 
0169   std::string schemaLabelForCredentialStore(const std::string& connectionString) {
0170     coral::URIParser parser;
0171     parser.setURI(connectionString);
0172     std::string serviceName = parser.hostName();
0173     std::string schemaName = parser.databaseOrSchemaName();
0174     return schemaLabel(serviceName, schemaName);
0175   }
0176 
0177   class CSScopedSession {
0178   public:
0179     CSScopedSession(CredentialStore& store) : m_store(store) {}
0180     ~CSScopedSession() { m_store.closeSession(false); }
0181     void startSuper(const std::string& connectionString, const std::string& userName, const std::string& password) {
0182       m_store.startSuperSession(connectionString, userName, password);
0183     }
0184     void start(bool readOnly = true) { m_store.startSession(readOnly); }
0185     void close() { m_store.closeSession(); }
0186 
0187   private:
0188     CredentialStore& m_store;
0189   };
0190 
0191   struct PrincipalData {
0192     int id;
0193     std::string verifKey;
0194     std::string principalKey;
0195     std::string adminKey;
0196     PrincipalData() : id(-1), verifKey(""), principalKey(""), adminKey("") {}
0197   };
0198   bool selectPrincipal(const std::string& schemaVersion,
0199                        coral::ISchema& schema,
0200                        const std::string& principal,
0201                        PrincipalData& destination) {
0202     std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(AUTHENTICATION_TABLE, schemaVersion)).newQuery());
0203     coral::AttributeList readBuff;
0204     readBuff.extend<int>(PRINCIPAL_ID_COL);
0205     readBuff.extend<std::string>(VERIFICATION_COL);
0206     readBuff.extend<std::string>(PRINCIPAL_KEY_COL);
0207     readBuff.extend<std::string>(ADMIN_KEY_COL);
0208     coral::AttributeList whereData;
0209     whereData.extend<std::string>(PRINCIPAL_NAME_COL);
0210     whereData[PRINCIPAL_NAME_COL].data<std::string>() = principal;
0211     std::string whereClause = PRINCIPAL_NAME_COL + " = :" + PRINCIPAL_NAME_COL;
0212     query->defineOutput(readBuff);
0213     query->addToOutputList(PRINCIPAL_ID_COL);
0214     query->addToOutputList(VERIFICATION_COL);
0215     query->addToOutputList(PRINCIPAL_KEY_COL);
0216     query->addToOutputList(ADMIN_KEY_COL);
0217     query->setCondition(whereClause, whereData);
0218     coral::ICursor& cursor = query->execute();
0219     bool found = false;
0220     if (cursor.next()) {
0221       found = true;
0222       const coral::AttributeList& row = cursor.currentRow();
0223       destination.id = row[PRINCIPAL_ID_COL].data<int>();
0224       destination.verifKey = row[VERIFICATION_COL].data<std::string>();
0225       destination.principalKey = row[PRINCIPAL_KEY_COL].data<std::string>();
0226       destination.adminKey = row[ADMIN_KEY_COL].data<std::string>();
0227     }
0228     return found;
0229   }
0230 
0231   struct CredentialData {
0232     int id;
0233     std::string userName;
0234     std::string password;
0235     std::string connectionKey;
0236     std::string verificationKey;
0237     CredentialData() : id(-1), userName(""), password(""), connectionKey("") {}
0238   };
0239 
0240   bool selectConnection(const std::string& schemaVersion,
0241                         coral::ISchema& schema,
0242                         const std::string& connectionLabel,
0243                         CredentialData& destination) {
0244     std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(CREDENTIAL_TABLE, schemaVersion)).newQuery());
0245     coral::AttributeList readBuff;
0246     readBuff.extend<int>(CONNECTION_ID_COL);
0247     readBuff.extend<std::string>(USERNAME_COL);
0248     readBuff.extend<std::string>(PASSWORD_COL);
0249     readBuff.extend<std::string>(VERIFICATION_KEY_COL);
0250     readBuff.extend<std::string>(CONNECTION_KEY_COL);
0251     coral::AttributeList whereData;
0252     whereData.extend<std::string>(CONNECTION_LABEL_COL);
0253     whereData[CONNECTION_LABEL_COL].data<std::string>() = connectionLabel;
0254     std::string whereClause = CONNECTION_LABEL_COL + " = :" + CONNECTION_LABEL_COL;
0255     query->defineOutput(readBuff);
0256     query->addToOutputList(CONNECTION_ID_COL);
0257     query->addToOutputList(USERNAME_COL);
0258     query->addToOutputList(PASSWORD_COL);
0259     query->addToOutputList(VERIFICATION_KEY_COL);
0260     query->addToOutputList(CONNECTION_KEY_COL);
0261     query->setCondition(whereClause, whereData);
0262     coral::ICursor& cursor = query->execute();
0263     bool found = false;
0264     if (cursor.next()) {
0265       const coral::AttributeList& row = cursor.currentRow();
0266       destination.id = row[CONNECTION_ID_COL].data<int>();
0267       destination.userName = row[USERNAME_COL].data<std::string>();
0268       destination.password = row[PASSWORD_COL].data<std::string>();
0269       destination.verificationKey = row[VERIFICATION_KEY_COL].data<std::string>();
0270       destination.connectionKey = row[CONNECTION_KEY_COL].data<std::string>();
0271       found = true;
0272     }
0273     return found;
0274   }
0275 
0276   struct AuthorizationData {
0277     int id;
0278     int connectionId;
0279     std::string key;
0280     AuthorizationData() : id(-1), connectionId(-1), key("") {}
0281   };
0282 
0283   bool selectAuthorization(const std::string& schemaVersion,
0284                            coral::ISchema& schema,
0285                            int principalId,
0286                            const std::string& role,
0287                            const std::string& connectionString,
0288                            AuthorizationData& destination) {
0289     std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(AUTHORIZATION_TABLE, schemaVersion)).newQuery());
0290     coral::AttributeList readBuff;
0291     readBuff.extend<int>(AUTH_ID_COL);
0292     readBuff.extend<int>(C_ID_COL);
0293     readBuff.extend<std::string>(AUTH_KEY_COL);
0294     coral::AttributeList whereData;
0295     whereData.extend<int>(P_ID_COL);
0296     whereData.extend<std::string>(ROLE_COL);
0297     whereData.extend<std::string>(SCHEMA_COL);
0298     whereData[P_ID_COL].data<int>() = principalId;
0299     whereData[ROLE_COL].data<std::string>() = role;
0300     whereData[SCHEMA_COL].data<std::string>() = to_lower(connectionString);
0301     std::stringstream whereClause;
0302     whereClause << P_ID_COL << " = :" << P_ID_COL;
0303     whereClause << " AND " << ROLE_COL << " = :" << ROLE_COL;
0304     whereClause << " AND " << SCHEMA_COL << " = :" << SCHEMA_COL;
0305     query->defineOutput(readBuff);
0306     query->addToOutputList(AUTH_ID_COL);
0307     query->addToOutputList(C_ID_COL);
0308     query->addToOutputList(AUTH_KEY_COL);
0309     query->setCondition(whereClause.str(), whereData);
0310     coral::ICursor& cursor = query->execute();
0311     bool found = false;
0312     if (cursor.next()) {
0313       const coral::AttributeList& row = cursor.currentRow();
0314       destination.id = row[AUTH_ID_COL].data<int>();
0315       destination.connectionId = row[C_ID_COL].data<int>();
0316       destination.key = row[AUTH_KEY_COL].data<std::string>();
0317       found = true;
0318     }
0319     return found;
0320   }
0321 
0322   size_t getAuthorizationEntries(const std::string& schemaVersion,
0323                                  coral::ISchema& schema,
0324                                  int principalId,
0325                                  const std::string& role,
0326                                  const std::string& connectionString) {
0327     std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(AUTHORIZATION_TABLE, schemaVersion)).newQuery());
0328     coral::AttributeList readBuff;
0329     readBuff.extend<int>(AUTH_ID_COL);
0330     coral::AttributeList whereData;
0331     whereData.extend<std::string>(SCHEMA_COL);
0332     std::stringstream whereClause;
0333     whereClause << SCHEMA_COL << " = :" << SCHEMA_COL;
0334     if (principalId >= 0) {
0335       whereData.extend<int>(P_ID_COL);
0336       whereClause << "AND" << P_ID_COL << " = :" << P_ID_COL;
0337     }
0338     if (!role.empty()) {
0339       whereData.extend<std::string>(ROLE_COL);
0340       whereClause << " AND " << ROLE_COL << " = :" << ROLE_COL;
0341     }
0342     whereData[SCHEMA_COL].data<std::string>() = connectionString;
0343     if (principalId >= 0)
0344       whereData[P_ID_COL].data<int>() = principalId;
0345     if (!role.empty())
0346       whereData[ROLE_COL].data<std::string>() = role;
0347     query->defineOutput(readBuff);
0348     query->addToOutputList(AUTH_ID_COL);
0349     query->setCondition(whereClause.str(), whereData);
0350     coral::ICursor& cursor = query->execute();
0351     size_t n_entries = 0;
0352     while (cursor.next()) {
0353       n_entries += 1;
0354     }
0355     return n_entries;
0356   }
0357 
0358   bool getNextSequenceValue(const std::string& schemaVersion,
0359                             coral::ISchema& schema,
0360                             const std::string& sequenceName,
0361                             int& value) {
0362     bool ret = false;
0363     std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(SEQUENCE_TABLE, schemaVersion)).newQuery());
0364     query->limitReturnedRows(1, 0);
0365     query->addToOutputList(SEQUENCE_VALUE_COL);
0366     query->defineOutputType(SEQUENCE_VALUE_COL, coral::AttributeSpecification::typeNameForType<int>());
0367     query->setForUpdate();
0368     std::string whereClause(SEQUENCE_NAME_COL + " = :" + SEQUENCE_NAME_COL);
0369     coral::AttributeList rowData;
0370     rowData.extend<std::string>(SEQUENCE_NAME_COL);
0371     rowData.begin()->data<std::string>() = sequenceName;
0372     query->setCondition(whereClause, rowData);
0373     coral::ICursor& cursor = query->execute();
0374     if (cursor.next()) {
0375       value = cursor.currentRow().begin()->data<int>() + 1;
0376       ret = true;
0377     } else {
0378       return false;
0379     }
0380     // update...
0381     coral::AttributeList updateData;
0382     updateData.extend<std::string>(SEQUENCE_NAME_COL);
0383     updateData.extend<int>(SEQUENCE_VALUE_COL);
0384     std::string setClause(SEQUENCE_VALUE_COL + " = :" + SEQUENCE_VALUE_COL);
0385     std::string whClause(SEQUENCE_NAME_COL + " = :" + SEQUENCE_NAME_COL);
0386     coral::AttributeList::iterator iAttribute = updateData.begin();
0387     iAttribute->data<std::string>() = sequenceName;
0388     ++iAttribute;
0389     iAttribute->data<int>() = value;
0390     schema.tableHandle(tname(SEQUENCE_TABLE, schemaVersion)).dataEditor().updateRows(setClause, whClause, updateData);
0391     return ret;
0392   }
0393 
0394   std::pair<int, std::string> updatePrincipalData(const std::string& schemaVersion,
0395                                                   coral::ISchema& schema,
0396                                                   const std::string& authenticationKey,
0397                                                   const std::string& principalName,
0398                                                   const std::string& adminKey,
0399                                                   bool init /**= false **/,
0400                                                   std::stringstream& log) {
0401     PrincipalData princData;
0402     bool found = selectPrincipal(schemaVersion, schema, principalName, princData);
0403 
0404     auth::Cipher cipher0(authenticationKey);
0405     auth::Cipher cipher1(adminKey);
0406 
0407     std::string verifStr = cipher0.b64encrypt(principalName);
0408     std::string principalKey("");
0409     int principalId = princData.id;
0410 
0411     std::string authentication_table_name = tname(AUTHENTICATION_TABLE, schemaVersion);
0412 
0413     coral::ITableDataEditor& editor = schema.tableHandle(authentication_table_name).dataEditor();
0414     if (found) {
0415       log << "Updating existing principal " << principalName << " (id: " << principalId << " )" << std::endl;
0416       principalKey = cipher1.b64decrypt(princData.adminKey);
0417       coral::AttributeList updateData;
0418       updateData.extend<int>(PRINCIPAL_ID_COL);
0419       updateData.extend<std::string>(VERIFICATION_COL);
0420       updateData.extend<std::string>(PRINCIPAL_KEY_COL);
0421       updateData.extend<std::string>(ADMIN_KEY_COL);
0422       updateData[PRINCIPAL_ID_COL].data<int>() = principalId;
0423       updateData[VERIFICATION_COL].data<std::string>() = verifStr;
0424       updateData[PRINCIPAL_KEY_COL].data<std::string>() = cipher0.b64encrypt(principalKey);
0425       updateData[ADMIN_KEY_COL].data<std::string>() = cipher1.b64encrypt(principalKey);
0426       std::stringstream setClause;
0427       setClause << VERIFICATION_COL << " = :" << VERIFICATION_COL << ", ";
0428       setClause << PRINCIPAL_KEY_COL << " = :" << PRINCIPAL_KEY_COL << ", ";
0429       setClause << ADMIN_KEY_COL << " = :" << ADMIN_KEY_COL;
0430       std::string whereClause = PRINCIPAL_ID_COL + " = :" + PRINCIPAL_ID_COL;
0431       editor.updateRows(setClause.str(), whereClause, updateData);
0432     } else {
0433       if (init) {
0434         principalKey = adminKey;
0435       } else {
0436         auth::KeyGenerator gen;
0437         principalKey = gen.make(auth::COND_DB_KEY_SIZE);
0438       }
0439       coral::ITableDataEditor& editor0 = schema.tableHandle(authentication_table_name).dataEditor();
0440 
0441       if (!getNextSequenceValue(schemaVersion, schema, authentication_table_name, principalId))
0442         throwException("Can't find " + authentication_table_name + " sequence.", "CredentialStore::updatePrincipal");
0443       log << "Creating new principal " << principalName << " (id: " << principalId << " )" << std::endl;
0444       coral::AttributeList authData;
0445       editor0.rowBuffer(authData);
0446       authData[PRINCIPAL_ID_COL].data<int>() = principalId;
0447       authData[PRINCIPAL_NAME_COL].data<std::string>() = principalName;
0448       authData[VERIFICATION_COL].data<std::string>() = verifStr;
0449       authData[PRINCIPAL_KEY_COL].data<std::string>() = cipher0.b64encrypt(principalKey);
0450       authData[ADMIN_KEY_COL].data<std::string>() = cipher1.b64encrypt(principalKey);
0451       editor0.insertRow(authData);
0452     }
0453 
0454     return std::make_pair(principalId, principalKey);
0455   }
0456 
0457   bool setPermissionData(const std::string& schemaVersion,
0458                          coral::ISchema& schema,
0459                          int principalId,
0460                          const std::string& principalKey,
0461                          const std::string& role,
0462                          const std::string& connectionString,
0463                          int connectionId,
0464                          const std::string& connectionKey,
0465                          std::stringstream& log) {
0466     if (cond::auth::ROLES.find(role) == cond::auth::ROLES.end()) {
0467       throwException(std::string("Role ") + role + " does not exists.", "CredentialStore::setPermission");
0468     }
0469     auth::Cipher cipher(principalKey);
0470     std::string encryptedConnectionKey = cipher.b64encrypt(connectionKey);
0471     AuthorizationData authData;
0472     bool found = selectAuthorization(schemaVersion, schema, principalId, role, connectionString, authData);
0473 
0474     std::string authorization_table_name = tname(AUTHORIZATION_TABLE, schemaVersion);
0475     coral::ITableDataEditor& editor = schema.tableHandle(authorization_table_name).dataEditor();
0476     if (found) {
0477       log << "Updating permission for principal id " << principalId << " to access resource " << connectionString
0478           << " with role " << role << std::endl;
0479       coral::AttributeList updateData;
0480       updateData.extend<int>(AUTH_ID_COL);
0481       updateData.extend<int>(C_ID_COL);
0482       updateData.extend<std::string>(AUTH_KEY_COL);
0483       updateData[AUTH_ID_COL].data<int>() = authData.id;
0484       updateData[C_ID_COL].data<int>() = connectionId;
0485       updateData[AUTH_KEY_COL].data<std::string>() = encryptedConnectionKey;
0486       std::string setCl = C_ID_COL + " = :" + C_ID_COL + ", " + AUTH_KEY_COL + " = :" + AUTH_KEY_COL;
0487       std::string whereCl = AUTH_ID_COL + " = :" + AUTH_ID_COL;
0488       editor.updateRows(setCl, whereCl, updateData);
0489     } else {
0490       int next = -1;
0491       if (!getNextSequenceValue(schemaVersion, schema, authorization_table_name, next))
0492         throwException("Can't find " + authorization_table_name + " sequence.", "CredentialStore::setPermission");
0493       log << "Setting permission for principal id " << principalId << " to access resource " << connectionString
0494           << " with role " << role << std::endl;
0495       coral::AttributeList insertData;
0496       insertData.extend<int>(AUTH_ID_COL);
0497       insertData.extend<int>(P_ID_COL);
0498       insertData.extend<std::string>(ROLE_COL);
0499       insertData.extend<std::string>(SCHEMA_COL);
0500       insertData.extend<std::string>(AUTH_KEY_COL);
0501       insertData.extend<int>(C_ID_COL);
0502       insertData[AUTH_ID_COL].data<int>() = next;
0503       insertData[P_ID_COL].data<int>() = principalId;
0504       insertData[ROLE_COL].data<std::string>() = role;
0505       insertData[SCHEMA_COL].data<std::string>() = to_lower(connectionString);
0506       insertData[AUTH_KEY_COL].data<std::string>() = encryptedConnectionKey;
0507       insertData[C_ID_COL].data<int>() = connectionId;
0508       editor.insertRow(insertData);
0509     }
0510     return true;
0511   }
0512 
0513   std::pair<int, std::string> updateConnectionData(const std::string& schemaVersion,
0514                                                    coral::ISchema& schema,
0515                                                    const std::string& adminKey,
0516                                                    const std::string& connectionLabel,
0517                                                    const std::string& userName,
0518                                                    const std::string& password,
0519                                                    bool forceUpdate,
0520                                                    std::stringstream& log) {
0521     CredentialData credsData;
0522     bool found = selectConnection(schemaVersion, schema, connectionLabel, credsData);
0523     int connId = credsData.id;
0524 
0525     auth::Cipher adminCipher(adminKey);
0526     std::string connectionKey("");
0527     std::string credential_table_name = tname(CREDENTIAL_TABLE, schemaVersion);
0528     coral::ITableDataEditor& editor = schema.tableHandle(credential_table_name).dataEditor();
0529     if (found) {
0530       connectionKey = adminCipher.b64decrypt(credsData.connectionKey);
0531       auth::Cipher cipher(connectionKey);
0532       std::string verificationKey = cipher.b64decrypt(credsData.verificationKey);
0533       if (verificationKey != connectionLabel) {
0534         throwException("Decoding of connection key failed.", "CredentialStore::updateConnection");
0535       }
0536       if (forceUpdate) {
0537         std::string encryptedUserName = cipher.b64encrypt(userName);
0538         std::string encryptedPassword = cipher.b64encrypt(password);
0539         log << "Forcing update of connection " << connectionLabel << std::endl;
0540         coral::AttributeList updateData;
0541         updateData.extend<int>(CONNECTION_ID_COL);
0542         updateData.extend<std::string>(USERNAME_COL);
0543         updateData.extend<std::string>(PASSWORD_COL);
0544         updateData[CONNECTION_ID_COL].data<int>() = connId;
0545         updateData[USERNAME_COL].data<std::string>() = encryptedUserName;
0546         updateData[PASSWORD_COL].data<std::string>() = encryptedPassword;
0547         std::stringstream setCl;
0548         setCl << USERNAME_COL << " = :" << USERNAME_COL;
0549         setCl << ", " << PASSWORD_COL << " = :" << PASSWORD_COL;
0550         std::string whereCl = CONNECTION_ID_COL + " = :" + CONNECTION_ID_COL;
0551         editor.updateRows(setCl.str(), whereCl, updateData);
0552       }
0553     } else {
0554       auth::KeyGenerator gen;
0555       connectionKey = gen.make(auth::COND_DB_KEY_SIZE);
0556       auth::Cipher cipher(connectionKey);
0557       std::string encryptedUserName = cipher.b64encrypt(userName);
0558       std::string encryptedPassword = cipher.b64encrypt(password);
0559       std::string encryptedLabel = cipher.b64encrypt(connectionLabel);
0560 
0561       if (!getNextSequenceValue(schemaVersion, schema, credential_table_name, connId))
0562         throwException("Can't find " + credential_table_name + " sequence.", "CredentialStore::updateConnection");
0563       log << "Creating new connection " << connectionLabel << std::endl;
0564       coral::AttributeList insertData;
0565       insertData.extend<int>(CONNECTION_ID_COL);
0566       insertData.extend<std::string>(CONNECTION_LABEL_COL);
0567       insertData.extend<std::string>(USERNAME_COL);
0568       insertData.extend<std::string>(PASSWORD_COL);
0569       insertData.extend<std::string>(VERIFICATION_KEY_COL);
0570       insertData.extend<std::string>(CONNECTION_KEY_COL);
0571       insertData[CONNECTION_ID_COL].data<int>() = connId;
0572       insertData[CONNECTION_LABEL_COL].data<std::string>() = connectionLabel;
0573       insertData[USERNAME_COL].data<std::string>() = encryptedUserName;
0574       insertData[PASSWORD_COL].data<std::string>() = encryptedPassword;
0575       insertData[VERIFICATION_KEY_COL].data<std::string>() = encryptedLabel;
0576       insertData[CONNECTION_KEY_COL].data<std::string>() = adminCipher.b64encrypt(connectionKey);
0577       ;
0578       editor.insertRow(insertData);
0579     }
0580     return std::make_pair(connId, connectionKey);
0581   }
0582 
0583 }  // namespace cond
0584 
0585 // class private methods
0586 void cond::CredentialStore::closeSession(bool commit) {
0587   if (m_session.get()) {
0588     if (m_session->transaction().isActive()) {
0589       if (commit) {
0590         m_session->transaction().commit();
0591       } else {
0592         m_session->transaction().rollback();
0593       }
0594     }
0595     m_session->endUserSession();
0596   }
0597   m_session.reset();
0598   if (m_connection.get()) {
0599     m_connection->disconnect();
0600   }
0601   m_connection.reset();
0602   m_log << "Session has been closed." << std::endl;
0603 }
0604 
0605 std::pair<std::string, std::string> cond::CredentialStore::openConnection(const std::string& connectionString) {
0606   coral::IHandle<coral::IRelationalService> relationalService =
0607       coral::Context::instance().query<coral::IRelationalService>();
0608   if (!relationalService.isValid()) {
0609     coral::Context::instance().loadComponent("CORAL/Services/RelationalService");
0610     relationalService = coral::Context::instance().query<coral::IRelationalService>();
0611   }
0612   coral::IRelationalDomain& domain = relationalService->domainForConnection(connectionString);
0613   std::pair<std::string, std::string> connTokens = domain.decodeUserConnectionString(connectionString);
0614   m_connection.reset(domain.newConnection(connTokens.first));
0615   m_connection->connect();
0616   return connTokens;
0617 }
0618 
0619 void cond::CredentialStore::openSession(const std::string& schemaName,
0620                                         const std::string& userName,
0621                                         const std::string& password,
0622                                         bool readMode) {
0623   coral::AccessMode accessMode = coral::ReadOnly;
0624   if (!readMode)
0625     accessMode = coral::Update;
0626   m_session.reset(m_connection->newSession(schemaName, accessMode));
0627   m_session->startUserSession(userName, password);
0628   // open read-only transaction
0629   m_session->transaction().start(readMode);
0630   m_log << "New session opened." << std::endl;
0631 }
0632 
0633 void cond::CredentialStore::startSuperSession(const std::string& connectionString,
0634                                               const std::string& userName,
0635                                               const std::string& password) {
0636   std::pair<std::string, std::string> connTokens = openConnection(connectionString);
0637   openSession(connTokens.second, userName, password, false);
0638 }
0639 
0640 // open session on the storage
0641 void cond::CredentialStore::startSession(bool readMode) {
0642   if (!m_serviceData) {
0643     throwException("The credential store has not been initialized.", "cond::CredentialStore::openConnection");
0644   }
0645   const std::string& storeConnectionString = m_serviceData->connectionString;
0646 
0647   std::pair<std::string, std::string> connTokens = openConnection(storeConnectionString);
0648 
0649   const std::string& userName = m_serviceData->userName;
0650   const std::string& password = m_serviceData->password;
0651 
0652   openSession(connTokens.second, userName, password, true);
0653 
0654   coral::ISchema& schema = m_session->nominalSchema();
0655   const std::string& schemaVersion = m_key.version();
0656   if (!schema.existsTable(tname(AUTHENTICATION_TABLE, schemaVersion)) ||
0657       !schema.existsTable(tname(AUTHORIZATION_TABLE, schemaVersion)) ||
0658       !schema.existsTable(tname(CREDENTIAL_TABLE, schemaVersion))) {
0659     throwException("Credential database does not exists in \"" + storeConnectionString + "\"",
0660                    "CredentialStore::startSession");
0661   }
0662 
0663   const std::string& principalName = m_key.principalName();
0664   // now authenticate...
0665   PrincipalData princData;
0666   if (!selectPrincipal(schemaVersion, m_session->nominalSchema(), principalName, princData)) {
0667     throwException("Invalid credentials provided.(0)", "CredentialStore::startSession");
0668   }
0669   auth::Cipher cipher0(m_key.principalKey());
0670   std::string verifStr = cipher0.b64decrypt(princData.verifKey);
0671   if (verifStr != principalName) {
0672     throwException("Invalid credentials provided (1)", "CredentialStore::startSession");
0673   }
0674   // ok, authenticated!
0675   m_principalId = princData.id;
0676   m_principalKey = cipher0.b64decrypt(princData.principalKey);
0677   m_authenticatedPrincipal = m_key.principalName();
0678 
0679   if (!readMode) {
0680     auth::Cipher cipher0(m_principalKey);
0681     std::string adminKey = cipher0.b64decrypt(princData.adminKey);
0682     if (adminKey != m_principalKey) {
0683       // not admin user!
0684       throwException("Provided credentials does not allow admin operation.", "CredentialStore::openSession");
0685     }
0686 
0687     // first find the credentials for WRITING in the security tables
0688     std::unique_ptr<coral::IQuery> query(schema.newQuery());
0689     query->addToTableList(tname(AUTHORIZATION_TABLE, schemaVersion), "AUTHO");
0690     query->addToTableList(tname(CREDENTIAL_TABLE, schemaVersion), "CREDS");
0691     coral::AttributeList readBuff;
0692     readBuff.extend<std::string>("CREDS." + CONNECTION_LABEL_COL);
0693     readBuff.extend<std::string>("CREDS." + CONNECTION_KEY_COL);
0694     readBuff.extend<std::string>("CREDS." + USERNAME_COL);
0695     readBuff.extend<std::string>("CREDS." + PASSWORD_COL);
0696     readBuff.extend<std::string>("CREDS." + VERIFICATION_KEY_COL);
0697     coral::AttributeList whereData;
0698     whereData.extend<int>(P_ID_COL);
0699     whereData.extend<std::string>(ROLE_COL);
0700     whereData.extend<std::string>(SCHEMA_COL);
0701     whereData[P_ID_COL].data<int>() = m_principalId;
0702     whereData[ROLE_COL].data<std::string>() = auth::COND_ADMIN_ROLE;
0703     whereData[SCHEMA_COL].data<std::string>() = storeConnectionString;
0704     std::stringstream whereClause;
0705     whereClause << "AUTHO." << C_ID_COL << " = CREDS." << CONNECTION_ID_COL;
0706     whereClause << " AND AUTHO." << P_ID_COL << " = :" << P_ID_COL;
0707     whereClause << " AND AUTHO." << ROLE_COL << " = :" << ROLE_COL;
0708     whereClause << " AND AUTHO." << SCHEMA_COL << " = :" << SCHEMA_COL;
0709     query->defineOutput(readBuff);
0710     query->addToOutputList("CREDS." + CONNECTION_LABEL_COL);
0711     query->addToOutputList("CREDS." + CONNECTION_KEY_COL);
0712     query->addToOutputList("CREDS." + USERNAME_COL);
0713     query->addToOutputList("CREDS." + PASSWORD_COL);
0714     query->addToOutputList("CREDS." + VERIFICATION_KEY_COL);
0715     query->setCondition(whereClause.str(), whereData);
0716     coral::ICursor& cursor = query->execute();
0717     bool found = false;
0718     std::string writeUserName("");
0719     std::string writePassword("");
0720     if (cursor.next()) {
0721       const coral::AttributeList& row = cursor.currentRow();
0722       const std::string& connLabel = row["CREDS." + CONNECTION_LABEL_COL].data<std::string>();
0723       const std::string& encryptedConnectionKey = row["CREDS." + CONNECTION_KEY_COL].data<std::string>();
0724       std::string connectionKey = cipher0.b64decrypt(encryptedConnectionKey);
0725       auth::Cipher cipher1(connectionKey);
0726       const std::string& encryptedUserName = row["CREDS." + USERNAME_COL].data<std::string>();
0727       const std::string& encryptedPassword = row["CREDS." + PASSWORD_COL].data<std::string>();
0728       std::string verificationKey = cipher1.b64decrypt(row["CREDS." + VERIFICATION_KEY_COL].data<std::string>());
0729       if (verificationKey != connLabel) {
0730         throwException("Could not decrypt credentials.Provided key is invalid.", "CredentialStore::startSession");
0731       }
0732       writeUserName = cipher1.b64decrypt(encryptedUserName);
0733       writePassword = cipher1.b64decrypt(encryptedPassword);
0734       found = true;
0735     }
0736     if (!found) {
0737       throwException("Provided credentials are invalid for write access.", "CredentialStore::openSession");
0738     }
0739     m_session->transaction().commit();
0740     m_session->endUserSession();
0741     openSession(connTokens.second, writeUserName, writePassword, false);
0742   }
0743 }
0744 
0745 // class public methods
0746 cond::CredentialStore::CredentialStore()
0747     : m_connection(),
0748       m_session(),
0749       m_authenticatedPrincipal(""),
0750       m_principalId(-1),
0751       m_principalKey(""),
0752       m_serviceName(""),
0753       m_serviceData(nullptr),
0754       m_key(),
0755       m_log() {}
0756 
0757 cond::CredentialStore::~CredentialStore() {}
0758 
0759 std::string cond::CredentialStore::setUpForService(const std::string& serviceName, const std::string& authPath) {
0760   if (serviceName.empty()) {
0761     throwException("Service name has not been provided.", "cond::CredentialStore::setUpConnection");
0762   }
0763   m_serviceName.clear();
0764   m_serviceData = nullptr;
0765 
0766   if (authPath.empty()) {
0767     throwException("The authentication Path has not been provided.", "cond::CredentialStore::setUpForService");
0768   }
0769   std::filesystem::path fullPath(authPath);
0770   if (!std::filesystem::exists(authPath) || !std::filesystem::is_directory(authPath)) {
0771     throwException("Authentication Path is invalid.", "cond::CredentialStore::setUpForService");
0772   }
0773   std::filesystem::path file(auth::DecodingKey::FILE_PATH);
0774   fullPath /= file;
0775 
0776   m_key.init(fullPath.string(), auth::COND_KEY);
0777 
0778   std::map<std::string, auth::ServiceCredentials>::const_iterator iK = m_key.services().find(serviceName);
0779   if (iK == m_key.services().end()) {
0780     std::string msg("");
0781     msg += "Service \"" + serviceName + "\" can't be open with the current key.";
0782     throwException(msg, "cond::CredentialStore::setUpConnection");
0783   }
0784   m_serviceName = serviceName;
0785   m_serviceData = &iK->second;
0786   m_log << "Opening Credential Store for service " << m_serviceName << " on " << m_serviceData->connectionString
0787         << std::endl;
0788   return m_serviceData->connectionString;
0789 }
0790 
0791 std::string cond::CredentialStore::setUpForConnectionString(const std::string& connectionString,
0792                                                             const std::string& authPath) {
0793   coral::IHandle<coral::IRelationalService> relationalService =
0794       coral::Context::instance().query<coral::IRelationalService>();
0795   if (!relationalService.isValid()) {
0796     coral::Context::instance().loadComponent("CORAL/Services/RelationalService");
0797     relationalService = coral::Context::instance().query<coral::IRelationalService>();
0798   }
0799   coral::IRelationalDomain& domain = relationalService->domainForConnection(connectionString);
0800   std::pair<std::string, std::string> connTokens = domain.decodeUserConnectionString(connectionString);
0801   std::string& serviceName = connTokens.first;
0802   return setUpForService(serviceName, authPath);
0803 }
0804 
0805 void addSequence(const std::string& schemaVersion, coral::ISchema& schema, const std::string& name) {
0806   // Create the entry in the table
0807   coral::AttributeList insertData;
0808   insertData.extend<std::string>(SEQUENCE_NAME_COL);
0809   insertData.extend<int>(SEQUENCE_VALUE_COL);
0810   coral::AttributeList::iterator iAttribute = insertData.begin();
0811   iAttribute->data<std::string>() = name;
0812   ++iAttribute;
0813   iAttribute->data<int>() = -1;
0814   schema.tableHandle(tname(SEQUENCE_TABLE, schemaVersion)).dataEditor().insertRow(insertData);
0815 }
0816 
0817 bool cond::CredentialStore::createSchema(const std::string& connectionString,
0818                                          const std::string& userName,
0819                                          const std::string& password) {
0820   CSScopedSession session(*this);
0821   session.startSuper(connectionString, userName, password);
0822 
0823   coral::ISchema& schema = m_session->nominalSchema();
0824   std::string authentication_table_name = tname(AUTHENTICATION_TABLE, m_key.version());
0825   if (schema.existsTable(authentication_table_name)) {
0826     throwException("Credential database, already exists.", "CredentialStore::create");
0827   }
0828 
0829   m_log << "Creating sequence table." << std::endl;
0830   std::string sequence_table_name = tname(SEQUENCE_TABLE, m_key.version());
0831   coral::TableDescription dseq;
0832   dseq.setName(sequence_table_name);
0833   dseq.insertColumn(SEQUENCE_NAME_COL, coral::AttributeSpecification::typeNameForType<std::string>());
0834   dseq.setNotNullConstraint(SEQUENCE_NAME_COL);
0835   dseq.insertColumn(SEQUENCE_VALUE_COL, coral::AttributeSpecification::typeNameForType<int>());
0836   dseq.setNotNullConstraint(SEQUENCE_VALUE_COL);
0837   dseq.setPrimaryKey(std::vector<std::string>(1, SEQUENCE_NAME_COL));
0838   schema.createTable(dseq);
0839 
0840   int columnSize = 2000;
0841 
0842   m_log << "Creating authentication table." << std::endl;
0843   // authentication table
0844   addSequence(m_key.version(), schema, authentication_table_name);
0845   coral::TableDescription descr0;
0846   descr0.setName(authentication_table_name);
0847   descr0.insertColumn(PRINCIPAL_ID_COL, coral::AttributeSpecification::typeNameForType<int>());
0848   descr0.insertColumn(
0849       PRINCIPAL_NAME_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0850   descr0.insertColumn(
0851       VERIFICATION_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0852   descr0.insertColumn(
0853       PRINCIPAL_KEY_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0854   descr0.insertColumn(ADMIN_KEY_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0855   descr0.setNotNullConstraint(PRINCIPAL_ID_COL);
0856   descr0.setNotNullConstraint(PRINCIPAL_NAME_COL);
0857   descr0.setNotNullConstraint(VERIFICATION_COL);
0858   descr0.setNotNullConstraint(PRINCIPAL_KEY_COL);
0859   descr0.setNotNullConstraint(ADMIN_KEY_COL);
0860   std::vector<std::string> columnsUnique;
0861   columnsUnique.push_back(PRINCIPAL_NAME_COL);
0862   descr0.setUniqueConstraint(columnsUnique);
0863   std::vector<std::string> columnsForIndex;
0864   columnsForIndex.push_back(PRINCIPAL_ID_COL);
0865   descr0.setPrimaryKey(columnsForIndex);
0866   schema.createTable(descr0);
0867 
0868   m_log << "Creating authorization table." << std::endl;
0869   std::string authorization_table_name = tname(AUTHORIZATION_TABLE, m_key.version());
0870   // authorization table
0871   addSequence(m_key.version(), schema, authorization_table_name);
0872   coral::TableDescription descr1;
0873   descr1.setName(authorization_table_name);
0874   descr1.insertColumn(AUTH_ID_COL, coral::AttributeSpecification::typeNameForType<int>());
0875   descr1.insertColumn(P_ID_COL, coral::AttributeSpecification::typeNameForType<int>());
0876   descr1.insertColumn(ROLE_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0877   descr1.insertColumn(SCHEMA_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0878   descr1.insertColumn(AUTH_KEY_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0879   descr1.insertColumn(C_ID_COL, coral::AttributeSpecification::typeNameForType<int>());
0880   descr1.setNotNullConstraint(AUTH_ID_COL);
0881   descr1.setNotNullConstraint(P_ID_COL);
0882   descr1.setNotNullConstraint(ROLE_COL);
0883   descr1.setNotNullConstraint(SCHEMA_COL);
0884   descr1.setNotNullConstraint(AUTH_KEY_COL);
0885   descr1.setNotNullConstraint(C_ID_COL);
0886   columnsUnique.clear();
0887   columnsUnique.push_back(P_ID_COL);
0888   columnsUnique.push_back(ROLE_COL);
0889   columnsUnique.push_back(SCHEMA_COL);
0890   descr1.setUniqueConstraint(columnsUnique);
0891   columnsForIndex.clear();
0892   columnsForIndex.push_back(AUTH_ID_COL);
0893   descr1.setPrimaryKey(columnsForIndex);
0894   schema.createTable(descr1);
0895 
0896   m_log << "Creating credential table." << std::endl;
0897   std::string credential_table_name = tname(CREDENTIAL_TABLE, m_key.version());
0898   // credential table
0899   addSequence(m_key.version(), schema, credential_table_name);
0900   coral::TableDescription descr2;
0901   descr2.setName(credential_table_name);
0902   descr2.insertColumn(CONNECTION_ID_COL, coral::AttributeSpecification::typeNameForType<int>());
0903   descr2.insertColumn(
0904       CONNECTION_LABEL_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0905   descr2.insertColumn(USERNAME_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0906   descr2.insertColumn(PASSWORD_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0907   descr2.insertColumn(
0908       VERIFICATION_KEY_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0909   descr2.insertColumn(
0910       CONNECTION_KEY_COL, coral::AttributeSpecification::typeNameForType<std::string>(), columnSize, false);
0911   descr2.setNotNullConstraint(CONNECTION_ID_COL);
0912   descr2.setNotNullConstraint(CONNECTION_LABEL_COL);
0913   descr2.setNotNullConstraint(USERNAME_COL);
0914   descr2.setNotNullConstraint(PASSWORD_COL);
0915   descr2.setNotNullConstraint(VERIFICATION_KEY_COL);
0916   descr2.setNotNullConstraint(CONNECTION_KEY_COL);
0917   columnsUnique.clear();
0918   columnsUnique.push_back(CONNECTION_LABEL_COL);
0919   descr2.setUniqueConstraint(columnsUnique);
0920   columnsForIndex.clear();
0921   columnsForIndex.push_back(CONNECTION_ID_COL);
0922   descr2.setPrimaryKey(columnsForIndex);
0923   schema.createTable(descr2);
0924 
0925   try {
0926     schema.tableHandle(authentication_table_name)
0927         .privilegeManager()
0928         .grantToUser(m_serviceData->userName, coral::ITablePrivilegeManager::Select);
0929     schema.tableHandle(authorization_table_name)
0930         .privilegeManager()
0931         .grantToUser(m_serviceData->userName, coral::ITablePrivilegeManager::Select);
0932     schema.tableHandle(credential_table_name)
0933         .privilegeManager()
0934         .grantToUser(m_serviceData->userName, coral::ITablePrivilegeManager::Select);
0935   } catch (const coral::Exception& e) {
0936     std::cout << "WARNING: Could not grant select access to user " << m_serviceData->userName << ": [" << e.what()
0937               << "]" << std::endl;
0938   }
0939   m_log << "Granting ADMIN access permission." << std::endl;
0940   auth::KeyGenerator gen;
0941   m_principalKey = gen.make(auth::COND_DB_KEY_SIZE);
0942   auto princData = updatePrincipalData(
0943       m_key.version(), schema, m_key.principalKey(), m_key.principalName(), m_principalKey, true, m_log);
0944   std::string credentialAccessLabel = schemaLabel(m_serviceName, userName);
0945   auto connParams = updateConnectionData(
0946       m_key.version(), schema, m_principalKey, credentialAccessLabel, userName, password, true, m_log);
0947   bool ret = setPermissionData(m_key.version(),
0948                                schema,
0949                                princData.first,
0950                                m_principalKey,
0951                                auth::COND_ADMIN_ROLE,
0952                                connectionString,
0953                                connParams.first,
0954                                connParams.second,
0955                                m_log);
0956   session.close();
0957   return ret;
0958 }
0959 
0960 bool cond::CredentialStore::drop(const std::string& connectionString,
0961                                  const std::string& userName,
0962                                  const std::string& password) {
0963   CSScopedSession session(*this);
0964   session.startSuper(connectionString, userName, password);
0965 
0966   m_log << "Dropping AUTHORIZATION, CREDENTIAL, AUTHENTICATION and SEQUENCE tables." << std::endl;
0967   coral::ISchema& schema = m_session->nominalSchema();
0968   schema.dropIfExistsTable(tname(AUTHORIZATION_TABLE, m_key.version()));
0969   schema.dropIfExistsTable(tname(CREDENTIAL_TABLE, m_key.version()));
0970   schema.dropIfExistsTable(tname(AUTHENTICATION_TABLE, m_key.version()));
0971   schema.dropIfExistsTable(tname(SEQUENCE_TABLE, m_key.version()));
0972   session.close();
0973   return true;
0974 }
0975 
0976 bool cond::CredentialStore::resetAdmin(const std::string& userName, const std::string& password) {
0977   if (!m_serviceData) {
0978     throwException("The credential store has not been initialized.", "cond::CredentialStore::installAdmin");
0979   }
0980   const std::string& connectionString = m_serviceData->connectionString;
0981 
0982   CSScopedSession session(*this);
0983   session.startSuper(connectionString, userName, password);
0984 
0985   coral::ISchema& schema = m_session->nominalSchema();
0986   const std::string& principalName = m_key.principalName();
0987   const std::string& authenticationKey = m_key.principalKey();
0988   PrincipalData princData;
0989   if (!selectPrincipal(m_key.version(), schema, principalName, princData)) {
0990     std::string msg("User \"");
0991     msg += principalName + "\" has not been found.";
0992     throwException(msg, "CredentialStore::resetAdmin");
0993   }
0994   auth::Cipher cipher0(authenticationKey);
0995   m_principalKey = cipher0.b64decrypt(princData.principalKey);
0996 
0997   auto p = updatePrincipalData(m_key.version(), schema, authenticationKey, principalName, m_principalKey, false, m_log);
0998   std::string credentialAccessLabel = schemaLabel(m_serviceName, userName);
0999   auto connParams = updateConnectionData(
1000       m_key.version(), schema, m_principalKey, credentialAccessLabel, userName, password, true, m_log);
1001   bool ret = setPermissionData(m_key.version(),
1002                                schema,
1003                                p.first,
1004                                m_principalKey,
1005                                auth::COND_ADMIN_ROLE,
1006                                connectionString,
1007                                connParams.first,
1008                                connParams.second,
1009                                m_log);
1010   session.close();
1011   return ret;
1012 }
1013 
1014 bool cond::CredentialStore::updatePrincipal(const std::string& principalName,
1015                                             const std::string& authenticationKey,
1016                                             bool setAdmin) {
1017   CSScopedSession session(*this);
1018   session.start(false);
1019   coral::ISchema& schema = m_session->nominalSchema();
1020   auto princData =
1021       updatePrincipalData(m_key.version(), schema, authenticationKey, principalName, m_principalKey, false, m_log);
1022   bool ret = false;
1023   if (setAdmin) {
1024     int princId = princData.first;
1025     std::string princKey = m_principalKey;
1026     std::string connString = m_serviceData->connectionString;
1027     std::vector<Permission> permissions;
1028     if (!selectPermissions(m_key.principalName(), auth::COND_ADMIN_ROLE, connString, permissions)) {
1029       throwException("The current operating user is not admin user on the underlying Credential Store.",
1030                      "CredentialStore::updatePrincipal");
1031     }
1032     std::string connLabel = permissions.front().connectionLabel;
1033     CredentialData credsData;
1034     if (!selectConnection(m_key.version(), schema, connLabel, credsData)) {
1035       throwException("Credential Store connection has not been defined.", "CredentialStore::updatePrincipal");
1036     }
1037     auth::Cipher adminCipher(m_principalKey);
1038     ret = setPermissionData(m_key.version(),
1039                             schema,
1040                             princId,
1041                             princKey,
1042                             auth::COND_ADMIN_ROLE,
1043                             connString,
1044                             credsData.id,
1045                             adminCipher.b64decrypt(credsData.connectionKey),
1046                             m_log);
1047   }
1048   session.close();
1049   return ret;
1050 }
1051 
1052 bool cond::CredentialStore::setPermission(const std::string& principal,
1053                                           const std::string& role,
1054                                           const std::string& connectionString,
1055                                           const std::string& connectionLabel) {
1056   CSScopedSession session(*this);
1057   session.start(false);
1058 
1059   coral::ISchema& schema = m_session->nominalSchema();
1060 
1061   PrincipalData princData;
1062   bool found = selectPrincipal(m_key.version(), schema, principal, princData);
1063 
1064   if (!found) {
1065     std::string msg = "Principal \"" + principal + "\" does not exist in the database.";
1066     throwException(msg, "CredentialStore::setPermission");
1067   }
1068 
1069   m_log << "Principal " << principal << " id: " << princData.id << std::endl;
1070   CredentialData credsData;
1071   found = selectConnection(m_key.version(), schema, connectionLabel, credsData);
1072 
1073   if (!found) {
1074     std::string msg = "Connection named \"" + connectionLabel + "\" does not exist in the database.";
1075     throwException(msg, "CredentialStore::setPermission");
1076   }
1077 
1078   auth::Cipher cipher(m_principalKey);
1079   bool ret = setPermissionData(m_key.version(),
1080                                schema,
1081                                princData.id,
1082                                cipher.b64decrypt(princData.adminKey),
1083                                role,
1084                                connectionString,
1085                                credsData.id,
1086                                cipher.b64decrypt(credsData.connectionKey),
1087                                m_log);
1088   session.close();
1089   return ret;
1090 }
1091 
1092 size_t cond::CredentialStore::unsetPermission(const std::string& principal,
1093                                               const std::string& role,
1094                                               const std::string& connectionString) {
1095   if (!role.empty() && cond::auth::ROLES.find(role) == cond::auth::ROLES.end()) {
1096     throwException(std::string("Role ") + role + " does not exists.", "CredentialStore::unsetPermission");
1097   }
1098   CSScopedSession session(*this);
1099   session.start(false);
1100   coral::ISchema& schema = m_session->nominalSchema();
1101 
1102   coral::AttributeList deleteData;
1103   deleteData.extend<std::string>(SCHEMA_COL);
1104   std::stringstream whereClause;
1105   m_log << "Removing permissions to access resource " << connectionString;
1106   if (!role.empty()) {
1107     deleteData.extend<std::string>(ROLE_COL);
1108     m_log << " with role " << role;
1109   }
1110   int princId = -1;
1111   if (!principal.empty()) {
1112     PrincipalData princData;
1113     bool found = selectPrincipal(m_key.version(), schema, principal, princData);
1114 
1115     if (!found) {
1116       std::string msg = "Principal \"" + principal + "\" does not exist in the database.";
1117       throwException(msg, "CredentialStore::unsetPermission");
1118     }
1119     deleteData.extend<int>(P_ID_COL);
1120     princId = princData.id;
1121     m_log << " by principal " << principal << " (id: " << princData.id << ")";
1122   }
1123 
1124   size_t n_e = getAuthorizationEntries(m_key.version(), schema, princId, role, connectionString);
1125   m_log << ": " << n_e << " authorization entries." << std::endl;
1126   if (n_e) {
1127     deleteData[SCHEMA_COL].data<std::string>() = connectionString;
1128     whereClause << SCHEMA_COL << " = :" << SCHEMA_COL;
1129     if (!role.empty()) {
1130       deleteData[ROLE_COL].data<std::string>() = role;
1131       whereClause << " AND " << ROLE_COL << " = :" << ROLE_COL;
1132     }
1133     if (!principal.empty()) {
1134       deleteData[P_ID_COL].data<int>() = princId;
1135       whereClause << " AND " << P_ID_COL + " = :" + P_ID_COL;
1136     }
1137     coral::ITableDataEditor& editor = schema.tableHandle(tname(AUTHORIZATION_TABLE, m_key.version())).dataEditor();
1138     editor.deleteRows(whereClause.str(), deleteData);
1139   }
1140   session.close();
1141   return n_e;
1142 }
1143 
1144 bool cond::CredentialStore::updateConnection(const std::string& connectionLabel,
1145                                              const std::string& userName,
1146                                              const std::string& password) {
1147   CSScopedSession session(*this);
1148   session.start(false);
1149 
1150   m_session->transaction().start();
1151   coral::ISchema& schema = m_session->nominalSchema();
1152   std::string connLabel = to_lower(connectionLabel);
1153   updateConnectionData(m_key.version(), schema, m_principalKey, connLabel, userName, password, true, m_log);
1154 
1155   session.close();
1156   return true;
1157 }
1158 
1159 bool cond::CredentialStore::removePrincipal(const std::string& principal) {
1160   CSScopedSession session(*this);
1161   session.start(false);
1162   coral::ISchema& schema = m_session->nominalSchema();
1163 
1164   PrincipalData princData;
1165   bool found = selectPrincipal(m_key.version(), schema, principal, princData);
1166 
1167   if (!found) {
1168     std::string msg = "Principal \"" + principal + "\" does not exist in the database.";
1169     throwException(msg, "CredentialStore::removePrincipal");
1170   }
1171 
1172   m_log << "Removing principal " << principal << " (id: " << princData.id << ")" << std::endl;
1173 
1174   coral::ITableDataEditor& editor0 = schema.tableHandle(tname(AUTHORIZATION_TABLE, m_key.version())).dataEditor();
1175 
1176   coral::AttributeList deleteData0;
1177   deleteData0.extend<int>(P_ID_COL);
1178   deleteData0[P_ID_COL].data<int>() = princData.id;
1179   std::string whereClause0 = P_ID_COL + " = :" + P_ID_COL;
1180   editor0.deleteRows(whereClause0, deleteData0);
1181 
1182   coral::ITableDataEditor& editor1 = schema.tableHandle(tname(AUTHENTICATION_TABLE, m_key.version())).dataEditor();
1183 
1184   coral::AttributeList deleteData1;
1185   deleteData1.extend<int>(PRINCIPAL_ID_COL);
1186   deleteData1[PRINCIPAL_ID_COL].data<int>() = princData.id;
1187   std::string whereClause1 = PRINCIPAL_ID_COL + " = :" + PRINCIPAL_ID_COL;
1188   editor1.deleteRows(whereClause1, deleteData1);
1189 
1190   session.close();
1191 
1192   return true;
1193 }
1194 
1195 bool cond::CredentialStore::removeConnection(const std::string& connectionLabel) {
1196   CSScopedSession session(*this);
1197   session.start(false);
1198   coral::ISchema& schema = m_session->nominalSchema();
1199 
1200   CredentialData credsData;
1201   bool found = selectConnection(m_key.version(), schema, connectionLabel, credsData);
1202 
1203   if (!found) {
1204     std::string msg = "Connection named \"" + connectionLabel + "\" does not exist in the database.";
1205     throwException(msg, "CredentialStore::removeConnection");
1206   }
1207 
1208   m_log << "Removing connection " << connectionLabel << std::endl;
1209   coral::ITableDataEditor& editor0 = schema.tableHandle(tname(AUTHORIZATION_TABLE, m_key.version())).dataEditor();
1210 
1211   coral::AttributeList deleteData0;
1212   deleteData0.extend<int>(C_ID_COL);
1213   deleteData0[C_ID_COL].data<int>() = credsData.id;
1214   std::string whereClause0 = C_ID_COL + " = :" + C_ID_COL;
1215   editor0.deleteRows(whereClause0, deleteData0);
1216 
1217   coral::ITableDataEditor& editor1 = schema.tableHandle(tname(CREDENTIAL_TABLE, m_key.version())).dataEditor();
1218 
1219   coral::AttributeList deleteData1;
1220   deleteData1.extend<int>(CONNECTION_ID_COL);
1221   deleteData1[CONNECTION_ID_COL].data<int>() = credsData.id;
1222   std::string whereClause1 = CONNECTION_ID_COL + " = :" + CONNECTION_ID_COL;
1223   editor1.deleteRows(whereClause1, deleteData1);
1224 
1225   session.close();
1226 
1227   return true;
1228 }
1229 
1230 bool cond::CredentialStore::selectForUser(coral_bridge::AuthenticationCredentialSet& destinationData) {
1231   CSScopedSession session(*this);
1232   session.start(true);
1233   coral::ISchema& schema = m_session->nominalSchema();
1234 
1235   auth::Cipher cipher(m_principalKey);
1236 
1237   std::unique_ptr<coral::IQuery> query(schema.newQuery());
1238   query->addToTableList(tname(AUTHORIZATION_TABLE, m_key.version()), "AUTHO");
1239   query->addToTableList(tname(CREDENTIAL_TABLE, m_key.version()), "CREDS");
1240   coral::AttributeList readBuff;
1241   readBuff.extend<std::string>("AUTHO." + ROLE_COL);
1242   readBuff.extend<std::string>("AUTHO." + SCHEMA_COL);
1243   readBuff.extend<std::string>("AUTHO." + AUTH_KEY_COL);
1244   readBuff.extend<std::string>("CREDS." + CONNECTION_LABEL_COL);
1245   readBuff.extend<std::string>("CREDS." + USERNAME_COL);
1246   readBuff.extend<std::string>("CREDS." + PASSWORD_COL);
1247   readBuff.extend<std::string>("CREDS." + VERIFICATION_KEY_COL);
1248   coral::AttributeList whereData;
1249   whereData.extend<int>(P_ID_COL);
1250   whereData[P_ID_COL].data<int>() = m_principalId;
1251   std::stringstream whereClause;
1252   whereClause << "AUTHO." << C_ID_COL << "="
1253               << "CREDS." << CONNECTION_ID_COL;
1254   whereClause << " AND "
1255               << "AUTHO." << P_ID_COL << " = :" << P_ID_COL;
1256   query->defineOutput(readBuff);
1257   query->addToOutputList("AUTHO." + ROLE_COL);
1258   query->addToOutputList("AUTHO." + SCHEMA_COL);
1259   query->addToOutputList("AUTHO." + AUTH_KEY_COL);
1260   query->addToOutputList("CREDS." + CONNECTION_LABEL_COL);
1261   query->addToOutputList("CREDS." + USERNAME_COL);
1262   query->addToOutputList("CREDS." + PASSWORD_COL);
1263   query->addToOutputList("CREDS." + VERIFICATION_KEY_COL);
1264   query->setCondition(whereClause.str(), whereData);
1265   coral::ICursor& cursor = query->execute();
1266   while (cursor.next()) {
1267     const coral::AttributeList& row = cursor.currentRow();
1268     const std::string& role = row["AUTHO." + ROLE_COL].data<std::string>();
1269     const std::string& connectionString = row["AUTHO." + SCHEMA_COL].data<std::string>();
1270     const std::string& encryptedAuthKey = row["AUTHO." + AUTH_KEY_COL].data<std::string>();
1271     const std::string& connectionLabel = row["CREDS." + CONNECTION_LABEL_COL].data<std::string>();
1272     const std::string& encryptedUserName = row["CREDS." + USERNAME_COL].data<std::string>();
1273     const std::string& encryptedPassword = row["CREDS." + PASSWORD_COL].data<std::string>();
1274     std::string authKey = cipher.b64decrypt(encryptedAuthKey);
1275     auth::Cipher connCipher(authKey);
1276     std::string verificationString = connCipher.b64decrypt(row["CREDS." + VERIFICATION_KEY_COL].data<std::string>());
1277     if (verificationString == connectionLabel) {
1278       destinationData.registerCredentials(to_lower(connectionString),
1279                                           role,
1280                                           connCipher.b64decrypt(encryptedUserName),
1281                                           connCipher.b64decrypt(encryptedPassword));
1282     }
1283   }
1284   session.close();
1285   return true;
1286 }
1287 
1288 std::pair<std::string, std::string> cond::CredentialStore::getUserCredentials(const std::string& connectionString,
1289                                                                               const std::string& role) {
1290   CSScopedSession session(*this);
1291   session.start(true);
1292   coral::ISchema& schema = m_session->nominalSchema();
1293 
1294   auth::Cipher cipher(m_principalKey);
1295 
1296   std::unique_ptr<coral::IQuery> query(schema.newQuery());
1297   query->addToTableList(tname(AUTHORIZATION_TABLE, m_key.version()), "AUTHO");
1298   query->addToTableList(tname(CREDENTIAL_TABLE, m_key.version()), "CREDS");
1299   coral::AttributeList readBuff;
1300   readBuff.extend<std::string>("AUTHO." + AUTH_KEY_COL);
1301   readBuff.extend<std::string>("CREDS." + CONNECTION_LABEL_COL);
1302   readBuff.extend<std::string>("CREDS." + USERNAME_COL);
1303   readBuff.extend<std::string>("CREDS." + PASSWORD_COL);
1304   readBuff.extend<std::string>("CREDS." + VERIFICATION_KEY_COL);
1305   coral::AttributeList whereData;
1306   whereData.extend<int>(P_ID_COL);
1307   whereData.extend<std::string>(SCHEMA_COL);
1308   whereData.extend<std::string>(ROLE_COL);
1309   whereData[P_ID_COL].data<int>() = m_principalId;
1310   whereData[SCHEMA_COL].data<std::string>() = to_lower(connectionString);
1311   whereData[ROLE_COL].data<std::string>() = role;
1312   std::stringstream whereClause;
1313   whereClause << "AUTHO." << C_ID_COL << "="
1314               << "CREDS." << CONNECTION_ID_COL;
1315   whereClause << " AND "
1316               << "AUTHO." << P_ID_COL << " = :" << P_ID_COL;
1317   whereClause << " AND "
1318               << "AUTHO." << SCHEMA_COL << " = :" << SCHEMA_COL;
1319   whereClause << " AND "
1320               << "AUTHO." << ROLE_COL << " = :" << ROLE_COL;
1321   query->defineOutput(readBuff);
1322   query->addToOutputList("AUTHO." + AUTH_KEY_COL);
1323   query->addToOutputList("CREDS." + CONNECTION_LABEL_COL);
1324   query->addToOutputList("CREDS." + USERNAME_COL);
1325   query->addToOutputList("CREDS." + PASSWORD_COL);
1326   query->addToOutputList("CREDS." + VERIFICATION_KEY_COL);
1327   query->setCondition(whereClause.str(), whereData);
1328   coral::ICursor& cursor = query->execute();
1329   auto ret = std::make_pair(std::string(""), std::string(""));
1330   if (cursor.next()) {
1331     const coral::AttributeList& row = cursor.currentRow();
1332     const std::string& encryptedAuthKey = row["AUTHO." + AUTH_KEY_COL].data<std::string>();
1333     const std::string& connectionLabel = row["CREDS." + CONNECTION_LABEL_COL].data<std::string>();
1334     const std::string& encryptedUserName = row["CREDS." + USERNAME_COL].data<std::string>();
1335     const std::string& encryptedPassword = row["CREDS." + PASSWORD_COL].data<std::string>();
1336     std::string authKey = cipher.b64decrypt(encryptedAuthKey);
1337     auth::Cipher connCipher(authKey);
1338     std::string verificationString = connCipher.b64decrypt(row["CREDS." + VERIFICATION_KEY_COL].data<std::string>());
1339     if (verificationString == connectionLabel) {
1340       ret.first = connCipher.b64decrypt(encryptedUserName);
1341       ret.second = connCipher.b64decrypt(encryptedPassword);
1342     }
1343   }
1344   session.close();
1345   return ret;
1346 }
1347 
1348 bool cond::CredentialStore::importForPrincipal(const std::string& principal,
1349                                                const coral_bridge::AuthenticationCredentialSet& dataSource,
1350                                                bool forceUpdateConnection) {
1351   CSScopedSession session(*this);
1352   session.start(false);
1353   coral::ISchema& schema = m_session->nominalSchema();
1354 
1355   PrincipalData princData;
1356   bool found = selectPrincipal(m_key.version(), schema, principal, princData);
1357 
1358   if (!found) {
1359     std::string msg = "Principal \"" + principal + "\" does not exist in the database.";
1360     throwException(msg, "CredentialStore::importForPrincipal");
1361   }
1362 
1363   bool imported = false;
1364   auth::Cipher cipher(m_principalKey);
1365   std::string princKey = cipher.b64decrypt(princData.adminKey);
1366 
1367   const std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>& creds = dataSource.data();
1368   for (std::map<std::pair<std::string, std::string>, coral::AuthenticationCredentials*>::const_iterator iConn =
1369            creds.begin();
1370        iConn != creds.end();
1371        ++iConn) {
1372     const std::string& connectionString = iConn->first.first;
1373     coral::URIParser parser;
1374     parser.setURI(connectionString);
1375     std::string serviceName = parser.hostName();
1376     const std::string& role = iConn->first.second;
1377     std::string userName = iConn->second->valueForItem(coral::IAuthenticationCredentials::userItem());
1378     std::string password = iConn->second->valueForItem(coral::IAuthenticationCredentials::passwordItem());
1379     // first import the connections
1380     std::pair<int, std::string> conn = updateConnectionData(m_key.version(),
1381                                                             schema,
1382                                                             m_principalKey,
1383                                                             schemaLabel(serviceName, userName),
1384                                                             userName,
1385                                                             password,
1386                                                             forceUpdateConnection,
1387                                                             m_log);
1388     auth::Cipher cipher(m_principalKey);
1389     // than set the permission for the specific role
1390     setPermissionData(
1391         m_key.version(), schema, princData.id, princKey, role, connectionString, conn.first, conn.second, m_log);
1392     imported = true;
1393   }
1394   session.close();
1395   return imported;
1396 }
1397 
1398 bool cond::CredentialStore::listPrincipals(std::vector<std::string>& destination) {
1399   CSScopedSession session(*this);
1400   session.start(true);
1401   coral::ISchema& schema = m_session->nominalSchema();
1402 
1403   std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(AUTHENTICATION_TABLE, m_key.version())).newQuery());
1404   coral::AttributeList readBuff;
1405   readBuff.extend<std::string>(PRINCIPAL_NAME_COL);
1406   query->defineOutput(readBuff);
1407   query->addToOutputList(PRINCIPAL_NAME_COL);
1408   coral::ICursor& cursor = query->execute();
1409   bool found = false;
1410   while (cursor.next()) {
1411     found = true;
1412     const coral::AttributeList& row = cursor.currentRow();
1413     destination.push_back(row[PRINCIPAL_NAME_COL].data<std::string>());
1414   }
1415   session.close();
1416   return found;
1417 }
1418 
1419 bool cond::CredentialStore::listConnections(std::map<std::string, std::pair<std::string, std::string> >& destination) {
1420   CSScopedSession session(*this);
1421   session.start(true);
1422   coral::ISchema& schema = m_session->nominalSchema();
1423 
1424   std::unique_ptr<coral::IQuery> query(schema.tableHandle(tname(CREDENTIAL_TABLE, m_key.version())).newQuery());
1425   coral::AttributeList readBuff;
1426   readBuff.extend<std::string>(CONNECTION_LABEL_COL);
1427   readBuff.extend<std::string>(USERNAME_COL);
1428   readBuff.extend<std::string>(PASSWORD_COL);
1429   readBuff.extend<std::string>(VERIFICATION_KEY_COL);
1430   readBuff.extend<std::string>(CONNECTION_KEY_COL);
1431   query->defineOutput(readBuff);
1432   query->addToOutputList(CONNECTION_LABEL_COL);
1433   query->addToOutputList(USERNAME_COL);
1434   query->addToOutputList(PASSWORD_COL);
1435   query->addToOutputList(VERIFICATION_KEY_COL);
1436   query->addToOutputList(CONNECTION_KEY_COL);
1437   coral::ICursor& cursor = query->execute();
1438   bool found = false;
1439   auth::Cipher cipher0(m_principalKey);
1440   while (cursor.next()) {
1441     std::string userName("");
1442     std::string password("");
1443     const coral::AttributeList& row = cursor.currentRow();
1444     const std::string& connLabel = row[CONNECTION_LABEL_COL].data<std::string>();
1445     const std::string& encryptedKey = row[CONNECTION_KEY_COL].data<std::string>();
1446     const std::string& encryptedVerif = row[VERIFICATION_KEY_COL].data<std::string>();
1447     std::string connKey = cipher0.b64decrypt(encryptedKey);
1448     auth::Cipher cipher1(connKey);
1449     std::string verif = cipher1.b64decrypt(encryptedVerif);
1450     if (verif == connLabel) {
1451       const std::string& encryptedUserName = row[USERNAME_COL].data<std::string>();
1452       const std::string& encryptedPassword = row[PASSWORD_COL].data<std::string>();
1453       userName = cipher1.b64decrypt(encryptedUserName);
1454       password = cipher1.b64decrypt(encryptedPassword);
1455     }
1456     destination.insert(std::make_pair(connLabel, std::make_pair(userName, password)));
1457     found = true;
1458   }
1459   session.close();
1460   return found;
1461 }
1462 
1463 bool cond::CredentialStore::selectPermissions(const std::string& principalName,
1464                                               const std::string& role,
1465                                               const std::string& connectionString,
1466                                               std::vector<Permission>& destination) {
1467   CSScopedSession session(*this);
1468   session.start(true);
1469   coral::ISchema& schema = m_session->nominalSchema();
1470   std::unique_ptr<coral::IQuery> query(schema.newQuery());
1471   query->addToTableList(tname(AUTHENTICATION_TABLE, m_key.version()), "AUTHE");
1472   query->addToTableList(tname(AUTHORIZATION_TABLE, m_key.version()), "AUTHO");
1473   query->addToTableList(tname(CREDENTIAL_TABLE, m_key.version()), "CREDS");
1474   coral::AttributeList readBuff;
1475   readBuff.extend<std::string>("AUTHE." + PRINCIPAL_NAME_COL);
1476   readBuff.extend<std::string>("AUTHO." + ROLE_COL);
1477   readBuff.extend<std::string>("AUTHO." + SCHEMA_COL);
1478   readBuff.extend<std::string>("CREDS." + CONNECTION_LABEL_COL);
1479   coral::AttributeList whereData;
1480   std::stringstream whereClause;
1481   whereClause << "AUTHE." << PRINCIPAL_ID_COL << "= AUTHO." << P_ID_COL;
1482   whereClause << " AND AUTHO." << C_ID_COL << "="
1483               << "CREDS." << CONNECTION_ID_COL;
1484   if (!principalName.empty()) {
1485     whereData.extend<std::string>(PRINCIPAL_NAME_COL);
1486     whereData[PRINCIPAL_NAME_COL].data<std::string>() = principalName;
1487     whereClause << " AND AUTHE." << PRINCIPAL_NAME_COL << " = :" << PRINCIPAL_NAME_COL;
1488   }
1489   if (!role.empty()) {
1490     whereData.extend<std::string>(ROLE_COL);
1491     whereData[ROLE_COL].data<std::string>() = role;
1492     whereClause << " AND AUTHO." << ROLE_COL << " = :" << ROLE_COL;
1493   }
1494   if (!connectionString.empty()) {
1495     whereData.extend<std::string>(SCHEMA_COL);
1496     whereData[SCHEMA_COL].data<std::string>() = to_lower(connectionString);
1497     whereClause << " AND AUTHO." << SCHEMA_COL << " = :" << SCHEMA_COL;
1498   }
1499 
1500   query->defineOutput(readBuff);
1501   query->addToOutputList("AUTHE." + PRINCIPAL_NAME_COL);
1502   query->addToOutputList("AUTHO." + ROLE_COL);
1503   query->addToOutputList("AUTHO." + SCHEMA_COL);
1504   query->addToOutputList("CREDS." + CONNECTION_LABEL_COL);
1505   query->setCondition(whereClause.str(), whereData);
1506   query->addToOrderList("AUTHO." + SCHEMA_COL);
1507   query->addToOrderList("AUTHE." + PRINCIPAL_NAME_COL);
1508   query->addToOrderList("AUTHO." + ROLE_COL);
1509   coral::ICursor& cursor = query->execute();
1510   bool found = false;
1511   while (cursor.next()) {
1512     const coral::AttributeList& row = cursor.currentRow();
1513     destination.resize(destination.size() + 1);
1514     Permission& perm = destination.back();
1515     perm.principalName = row["AUTHE." + PRINCIPAL_NAME_COL].data<std::string>();
1516     perm.role = row["AUTHO." + ROLE_COL].data<std::string>();
1517     perm.connectionString = row["AUTHO." + SCHEMA_COL].data<std::string>();
1518     perm.connectionLabel = row["CREDS." + CONNECTION_LABEL_COL].data<std::string>();
1519     found = true;
1520   }
1521   session.close();
1522   return found;
1523 }
1524 
1525 bool cond::CredentialStore::exportAll(coral_bridge::AuthenticationCredentialSet& data) {
1526   CSScopedSession session(*this);
1527   session.start(true);
1528   coral::ISchema& schema = m_session->nominalSchema();
1529   std::unique_ptr<coral::IQuery> query(schema.newQuery());
1530   query->addToTableList(tname(AUTHORIZATION_TABLE, m_key.version()), "AUTHO");
1531   query->addToTableList(tname(CREDENTIAL_TABLE, m_key.version()), "CREDS");
1532   coral::AttributeList readBuff;
1533   readBuff.extend<std::string>("AUTHO." + ROLE_COL);
1534   readBuff.extend<std::string>("AUTHO." + SCHEMA_COL);
1535   readBuff.extend<std::string>("CREDS." + CONNECTION_LABEL_COL);
1536   readBuff.extend<std::string>("CREDS." + VERIFICATION_KEY_COL);
1537   readBuff.extend<std::string>("CREDS." + CONNECTION_KEY_COL);
1538   readBuff.extend<std::string>("CREDS." + USERNAME_COL);
1539   readBuff.extend<std::string>("CREDS." + PASSWORD_COL);
1540   coral::AttributeList whereData;
1541   std::stringstream whereClause;
1542   whereClause << "AUTHO." << C_ID_COL << "="
1543               << "CREDS." << CONNECTION_ID_COL;
1544 
1545   query->defineOutput(readBuff);
1546   query->addToOutputList("AUTHO." + ROLE_COL);
1547   query->addToOutputList("AUTHO." + SCHEMA_COL);
1548   query->addToOutputList("CREDS." + CONNECTION_LABEL_COL);
1549   query->addToOutputList("CREDS." + VERIFICATION_KEY_COL);
1550   query->addToOutputList("CREDS." + CONNECTION_KEY_COL);
1551   query->addToOutputList("CREDS." + USERNAME_COL);
1552   query->addToOutputList("CREDS." + PASSWORD_COL);
1553   query->setCondition(whereClause.str(), whereData);
1554   coral::ICursor& cursor = query->execute();
1555   bool found = false;
1556   auth::Cipher cipher0(m_principalKey);
1557   while (cursor.next()) {
1558     const coral::AttributeList& row = cursor.currentRow();
1559     const std::string& role = row["AUTHO." + ROLE_COL].data<std::string>();
1560     const std::string& connectionString = row["AUTHO." + SCHEMA_COL].data<std::string>();
1561     const std::string& connectionLabel = row["CREDS." + CONNECTION_LABEL_COL].data<std::string>();
1562     const std::string& encryptedVerifKey = row["CREDS." + VERIFICATION_KEY_COL].data<std::string>();
1563     const std::string& encryptedConnection = row["CREDS." + CONNECTION_KEY_COL].data<std::string>();
1564     std::string userName("");
1565     std::string password("");
1566     std::string connectionKey = cipher0.b64decrypt(encryptedConnection);
1567     auth::Cipher cipher1(connectionKey);
1568     std::string verifKey = cipher1.b64decrypt(encryptedVerifKey);
1569     if (verifKey == connectionLabel) {
1570       const std::string& encryptedUserName = row["CREDS." + USERNAME_COL].data<std::string>();
1571       const std::string& encryptedPassword = row["CREDS." + PASSWORD_COL].data<std::string>();
1572       userName = cipher1.b64decrypt(encryptedUserName);
1573       password = cipher1.b64decrypt(encryptedPassword);
1574     }
1575     data.registerCredentials(to_lower(connectionString), role, userName, password);
1576     found = true;
1577   }
1578   session.close();
1579   return found;
1580 }
1581 
1582 const std::string& cond::CredentialStore::serviceName() { return m_serviceName; }
1583 
1584 const std::string& cond::CredentialStore::keyPrincipalName() { return m_authenticatedPrincipal; }
1585 
1586 std::string cond::CredentialStore::log() { return m_log.str(); }