Release 0.1.54.9
[platform/core/security/key-manager.git] / misc / ckm_db_tool / db-wrapper.cpp
1 /*
2  *  Copyright (c) 2000-2020 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file       db-wrapper.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @author     Bartlomiej Grzelewski (b.grzelewski@samsung.com)
20  * @version    1.0
21  */
22 #include "db-wrapper.h"
23 #include "ui.h"
24
25 #include <string>
26 #include <algorithm>
27 #include <utility>
28
29 #include <base64.h>
30
31 namespace {
32
33 const size_t MAX_LEN = 64;
34 const char ELLIPSIS[] = "...";
35 const size_t ELLIPSIS_LEN = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]);
36
37
38 const char *const SQL_TABLES = "SELECT name FROM sqlite_master "
39                                                            "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
40                                                            "UNION ALL "
41                                                            "SELECT name FROM sqlite_temp_master "
42                                                            "WHERE type IN ('table','view') "
43                                                            "ORDER BY 1";
44
45 const char *const SQL_SCHEMA = "SELECT sql FROM "
46                                                            "(SELECT * FROM sqlite_master "
47                                                            "UNION ALL "
48                                                            "SELECT * FROM sqlite_temp_master) "
49                                                            "WHERE type!='meta' AND sql!='NULL'"
50                                                            "ORDER BY tbl_name, type DESC, name";
51 } // anonymous namespace
52
53 namespace CKM {
54
55 int DbWrapper::unlock()
56 {
57         // no unlock for system db
58         if (m_uid == 0 && m_pw.empty())
59                 return m_logic.unlockSystemDB();
60
61         int retCode;
62         MessageBuffer buff;
63         buff.Push(m_logic.unlockUserKey(m_uid, m_pw));
64         buff.Deserialize(retCode);
65         return retCode;
66 }
67
68 void DbWrapper::lock()
69 {
70         // no lock for system db
71         if (m_uid < 5000)
72                 return;
73
74         m_logic.lockUserKey(m_uid);
75 }
76
77 void DbWrapper::process(const std::string &acmd, bool shouldDecrypt)
78 {
79         try {
80                 std::string cmd = acmd;
81                 bool trim = true;
82
83                 if (acmd == ".tables") {
84                         cmd = SQL_TABLES;
85                         trim = false;
86                 } else if (acmd == ".schema") {
87                         cmd = SQL_SCHEMA;
88                         trim = false;
89                 }
90
91                 DB::SqlConnection::Output output = m_logic.Execute(m_uid, cmd);
92
93                 if (output.GetNames().empty())
94                         return;
95
96                 Decrypt decryptState(output.GetNames(), m_logic, m_uid);
97                 Decrypt *decrypt = nullptr;
98                 if (shouldDecrypt && decryptState.canDecryptQuery())
99                         decrypt = &decryptState;
100
101                 displayRow(output.GetNames(), trim, nullptr);
102                 std::cout << "--------------------------" << std::endl;
103
104                 for (const auto &row : output.GetValues()) {
105                         displayRow(row, trim, decrypt);
106                 }
107         } catch (const DB::SqlConnection::Exception::Base &e) {
108                 UI::error() << "sql exception: " << e.GetMessage() << std::endl;
109         } catch (const Exc::Exception &e) {
110                 UI::error() << "unexpected exception: " << e.message() << std::endl;
111         } catch (const std::exception &e) {
112                 UI::error() << "unexpected exception: " << e.what() << std::endl;
113         } catch (...) {
114                 UI::error() << "unknown exception" << std::endl;
115         }
116 }
117
118 void DbWrapper::displayRow(const DB::SqlConnection::Output::Row &row, bool trim, Decrypt *decrypt)
119 {
120         std::pair<std::string, bool> decrypted;
121         if (decrypt)
122                 decrypted = decrypt->tryDecrypt(row);
123
124         for (auto it = row.begin(); it != row.end(); it++) {
125                 std::string col = *it;
126
127                 if (decrypted.second && it - row.begin() == decrypt->getDataColumnIndex())
128                         col = decrypted.first;
129
130                 /*
131                  * Convert unprintable data to base64. Note that a row may contain an incomplete data
132                  * since it holds a binary data as a string.
133                  */
134                 if (std::any_of(col.begin(),
135                                 col.end(),
136                                 [](const char c){ return isprint(c) + iscntrl(c) == 0; }))
137                         col = "b64:" + CKM::base64Encode<std::string>(col);
138
139                 if (trim && col.size() > MAX_LEN) {
140                         col.resize(MAX_LEN);
141                         col.replace(MAX_LEN - ELLIPSIS_LEN, ELLIPSIS_LEN, ELLIPSIS);
142                 }
143
144                 std::cout << col;
145
146                 if (it + 1 != row.end())
147                         std::cout << "|";
148         }
149
150         std::cout << std::endl;
151 }
152
153 DB::RowVector DbWrapper::getRows()
154 {
155         return m_logic.getRows(m_uid);
156 }
157
158 void DbWrapper::saveRow(const DB::Row &row)
159 {
160         return m_logic.saveRow(m_uid, row);
161 }
162
163 } // namespace CKM