Refactor pkgmgr-info
[platform/core/appfw/pkgmgr-info.git] / src / server / certinfo_internal.cc
1 /*
2 * Copyright (c) 2023 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
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdbool.h>
22 #include <unistd.h>
23 #include <ctype.h>
24 #include <sys/smack.h>
25 #include <linux/limits.h>
26 #include <sys/stat.h>
27
28 #include <sqlite3.h>
29 #include <glib.h>
30
31 #include "pkgmgrinfo_basic.h"
32 #include "pkgmgrinfo_private.h"
33 #include "pkgmgrinfo_internal.h"
34 #include "pkgmgrinfo_debug.h"
35 #include "pkgmgr-info.h"
36
37 namespace {
38
39 int GetCertInfo(const tizen_base::Database& db, int cert_id[],
40     char* cert_info[]) {
41   auto q = tizen_base::Database::Sql(
42       "SELECT cert_info "
43       "FROM package_cert_index_info WHERE cert_id=?");
44   auto r = db.Prepare(q);
45   if (!r) {
46     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
47     return PMINFO_R_ERROR;
48   }
49
50   for (int i = 0; i < MAX_CERT_TYPE; i++) {
51     q.Reset().Bind(cert_id[i]);
52     if (!db.Exec(q, r)) {
53       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
54       return PMINFO_R_ERROR;
55     }
56
57     auto rec = r.GetFirstRecord();
58     if (!rec)
59       continue;
60     std::string str = static_cast<std::string>(rec->Get(0));
61     cert_info[i] = strdup(str.c_str());
62   }
63
64   return PMINFO_R_OK;
65 }
66
67 int GetCertId(const tizen_base::Database& db,
68     std::string_view pkgid, int (&cert_id)[MAX_CERT_TYPE]) {
69   auto q = tizen_base::Database::Sql(
70       "SELECT author_root_cert, author_im_cert, "
71       "author_signer_cert, dist_root_cert, "
72       "dist_im_cert, dist_signer_cert, dist2_root_cert, "
73       "dist2_im_cert, dist2_signer_cert "
74       "FROM package_cert_info WHERE package=?")
75       .Bind(std::string(pkgid));
76
77   auto r = db.Exec(q);
78   if (!r) {
79     _LOGE("Exec failed: %s", static_cast<const char*>(r));
80     return PMINFO_R_ERROR;
81   }
82
83   auto rec = r.GetFirstRecord();
84   if (!rec)
85     return PMINFO_R_ERROR;
86
87   for (int i = 0; i < MAX_CERT_TYPE; i++) {
88     std::optional<int> id = rec->Get(i);
89     if (!id)
90       cert_id[i] = 0;
91     else
92       cert_id[i] = *id;
93   }
94
95   return PMINFO_R_OK;
96 }
97
98 int GetCert(const tizen_base::Database& db,
99     std::string_view pkgid, pkgmgr_certinfo_x* info) {
100   int ret;
101
102   ret = GetCertId(db, pkgid, info->cert_id);
103   if (ret != PMINFO_R_OK)
104     return ret;
105
106   ret = GetCertInfo(db, info->cert_id, info->cert_info);
107   if (ret != PMINFO_R_OK)
108     return ret;
109
110   return PMINFO_R_OK;
111 }
112
113 int SaveCertIndex(const tizen_base::Database& db,
114     char* cert_info[]) {
115   auto q = tizen_base::Database::Sql(
116       "INSERT OR REPLACE INTO package_cert_index_info "
117       "(cert_info, cert_id, cert_ref_count) "
118       "VALUES ( "
119       " ?, "
120       " (SELECT cert_id FROM package_cert_index_info "
121       "  WHERE cert_info=?), "
122       " COALESCE( "
123       "  ((SELECT cert_ref_count FROM package_cert_index_info "
124       "    WHERE cert_info=?) + 1), 1))");
125   auto r = db.Prepare(q);
126   if (!r) {
127     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
128     return PMINFO_R_ERROR;
129   }
130
131   for (int i = 0; i < MAX_CERT_TYPE; i++) {
132     if (cert_info[i] == nullptr)
133       continue;
134     q.Reset()
135         .Bind(cert_info[i])
136         .Bind(cert_info[i])
137         .Bind(cert_info[i]);
138     if (!db.Exec(q, r)) {
139       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
140       return PMINFO_R_ERROR;
141     }
142   }
143
144   return PMINFO_R_OK;
145 }
146
147 int SaveCertInfo(const tizen_base::Database& db,
148     std::string_view pkgid, char* cert_info[]) {
149   auto q_insert = tizen_base::Database::Sql(
150       "INSERT INTO package_cert_info (package, package_count,"
151       " author_root_cert, author_im_cert, author_signer_cert,"
152       " dist_root_cert, dist_im_cert, dist_signer_cert,"
153       " dist2_root_cert, dist2_im_cert, dist2_signer_cert) "
154       "VALUES(?, 1,"
155       " (SELECT cert_id FROM package_cert_index_info"
156       " WHERE cert_info=?),"
157       " (SELECT cert_id FROM package_cert_index_info"
158       " WHERE cert_info=?),"
159       " (SELECT cert_id FROM package_cert_index_info"
160       " WHERE cert_info=?),"
161       " (SELECT cert_id FROM package_cert_index_info"
162       " WHERE cert_info=?),"
163       " (SELECT cert_id FROM package_cert_index_info"
164       " WHERE cert_info=?),"
165       " (SELECT cert_id FROM package_cert_index_info"
166       " WHERE cert_info=?),"
167       " (SELECT cert_id FROM package_cert_index_info"
168       " WHERE cert_info=?),"
169       " (SELECT cert_id FROM package_cert_index_info"
170       " WHERE cert_info=?),"
171       " (SELECT cert_id FROM package_cert_index_info"
172       " WHERE cert_info=?))")
173       .Bind(std::string(pkgid));
174
175   for (int i = 0; i < MAX_CERT_TYPE; i++)
176     q_insert.Bind(cert_info[i]);
177
178   int code = static_cast<int>(db.Exec(q_insert));
179   if (code == SQLITE_CONSTRAINT) {
180     auto q_update = tizen_base::Database::Sql(
181         "UPDATE package_cert_info "
182         "SET package_count = package_count + 1 "
183         "WHERE package=?")
184         .Bind(std::string(pkgid));
185     auto r = db.Exec(q_update);
186     if (!r) {
187       _LOGE("error: %s", static_cast<const char*>(r));
188       return PMINFO_R_ERROR;
189     }
190   } else if (code != SQLITE_DONE) {
191     return PMINFO_R_ERROR;
192   }
193
194   return PMINFO_R_OK;
195 }
196
197 }  // namespace
198
199 namespace pkgmgr_server::internal {
200
201 int CertInfoGet(const tizen_base::Database& db,
202     std::string_view pkgid, uid_t uid, pkgmgrinfo_certinfo_h certinfo) {
203   pkgmgr_certinfo_x* info = static_cast<pkgmgr_certinfo_x*>(certinfo);
204
205   if (pkgid.empty() || certinfo == nullptr)
206     return PMINFO_R_EINVAL;
207
208   int ret;
209   try {
210     ret = GetCert(db, pkgid, info);
211     if (ret != PMINFO_R_OK)
212       _LOGE("failed to get certinfo of %s ", pkgid.data());
213   } catch (const tizen_base::DbException& e) {
214     _LOGE("Exception: %s", e.msg());
215     return PMINFO_R_ERROR;
216   }
217
218   return ret;
219 }
220
221 int CertInfoSet(const tizen_base::Database& db,
222     std::string_view pkgid, pkgmgrinfo_instcertinfo_h handle, uid_t uid) {
223   pkgmgr_certinfo_x* info = static_cast<pkgmgr_certinfo_x*>(handle);
224
225   if (pkgid.empty() || handle == nullptr) {
226     _LOGE("invalid parameter");
227     return PMINFO_R_EINVAL;
228   }
229
230   try {
231     auto guard = db.CreateTransactionGuard();
232
233     if (SaveCertIndex(db, info->cert_info)) {
234       _LOGE("failed to save cert index info, rollback now");
235       return PMINFO_R_ERROR;
236     }
237
238     if (SaveCertInfo(db, pkgid, info->cert_info)) {
239       _LOGE("failed to save cert info, rollback now");
240       return PMINFO_R_ERROR;
241     }
242
243     guard.Commit();
244   } catch (const tizen_base::DbException& e) {
245     _LOGE("Exception: %s", e.msg());
246     return PMINFO_R_ERROR;
247   }
248
249   return PMINFO_R_OK;
250 }
251
252 }  // namespace pkgmgr_server::internal