Convert ServiceImpl namespace to a class
[platform/core/security/security-manager.git] / src / server / service / master-service.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Rafal Krypa <r.krypa@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18 /*
19  * @file        master-service.cpp
20  * @author      Lukasz Kostyra <l.kostyra@samsung.com>
21  * @author      Rafal Krypa <r.krypa@samsung.com>
22  * @brief       Implementation of security-manager master service.
23  */
24
25 #include <generic-socket-manager.h>
26
27 #include <dpl/log/log.h>
28 #include <dpl/serialization.h>
29
30 #include "protocols.h"
31 #include "zone-utils.h"
32 #include "cynara.h"
33 #include "master-service.h"
34 #include "smack-rules.h"
35 #include "smack-labels.h"
36 #include "service_impl.h"
37
38 namespace SecurityManager {
39
40 const InterfaceID IFACE = 1;
41
42 MasterService::MasterService()
43 {
44 }
45
46 GenericSocketService::ServiceDescriptionVector MasterService::GetServiceDescription()
47 {
48     return ServiceDescriptionVector {
49         {MASTER_SERVICE_SOCKET, "security-manager-master", IFACE},
50     };
51 }
52
53 bool MasterService::processOne(const ConnectionID &conn, MessageBuffer &buffer,
54                                   InterfaceID interfaceID)
55 {
56     LogDebug("Iteration begin. Interface = " << interfaceID);
57
58     //waiting for all data
59     if (!buffer.Ready()) {
60         return false;
61     }
62
63     MessageBuffer send;
64     bool retval = false;
65
66     uid_t uid;
67     pid_t pid;
68     std::string smackLabel;
69
70     if (!getPeerID(conn.sock, uid, pid, smackLabel)) {
71         LogError("Closing socket because of error: unable to get peer's uid and pid");
72         m_serviceManager->Close(conn);
73         return false;
74     }
75
76     // FIXME this part needs to be updated when Vasum is added to OBS. See zone-utils.h
77     std::string vsmZoneId;
78     if (!getZoneIdFromPid(pid, vsmZoneId)) {
79         LogError("Failed to extract Zone ID! Closing socket.");
80         m_serviceManager->Close(conn);
81         return false;
82     }
83
84     if (vsmZoneId == ZONE_HOST) {
85         LogError("Connection came from host - in master mode this should not happen! Closing.");
86         m_serviceManager->Close(conn);
87         return false;
88     }
89
90     LogInfo("Connection came from Zone " << vsmZoneId);
91
92     if (IFACE == interfaceID) {
93         Try {
94             // deserialize API call type
95             int call_type_int;
96             Deserialization::Deserialize(buffer, call_type_int);
97             MasterSecurityModuleCall call_type = static_cast<MasterSecurityModuleCall>(call_type_int);
98
99             switch (call_type) {
100                 case MasterSecurityModuleCall::CYNARA_UPDATE_POLICY:
101                     LogDebug("call type MasterSecurityModuleCall::CYNARA_UPDATE_POLICY");
102                     processCynaraUpdatePolicy(buffer, send, vsmZoneId);
103                     break;
104                 case MasterSecurityModuleCall::CYNARA_USER_INIT:
105                     LogDebug("call type MasterSecurityModuleCall::CYNARA_USER_INIT");
106                     processCynaraUserInit(buffer, send);
107                     break;
108                 case MasterSecurityModuleCall::CYNARA_USER_REMOVE:
109                     LogDebug("call type MasterSecurityModuleCall::CYNARA_USER_REMOVE");
110                     processCynaraUserRemove(buffer, send);
111                     break;
112                 case MasterSecurityModuleCall::POLICY_UPDATE:
113                     LogDebug("call type MasterSecurityModuleCall::POLICY_UPDATE");
114                     processPolicyUpdate(buffer, send);
115                     break;
116                 case MasterSecurityModuleCall::GET_CONFIGURED_POLICY:
117                     LogDebug("call type MasterSecurityModuleCall::GET_CONFIGURED_POLICY");
118                     processGetConfiguredPolicy(buffer, send);
119                     break;
120                 case MasterSecurityModuleCall::GET_POLICY:
121                     LogDebug("call type MasterSecurityModuleCall::GET_POLICY");
122                     processGetPolicy(buffer, send);
123                     break;
124                 case MasterSecurityModuleCall::POLICY_GET_DESC:
125                     LogDebug("call type MasterSecurityModuleCall::POLICY_GET_DESC");
126                     processPolicyGetDesc(send);
127                     break;
128                 case MasterSecurityModuleCall::SMACK_INSTALL_RULES:
129                     LogDebug("call type MasterSecurityModuleCall::SMACK_INSTALL_RULES");
130                     processSmackInstallRules(buffer, send, vsmZoneId);
131                     break;
132                 case MasterSecurityModuleCall::SMACK_UNINSTALL_RULES:
133                     LogDebug("call type MasterSecurityModuleCall::SMACK_UNINSTALL_RULES");
134                     processSmackUninstallRules(buffer, send, vsmZoneId);
135                     break;
136                 default:
137                     LogError("Invalid call: " << call_type_int);
138                     Throw(MasterServiceException::InvalidAction);
139             }
140             // if we reach this point, the protocol is OK
141             retval = true;
142         } Catch (MessageBuffer::Exception::Base) {
143             LogError("Broken protocol.");
144         } Catch (MasterServiceException::Base) {
145             LogError("Broken protocol.");
146         } catch (const std::exception &e) {
147             LogError("STD exception " << e.what());
148         } catch (...) {
149             LogError("Unknown exception");
150         }
151     }
152     else {
153         LogError("Wrong interface");
154     }
155
156     if (retval) {
157         //send response
158         m_serviceManager->Write(conn, send.Pop());
159     } else {
160         LogError("Closing socket because of error");
161         m_serviceManager->Close(conn);
162     }
163
164     return retval;
165 }
166
167 void MasterService::processCynaraUpdatePolicy(MessageBuffer &buffer, MessageBuffer &send,
168         const std::string &zoneId)
169 {
170     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
171     std::string appId;
172     std::string uidstr;
173     std::vector<std::string> oldAppPrivileges, newAppPrivileges;
174     std::string appLabel, newLabel;
175
176     Deserialization::Deserialize(buffer, appId);
177     Deserialization::Deserialize(buffer, uidstr);
178     Deserialization::Deserialize(buffer, oldAppPrivileges);
179     Deserialization::Deserialize(buffer, newAppPrivileges);
180
181     appLabel = zoneSmackLabelGenerate(SmackLabels::generateAppLabel(appId), zoneId);
182
183     try {
184         CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, uidstr, oldAppPrivileges,
185                                                    newAppPrivileges);
186     } catch (const CynaraException::Base &e) {
187         LogError("Error while setting Cynara rules for application: " << e.DumpToString());
188         goto out;
189     } catch (const std::bad_alloc &e) {
190         LogError("Memory allocation while setting Cynara rules for application: " << e.what());
191         ret = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
192         goto out;
193     }
194
195     ret = SECURITY_MANAGER_API_SUCCESS;
196
197 out:
198     Serialization::Serialize(send, ret);
199 }
200
201 void MasterService::processCynaraUserInit(MessageBuffer &buffer, MessageBuffer &send)
202 {
203     int ret = SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
204     uid_t uidAdded;
205     int userType;
206
207     Deserialization::Deserialize(buffer, uidAdded);
208     Deserialization::Deserialize(buffer, userType);
209
210     try {
211         CynaraAdmin::getInstance().UserInit(uidAdded,
212                                             static_cast<security_manager_user_type>(userType));
213     } catch (CynaraException::InvalidParam &e) {
214         goto out;
215     }
216
217     ret = SECURITY_MANAGER_API_SUCCESS;
218 out:
219     Serialization::Serialize(send, ret);
220 }
221
222 void MasterService::processCynaraUserRemove(MessageBuffer &buffer, MessageBuffer &send)
223 {
224     int ret = SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
225     uid_t uidDeleted;
226
227     Deserialization::Deserialize(buffer, uidDeleted);
228
229     try {
230         CynaraAdmin::getInstance().UserRemove(uidDeleted);
231     } catch (CynaraException::InvalidParam &e) {
232         goto out;
233     }
234
235     ret = SECURITY_MANAGER_API_SUCCESS;
236 out:
237     Serialization::Serialize(send, ret);
238 }
239
240 void MasterService::processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send)
241 {
242     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
243     std::vector<policy_entry> policyEntries;
244     uid_t uid;
245     pid_t pid;
246     std::string smackLabel;
247
248     Deserialization::Deserialize(buffer, policyEntries);
249     Deserialization::Deserialize(buffer, uid);
250     Deserialization::Deserialize(buffer, pid);
251     Deserialization::Deserialize(buffer, smackLabel);
252
253     ret = serviceImpl.policyUpdate(policyEntries, uid, pid, smackLabel);
254     Serialization::Serialize(send, ret);
255 }
256
257 void MasterService::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send)
258 {
259     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
260     bool forAdmin;
261     policy_entry filter;
262     uid_t uid;
263     pid_t pid;
264     std::string smackLabel;
265     std::vector<policy_entry> policyEntries;
266
267     Deserialization::Deserialize(buffer, forAdmin);
268     Deserialization::Deserialize(buffer, filter);
269     Deserialization::Deserialize(buffer, uid);
270     Deserialization::Deserialize(buffer, pid);
271     Deserialization::Deserialize(buffer, smackLabel);
272
273     ret = serviceImpl.getConfiguredPolicy(forAdmin, filter, uid, pid, smackLabel, policyEntries);
274     Serialization::Serialize(send, ret);
275     if (ret == SECURITY_MANAGER_API_SUCCESS)
276         Serialization::Serialize(send, policyEntries);
277 }
278
279 void MasterService::processGetPolicy(MessageBuffer &buffer, MessageBuffer &send)
280 {
281     (void) buffer;
282     int ret = SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
283
284     // FIXME getPolicy is not ready to work in Master mode. Uncomment below code when getPolicy will
285     //       be implemented for Master.
286     /*
287     policy_entry filter;
288     uid_t uid;
289     pid_t pid;
290     std::string smackLabel;
291     std::vector<policy_entry> policyEntries;
292
293     Deserialization::Deserialize(buffer, filter);
294     Deserialization::Deserialize(buffer, uid);
295     Deserialization::Deserialize(buffer, pid);
296     Deserialization::Deserialize(buffer, smackLabel);
297
298     ret = serviceImpl.getPolicy(filter, uid, pid, smackLabel, policyEntries);*/
299     Serialization::Serialize(send, ret);
300     /*if (ret == SECURITY_MANAGER_API_SUCCESS)
301         Serialization::Serialize(send, policyEntries);*/
302 }
303
304 void MasterService::processPolicyGetDesc(MessageBuffer &send)
305 {
306     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
307     std::vector<std::string> descriptions;
308
309     ret = serviceImpl.policyGetDesc(descriptions);
310     Serialization::Serialize(send, ret);
311     if (ret == SECURITY_MANAGER_API_SUCCESS)
312         Serialization::Serialize(send, descriptions);
313 }
314
315 void MasterService::processSmackInstallRules(MessageBuffer &buffer, MessageBuffer &send,
316                                              const std::string &zoneId)
317 {
318     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
319     std::string appId, pkgId;
320     std::vector<std::string> pkgContents;
321
322     Deserialization::Deserialize(buffer, appId);
323     Deserialization::Deserialize(buffer, pkgId);
324     Deserialization::Deserialize(buffer, pkgContents);
325
326     try {
327         LogDebug("Adding Smack rules for new appId: " << appId << " with pkgId: "
328                 << pkgId << ". Applications in package: " << pkgContents.size());
329         SmackRules::installApplicationRules(appId, pkgId, pkgContents, zoneId);
330
331         // FIXME implement zoneSmackLabelMap and check if works when Smack Namespaces are implemented
332         std::string zoneAppLabel = SmackLabels::generateAppLabel(appId);
333         std::string zonePkgLabel = SmackLabels::generatePkgLabel(pkgId);
334         std::string hostAppLabel = zoneSmackLabelGenerate(zoneAppLabel, zoneId);
335         std::string hostPkgLabel = zoneSmackLabelGenerate(zonePkgLabel, zoneId);
336
337         if (!zoneSmackLabelMap(hostAppLabel, zoneId, zoneAppLabel)) {
338             LogError("Failed to apply Smack label mapping for application " << appId);
339             goto out;
340         }
341
342         if (!zoneSmackLabelMap(hostPkgLabel, zoneId, zonePkgLabel)) {
343             LogError("Failed to apply Smack label mapping for package " << pkgId);
344             goto out;
345         }
346     } catch (const SmackException::Base &e) {
347         LogError("Error while adding Smack rules for application: " << e.DumpToString());
348         ret = SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
349         goto out;
350     } catch (const std::bad_alloc &e) {
351         LogError("Memory allocation error: " << e.what());
352         ret =  SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
353         goto out;
354     }
355
356     ret = SECURITY_MANAGER_API_SUCCESS;
357 out:
358     Serialization::Serialize(send, ret);
359 }
360
361 void MasterService::processSmackUninstallRules(MessageBuffer &buffer, MessageBuffer &send,
362                                                const std::string &zoneId)
363 {
364     int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
365     std::string appId, pkgId;
366     std::vector<std::string> pkgContents;
367     bool removePkg = false;
368
369     Deserialization::Deserialize(buffer, appId);
370     Deserialization::Deserialize(buffer, pkgId);
371     Deserialization::Deserialize(buffer, pkgContents);
372     Deserialization::Deserialize(buffer, removePkg);
373
374     try {
375         if (removePkg) {
376             LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
377             SmackRules::uninstallPackageRules(pkgId);
378         }
379
380         LogDebug ("Removing smack rules for deleted appId " << appId);
381         SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents, zoneId);
382
383         // FIXME implement zoneSmackLabelUnmap and check if works when Smack Namespaces are implemented
384         std::string zoneAppLabel = SmackLabels::generateAppLabel(appId);
385         std::string zonePkgLabel = SmackLabels::generatePkgLabel(pkgId);
386         std::string hostAppLabel = zoneSmackLabelGenerate(zoneAppLabel, zoneId);
387         std::string hostPkgLabel = zoneSmackLabelGenerate(zonePkgLabel, zoneId);
388
389         if (!zoneSmackLabelUnmap(hostAppLabel, zoneId)) {
390             LogError("Failed to unmap Smack labels for application " << appId);
391             goto out;
392         }
393
394         if (removePkg) {
395             if (!zoneSmackLabelUnmap(hostPkgLabel, zoneId)) {
396                 LogError("Failed to unmap Smack label for package " << pkgId);
397                 goto out;
398             }
399         }
400     } catch (const SmackException::Base &e) {
401         LogError("Error while removing Smack rules for application: " << e.DumpToString());
402         ret = SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
403         goto out;
404     } catch (const std::bad_alloc &e) {
405         LogError("Memory allocation error: " << e.what());
406         ret =  SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
407         goto out;
408     }
409
410     ret = SECURITY_MANAGER_API_SUCCESS;
411 out:
412     Serialization::Serialize(send, ret);
413 }
414
415 } // namespace SecurityManager