Split service implementation logic away from the Service class
[platform/core/security/security-manager.git] / src / server / service / 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        service.cpp
20  * @author      Michal Witanowski <m.witanowski@samsung.com>
21  * @author      Jacek Bukarewicz <j.bukarewicz@samsung.com>
22  * @author      Rafal Krypa <r.krypa@samsung.com>
23  * @brief       Implementation of security-manager service.
24  */
25
26 #include <sys/socket.h>
27
28 #include <dpl/log/log.h>
29 #include <dpl/serialization.h>
30
31 #include "protocols.h"
32 #include "service.h"
33 #include "service_impl.h"
34
35 namespace SecurityManager {
36
37 const InterfaceID IFACE = 1;
38
39 Service::Service()
40 {
41 }
42
43 GenericSocketService::ServiceDescriptionVector Service::GetServiceDescription()
44 {
45     return ServiceDescriptionVector {
46         {SERVICE_SOCKET, "security-manager", IFACE},
47     };
48 }
49
50 void Service::accept(const AcceptEvent &event)
51 {
52     LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock <<
53              " ConnectionID.counter: " << event.connectionID.counter <<
54              " ServiceID: " << event.interfaceID);
55
56     auto &info = m_connectionInfoMap[event.connectionID.counter];
57     info.interfaceID = event.interfaceID;
58 }
59
60 void Service::write(const WriteEvent &event)
61 {
62     LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
63              " Size: " << event.size <<
64              " Left: " << event.left);
65
66     if (event.left == 0)
67         m_serviceManager->Close(event.connectionID);
68 }
69
70 void Service::process(const ReadEvent &event)
71 {
72     LogDebug("Read event for counter: " << event.connectionID.counter);
73     auto &info = m_connectionInfoMap[event.connectionID.counter];
74     info.buffer.Push(event.rawBuffer);
75
76     // We can get several requests in one package.
77     // Extract and process them all
78     while (processOne(event.connectionID, info.buffer, info.interfaceID));
79 }
80
81 void Service::close(const CloseEvent &event)
82 {
83     LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
84     m_connectionInfoMap.erase(event.connectionID.counter);
85 }
86
87 static bool getPeerID(int sock, uid_t &uid, pid_t &pid) {
88     struct ucred cr;
89     socklen_t len = sizeof(cr);
90
91     if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len)) {
92         uid = cr.uid;
93         pid = cr.pid;
94         return true;
95     }
96
97     return false;
98 }
99
100 bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
101                                   InterfaceID interfaceID)
102 {
103     LogDebug("Iteration begin. Interface = " << interfaceID);
104
105     //waiting for all data
106     if (!buffer.Ready()) {
107         return false;
108     }
109
110     MessageBuffer send;
111     bool retval = false;
112
113     uid_t uid;
114     pid_t pid;
115
116     if(!getPeerID(conn.sock, uid, pid)) {
117         LogError("Closing socket because of error: unable to get peer's uid and pid");
118         m_serviceManager->Close(conn);
119         return false;
120     }
121
122     if (IFACE == interfaceID) {
123         Try {
124             // deserialize API call type
125             int call_type_int;
126             Deserialization::Deserialize(buffer, call_type_int);
127             SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
128
129             switch (call_type) {
130                 case SecurityModuleCall::APP_INSTALL:
131                     LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
132                     processAppInstall(buffer, send, uid);
133                     break;
134                 case SecurityModuleCall::APP_UNINSTALL:
135                     LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
136                     processAppUninstall(buffer, send, uid);
137                     break;
138                 case SecurityModuleCall::APP_GET_PKGID:
139                     processGetPkgId(buffer, send);
140                     break;
141                 case SecurityModuleCall::APP_GET_GROUPS:
142                     processGetAppGroups(buffer, send, uid, pid);
143                     break;
144                 default:
145                     LogError("Invalid call: " << call_type_int);
146                     Throw(ServiceException::InvalidAction);
147             }
148             // if we reach this point, the protocol is OK
149             retval = true;
150         } Catch (MessageBuffer::Exception::Base) {
151             LogError("Broken protocol.");
152         } Catch (ServiceException::Base) {
153             LogError("Broken protocol.");
154         } catch (std::exception &e) {
155             LogError("STD exception " << e.what());
156         } catch (...) {
157             LogError("Unknown exception");
158         }
159     }
160     else {
161         LogError("Wrong interface");
162     }
163
164     if (retval) {
165         //send response
166         m_serviceManager->Write(conn, send.Pop());
167     } else {
168         LogError("Closing socket because of error");
169         m_serviceManager->Close(conn);
170     }
171
172     return retval;
173 }
174
175 void Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
176 {
177     app_inst_req req;
178
179     Deserialization::Deserialize(buffer, req.appId);
180     Deserialization::Deserialize(buffer, req.pkgId);
181     Deserialization::Deserialize(buffer, req.privileges);
182     Deserialization::Deserialize(buffer, req.appPaths);
183     Deserialization::Deserialize(buffer, req.uid);
184     Serialization::Serialize(send, ServiceImpl::appInstall(req, uid));
185 }
186
187 void Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
188 {
189     std::string appId;
190
191     Deserialization::Deserialize(buffer, appId);
192     Serialization::Serialize(send, ServiceImpl::appUninstall(appId, uid));
193 }
194
195 void Service::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send)
196 {
197     std::string appId;
198     std::string pkgId;
199     int ret;
200
201     Deserialization::Deserialize(buffer, appId);
202     ret = ServiceImpl::getPkgId(appId, pkgId);
203     Serialization::Serialize(send, ret);
204     if (ret == SECURITY_MANAGER_API_SUCCESS)
205         Serialization::Serialize(send, pkgId);
206 }
207
208 void Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid)
209 {
210     std::string appId;
211     std::unordered_set<gid_t> gids;
212     int ret;
213
214     Deserialization::Deserialize(buffer, appId);
215     ret = ServiceImpl::getAppGroups(appId, uid, pid, gids);
216     Serialization::Serialize(send, ret);
217     if (ret == SECURITY_MANAGER_API_SUCCESS) {
218         Serialization::Serialize(send, static_cast<int>(gids.size()));
219         for (const auto &gid : gids) {
220             Serialization::Serialize(send, gid);
221         }
222     }
223 }
224
225
226 } // namespace SecurityManager