8e5c6c07be535f4357803b91cb86dab904b2a2b8
[platform/core/security/suspicious-activity-monitor.git] / device-agent / samonitor / dpm / dpm_api_mapper.cpp
1 /**
2  * Samsung Ukraine R&D Center (SRK under a contract between)
3  * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
4  * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
5  */
6 /**
7  * @file   dpm_api_mapper.cpp
8  * @brief  Mapper of policy feature names into DPM API calls
9  * @date   Created Jun 23, 2017
10  * @author Mail to: <A HREF="mailto:a.zabolotnyi@samsung.com">Andrey Zabolotnyi, a.zabolotnyi@samsung.com</A>
11  * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
12  */
13 #include <functional>
14 #include <map>
15 #include <dirent.h>
16 #include <fstream>
17 #include <thread>
18 #include <chrono>
19 #include <unistd.h>
20 #include <pwd.h>
21
22 #include <dpm/device-policy-manager.h>
23 #include <dpm/bluetooth.h>
24 #include <dpm/wifi.h>
25 #include <dpm/restriction.h>
26 #include <dpm/application.h>
27 #include <dpm/security.h>
28 #include <dpm/firewall.h>
29
30 #include "logging.h"
31 #include "samonitor_tag.h"
32 #include "dpm_api_mapper.h"
33
34 using namespace dpm_api;
35 using namespace std;
36
37 typedef device_policy_manager_h dpmh;
38
39 typedef function<int(dpmh)>  ApiNone;
40 typedef function<int(dpmh, int)>  ApiInt;
41 typedef function<int(dpmh, const char*)>  ApiStr;
42 typedef function<int(dpmh, int, const char*)>  ApiIntStr;
43
44 const map<const string, ApiNone> m = {
45     {"lockout-screen",  dpm_security_lockout_screen},
46 };
47
48 const map<const string, ApiInt> mi = {
49     {"sound",           dpm_restriction_set_sound_state},
50     {"bluetooth",       dpm_restriction_set_bluetooth_mode_change_state},
51     {"wifi",            dpm_restriction_set_wifi_state},
52     {"usb",             dpm_restriction_set_usb_client_state},
53     {"dtv-tunner",      dpm_restriction_set_tuner_state},
54
55     {"camera",          dpm_restriction_set_camera_state},
56     {"microphone",      dpm_restriction_set_microphone_state},
57     {"location",        dpm_restriction_set_location_state},
58     {"clipboard",       dpm_restriction_set_clipboard_state},
59     {"usb-debug",       dpm_restriction_set_usb_debugging_state},
60     {"wifi-hotspot",    dpm_restriction_set_wifi_hotspot_state},
61     {"bt-tethering",    dpm_restriction_set_bluetooth_tethering_state},
62     {"usb-tethering",   dpm_restriction_set_usb_tethering_state},
63     {"bt-mode-change",  dpm_restriction_set_bluetooth_mode_change_state},
64     {"bt-desktop-conn", dpm_restriction_set_bluetooth_desktop_connectivity_state},
65     {"bt-pairing",      dpm_restriction_set_bluetooth_pairing_state},
66     {"email",           dpm_restriction_set_popimap_email_state},
67     {"browser",         dpm_restriction_set_browser_state},
68     {"bt-mac",          dpm_bluetooth_set_device_restriction},
69     {"bt-uuid",         dpm_bluetooth_set_uuid_restriction},
70     {"int-stor-enc",    dpm_security_set_internal_storage_encryption},
71     {"ext-stor-enc",    dpm_security_set_external_storage_encryption},
72     {"wifi-profile",    dpm_wifi_set_profile_change_restriction},
73     {"wifi-network",    dpm_wifi_set_network_access_restriction},
74 };
75
76 const map<const string, ApiStr> ms = {
77     {"iptables",        dpm_firewall_apply_deny_rules},
78
79     {"bt-mac-add",      dpm_bluetooth_add_device_to_blacklist},
80     {"bt-mac-del",      dpm_bluetooth_remove_device_from_blacklist},
81     {"bt-uuid-add",     dpm_bluetooth_add_uuid_to_blacklist},
82     {"bt-uuid-del",     dpm_bluetooth_remove_uuid_from_blacklist},
83     {"wifi-ssid-add",   dpm_wifi_add_ssid_to_blocklist},
84     {"wifi-ssid-del",   dpm_wifi_remove_ssid_from_blocklist},
85
86 };
87
88 #ifdef USE_MIS
89 const map<const string, ApiIntStr> mis;
90 #endif
91
92
93 //      {"wipe external data", dpm_security_wipe_data},
94 //      {"wipe internal data", dpm_security_wipe_data},
95 //      {"messaging",       dpm_restriction_set_messaging_state},
96 //      {"privil-add",      dpm_application_add_privilege_to_blacklist},
97 //      {"privil-del",      dpm_application_remove_privilege_from_blacklist},
98 //      {"package-set", dpm_application_set_mode_restriction},
99 //      {"package-unset", dpm_application_unset_mode_restriction},
100
101 Mapper::Mapper() : handle(nullptr)
102 {
103 }
104
105 Mapper::~Mapper()
106 {
107     if (handle) {
108         dpm_manager_destroy((dpmh)handle);
109     }
110 }
111
112 dpm_api::ErrorCode convert_err(int err)
113 {
114     switch (err) {
115     case DPM_ERROR_NONE:
116         return SUCCESS;
117     case DPM_ERROR_INVALID_PARAMETER:
118         return INVALID_PARAMETER;
119     case DPM_ERROR_CONNECTION_REFUSED:
120         return CONNECTION_REFUSED;
121     case DPM_ERROR_TIMED_OUT:
122         return TIMED_OUT;
123     case DPM_ERROR_PERMISSION_DENIED:
124         return PERMISSION_DENIED;
125     case DPM_ERROR_NOT_PERMITTED:
126         return NOT_PERMITTED;
127     case DPM_ERROR_FILE_EXISTS:
128         return FILE_EXISTS;
129     case DPM_ERROR_OUT_OF_MEMORY:
130         return OUT_OF_MEMORY;
131     case DPM_ERROR_NO_DATA:
132         return NO_DATA;
133     default:
134         return UNKNOWN;
135     }
136     return UNKNOWN;
137 }
138
139 const char* Mapper::getErrorString(dpm_api::ErrorCode err)
140 {
141     struct errs {
142         dpm_api::ErrorCode  code;
143         const char*  name;
144     };
145
146     static const errs errs_arr[] = {
147         {SUCCESS,               "The operation was successful"},
148         {INVALID_PARAMETER,     "Invalid parameter"},
149         {CONNECTION_REFUSED,    "Connection refused"},
150         {TIMED_OUT,             "Time out"},
151         {PERMISSION_DENIED,     "Access privilege is not sufficient"},
152         {NOT_PERMITTED,         "Operation not permitted"},
153         {FILE_EXISTS,           "File exists"},
154         {OUT_OF_MEMORY,         "Out of memory"},
155         {NO_DATA,               "No Data"},
156         {NOT_INITIALIZED,       "Library not initialized"},
157         {NAME_NOT_FOUND,        "Policy's name not found"},
158         {UNKNOWN,               "Unknown error"},
159     };
160
161     for (unsigned int i = 0; i < sizeof(errs_arr) / sizeof(errs_arr[0]); ++i) {
162         if (errs_arr[i].code == err) {
163             return errs_arr[i].name;
164         }
165     }
166
167     return "Unknown";
168 }
169
170 pid_t getUidByName(const std::string& name)
171 {
172     long int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
173     if (bufsize == -1) {
174         bufsize = 16384;
175     }
176
177     char* buf = new char[bufsize];
178     struct passwd pwd;
179     struct passwd* result;
180
181     int s = getpwnam_r(name.c_str(), &pwd, buf, bufsize, &result);
182     pid_t pid = pwd.pw_uid;
183     delete[] buf;
184
185     if (result == nullptr) {
186         if (s == 0) {
187             throw std::runtime_error("User not found");
188         } else {
189             throw std::runtime_error("Get user info error: " + std::to_string(s));
190         }
191     }
192
193     return pid;
194 }
195
196 dpm_api::ErrorCode Mapper::apply(const std::string& name, const int param, const vector<string>& items)
197 {
198     dpm_api::ErrorCode res;
199     // temporary change user to 'owner'
200     uid_t root = geteuid();
201     uid_t owner;
202
203     try {
204 #ifndef __MOCK_THIRDPARTY__
205         owner = getUidByName("owner");
206 #else
207         owner = root;
208 #endif
209     } catch (std::runtime_error& e) {
210         LOG_E(TAG, "getUidByName(): %s", e.what());
211         return NO_DATA;
212     }
213
214     setresuid(root, owner, root);
215
216     if (!handle) {
217         handle = (dpmh)dpm_manager_create();
218     }
219
220     res = work(name, param, items);
221     setresuid(root, root, -1);
222     return res;
223 }
224
225 dpm_api::ErrorCode Mapper::work(const std::string& name, const int param, const vector<string>& items)
226 {
227     LOG_D(TAG, "Mapper::work: %s %i", name.c_str(), param);
228
229     int res = 0;
230     if (!handle) {
231         return NOT_INITIALIZED;
232     }
233
234     auto iti = mi.find(name);
235     if (iti != mi.end()) {
236         return convert_err(iti->second((dpmh)handle, param));
237     }
238
239     auto itn = m.find(name);
240     if (itn != m.end()) {
241         return convert_err(itn->second((dpmh)handle));
242     }
243
244     auto its = ms.find(name);
245     if (its != ms.end()) {
246         bool use_items = true;
247         if (name == "iptables") {
248             dpm_firewall_flush_deny_rules((dpmh)handle);
249             if (param == 0) use_items = false; // turn off the firewall
250         }
251
252         if (use_items) {
253             for (auto& item : items) {
254                 res = its->second((dpmh)handle, item.c_str());
255                 if (res != DPM_ERROR_NONE) {
256                     break;
257                 }
258             }
259         }
260         return convert_err(res);
261     }
262
263 #ifdef USE_MIS
264     auto itis = mis.find(name);
265     if (itis != mis.end()) {
266         for (auto& item : items) {
267             res = itis->second((dpmh)handle, param, item.c_str());
268             if (res != DPM_ERROR_NONE) {
269                 break;
270             }
271         }
272         return convert_err(res);
273     }
274 #endif
275
276     return NAME_NOT_FOUND;
277 }