/* * 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 #include #include #include #include #include #include #include using namespace std; using namespace CKM; typedef function RowFilter; typedef vector 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.owner; cout << "\n Exportable: " << row.exportable; cout << "\n Alg type: " << static_cast(row.algorithmType); cout << "\n Enc schema: " << row.encryptionScheme; cout << "\n Data size: " << row.dataSize; cout << "\n BackendId: " << static_cast(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.owner = 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; }