diff options
Diffstat (limited to 'tools/ckm_db_tool/ckm_db_merge.cpp')
-rw-r--r-- | tools/ckm_db_tool/ckm_db_merge.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/tools/ckm_db_tool/ckm_db_merge.cpp b/tools/ckm_db_tool/ckm_db_merge.cpp new file mode 100644 index 00000000..17e308cf --- /dev/null +++ b/tools/ckm_db_tool/ckm_db_merge.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file ckm_db_merge.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @version 1.0 + */ + +#include <string> +#include <vector> +#include <iostream> +#include <sstream> +#include <exception> + +#include <getopt.h> +#include <unistd.h> + +#include <db-wrapper.h> + +using namespace std; +using namespace CKM; + +typedef function<bool(DB::Row &row)> RowFilter; +typedef vector<RowFilter> RowFilterVector; + +bool printRow(const DB::Row &row) { + string iv(10, ' '), data(10, ' '); + for (std::size_t i=0; i < iv.size(); ++i) { + if (row.iv.size() > i) iv[i] = row.iv[i]; + if (row.data.size() > i) data[i] = row.data[i]; + } + cout << "Read row:"; + cout << "\n Name: " << row.name; + cout << "\n Owner: " << row.ownerLabel; + cout << "\n Exportable: " << row.exportable; + cout << "\n Alg type: " << static_cast<int>(row.algorithmType); + cout << "\n Enc schema: " << row.encryptionScheme; + cout << "\n Data size: " << row.dataSize; + cout << "\n BackendId: " << static_cast<int>(row.backendId); + cout << "\n Data(first 10 chars): " << data; + cout << "\n IV(first 10 chars): " << iv; + cout << "\n"; + return true; +} + +void printUsage() +{ + cout << "Usage: ckm_db_merge [OPTION]\n"; + cout << "Copy data from one key-manager database into other one.\n"; + cout << "Options:\n"; + cout << " -v, --verbose print additional data on screen\n"; + cout << " -s, --source UID database UID from were data will be readed - default value 0\n"; + cout << " -t, --target UID database UID to were data will be writen - default value 0\n"; + cout << " -p, --spass PASSWORD password for source database - default empty string\n"; + cout << " -r, --tpass PASSWORD password for target database - default emtpy string\n"; + cout << " -o, --owner OWNER change the owner of information in database to OWNER\n"; + cout << " -h, --help print this help on screen\n"; + cout << "Example: Copy data from db-5001 to db-0 (system database) and change object owner to /System\n"; + cout << " ckm_db_merge -s 5001 -t 0 -p !@#SDFCV -o \"/System\"\n"; + cout << "Please note: This tool automatically updates databases to newest scheme!" << endl; +} + +int mergeDatabase( + uid_t uid1, + const Password &pass1, + uid_t uid2, + const Password &pass2, + const RowFilterVector &filters) +{ + DbWrapper source(uid1, pass1); + DbWrapper target(uid2, pass2); + + int ret; + + if (CKM_API_SUCCESS != (ret = source.unlock())) { // this should migrate database to newest version + cerr << "Unlocking source database failed: " << ret << endl; + return 1; + } + if (CKM_API_SUCCESS != (ret = target.unlock())) { // this should migrate database to newest version + cerr << "Unlocking target database failed: " << ret << endl; + return 1; + } + + DB::RowVector data = source.getRows(); + + // apply all filters to each row + for (auto &e : data) { + bool migrate = true; + for (auto &f : filters) { + migrate &= f(e); + } + if (migrate) { + try { + target.saveRow(e); + } catch (const CKM::DB::SqlConnection::Exception::Base &e) { + cerr << "Sql exception. Migration failed or object already exist in database: " << e.DumpToString() << endl; + } + } + } + + source.lock(); + target.lock(); + return 0; +} + +int main(int argc, char *argv[]) { + Password password1, password2; + uid_t uid1 = 0, uid2 = 0; + string owner; + RowFilterVector filters; + try { + while (1) { + int option_index = 0; + + static struct option long_options[] = { + {"verbose", no_argument, 0, 'v'}, + {"source", required_argument, 0, 's'}, + {"target", required_argument, 0, 't'}, + {"spass", required_argument, 0, 'p'}, + {"tpass", required_argument, 0, 'r'}, + {"owner", required_argument, 0, 'o'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0 } + }; + int c = getopt_long(argc, argv, "vs:t:p:r:o:h", long_options, &option_index); + + if (-1 == c) + break; + + switch (c) { + case 'v': + filters.push_back(printRow); + break; + case 's': + uid1 = stoi(optarg); + break; + case 't': + uid2 = stoi(optarg); + break; + case 'p': + password1 = optarg; + break; + case 'r': + password2 = optarg; + break; + case 'o': + owner = optarg; // I cannot pass optarg to lambda because it's pointer + filters.push_back([=](DB::Row &row) {row.ownerLabel = owner; return true;}); + break; + case 'h': + printUsage(); + return 0; + case '?': + case ':': + default: + printUsage(); + return 1; + } + } + + if (uid1 == uid2) { + cerr << "Source database and target database must be different!" << endl; + return 1; + } + + return mergeDatabase(uid1, password1, uid2, password2, filters); + } catch (const CKM::DB::SqlConnection::Exception::InvalidColumn &e) { + cerr << "Invalid Column exception was catched. Probably migration failed. " << e.DumpToString() << endl; + } catch (const invalid_argument &e) { + cerr << "Argument could not be converted" << endl; + } catch (const out_of_range &e) { + cerr << "Out of range" << endl; + } catch (const exception &e) { + cerr << "Unexpected error: " << e.what() << endl; + } catch (...) { + cerr << "Unknown exception" << endl; + } + + return 1; +} |