Add caching of App/Pkg data & use faster way to retrieve this data
[platform/core/security/askuser.git] / src / common / policy / PrivilegeInfo.cpp
1 /*
2  *  Copyright (c) 2016-2018 Samsung Electronics Co.
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        src/agent/notification-daemon/Privilege.cpp
18  * @author      Zofia Grzelewska <z.abramowska@samsung.com>
19  * @brief       Implementation of Privilege Info wrappers
20  */
21
22 #include <cstdlib>
23 #include <memory>
24 #include <set>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include "Policy.h"
29 #include "PrivilegeInfo.h"
30
31 #include <exception/Exception.h>
32 #include <log/alog.h>
33
34 #include <privilegemgr/privilege_info.h>
35 #include <privilegemgr/privilege_db_manager.h>
36 #include <glib.h>
37
38 namespace AskUser {
39
40 namespace PrivilegeInfo {
41
42 namespace {
43
44 class GListWrap {
45 public:
46     GListWrap() : m_head(nullptr) {
47         m_head = g_list_alloc();
48         if (!m_head) {
49             ALOGE("Failed to allocate glib list");
50             // FIXME : throw
51         }
52     }
53
54     GListWrap(GList *_list) : m_head(_list) {}
55
56     ~GListWrap() { g_list_free(m_head);}
57
58     void append(gpointer data) {
59         GList *newHead = g_list_prepend(m_head, data);
60         if (newHead == nullptr) {
61             ALOGE("Failed to prepend the glib list");
62             return;
63         }
64         m_head = newHead;
65     }
66     GList * get() { return m_head; }
67
68 private:
69     GList *m_head;
70 };
71
72 Privacy getPrivacyName(const Privilege &privilege) {
73     char* privacyName = nullptr;
74     int ret = privilege_info_get_privacy_by_privilege(privilege.c_str(), &privacyName);
75     if (ret != PRVMGR_ERR_NONE || !privacyName) {
76         ALOGE("Unable to get privacy group for privilege: <" << privilege << ">, err: <" << ret << ">");
77         return privilege;
78     }
79
80     std::unique_ptr<char, decltype(free) *> privacyNamePtr(privacyName, free);
81     return std::string(privacyName);
82 }
83
84 } //namespace anonymous
85
86 std::vector<Privacy> getPrivilegesPrivacies(const std::vector<std::string> &corePrivileges) {
87     std::set<Privacy> privaciesSet;
88     for (auto &privilege : corePrivileges) {
89         ALOGD("Getting privacy for privilege : " << privilege);
90         if (!isPrivacy(privilege)) {
91             ALOGD("Privilege " << privilege << " is not privacy, skipping");
92             continue;
93         }
94         Privacy privacy = getPrivacyName(privilege);
95         if (privacy.empty()) {
96             // FIXME: should we abort whole request or ignore privilege which cannot be mapped to privacy?
97             ALOGE("Something went wrong with fetching privacy name for " << privilege << ", aborting");
98             return {};
99         } else {
100             ALOGD("Privilege belongs to privacy " << privacy);
101         }
102         privaciesSet.insert(privacy);
103     }
104     return std::vector<Privacy>(privaciesSet.begin(), privaciesSet.end());
105 }
106
107 std::vector<Privilege> getPrivilegeMapping(AppInfo &appInfo, const std::string &appId, const Privilege &privilege) {
108     ALOGD("Mapping privilege " << privilege);
109     uid_t uid = geteuid();
110     std::string version = appInfo.apiVersion(appId, uid);
111     std::string type = appInfo.type(appId, uid);
112
113     if (version.empty() || type.empty()) {
114         ALOGE("Failed to fetch application version and type");
115         return {};
116     }
117     ALOGD("App " << appId << " is of type " << type << " and version " << version);
118
119     privilege_manager_package_type_e pkgType;
120     if (type == "c++app" || type == "capp") {
121         pkgType = PRVMGR_PACKAGE_TYPE_CORE;
122     } else if (type == "webapp") {
123         pkgType = PRVMGR_PACKAGE_TYPE_WRT;
124     } else {
125         ALOGD("Application type not supported by mapping : " << type);
126         return {privilege};
127     }
128
129     GListWrap privList;
130     privList.append(const_cast<void*>(static_cast<const void *>(privilege.c_str())));
131
132     GList *privMapped = nullptr;
133     int ret = privilege_db_manager_get_mapped_privilege_list(version.c_str(), pkgType, privList.get(), &privMapped);
134     if (ret != PRIVILEGE_DB_MANAGER_ERR_NONE || !privMapped) {
135         ALOGE("Unable to get mapping of privilege " << privilege << "; err: <" << ret <<  ">");
136         return {};
137     }
138
139     GListWrap privMappedWrap(privMapped);
140     std::vector<std::string> privMappedVector;
141     for (GList *l = privMappedWrap.get(); l != NULL; l = l->next) {
142         std::string corePriv = static_cast<char*>(l->data);
143         ALOGD("Privilege mapps to " << corePriv);
144         privMappedVector.push_back(std::move(corePriv));
145     }
146
147     return privMappedVector;
148 }
149
150 bool isPrivacy(const Privilege &privilege) {
151     return privilege_info_is_privacy(privilege.c_str()) == 1;
152 }
153
154 std::string getPrivacyDisplayName(const Privacy &privacy) {
155     char *displayName = nullptr;
156     int ret = privilege_info_get_privacy_display(privacy.c_str(), &displayName);
157     if (ret != PRVMGR_ERR_NONE || !displayName) {
158         ALOGE("Unable to get privacy display name for <" << privacy << ">, err: <" << ret << ">");
159         return privacy;
160     }
161     std::unique_ptr<char, decltype(free)*> displaNamePtr(displayName, free);
162     return std::string(displayName);
163 }
164
165 std::vector<Privilege> getPrivacyPrivileges(const Privacy &privacy) {
166     GList *privilegeList = nullptr;
167
168     int ret = privilege_info_get_privilege_list_by_privacy(privacy.c_str(), &privilegeList);
169     if (ret != PRVMGR_ERR_NONE || !privilegeList) {
170         ALOGE("Unable to get privacy group list of privileges; err: <" << ret <<  ">");
171         return {privacy};
172     }
173
174     GListWrap privList(privilegeList);
175     std::vector<Privilege> privVector;
176     for (GList *l = privList.get(); l != NULL; l = l->next) {
177         privVector.push_back(static_cast<char*>(l->data));
178     }
179     return privVector;
180 }
181
182 }
183 } /* namespace AskUser */