a58f7b3180c5e6c39f5442ee471ad11a72926ad2
[platform/core/security/security-manager.git] / src / client / client-common.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        client-common.cpp
20  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21  * @version     1.0
22  * @brief       This file is implementation of client-common functions.
23  */
24
25 #include <fcntl.h>
26 #include <poll.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30 #include <sys/smack.h>
31 #include <sys/xattr.h>
32 #include <linux/xattr.h>
33 #include <unistd.h>
34
35 #include <dpl/log/log.h>
36 #include <dpl/serialization.h>
37 #include <dpl/singleton.h>
38 #include <dpl/singleton_safe_impl.h>
39
40 #include <message-buffer.h>
41 #include <smack-common.h>
42
43 #include <protocols.h>
44
45 IMPLEMENT_SAFE_SINGLETON(SecurityManager::Log::LogSystem);
46
47 namespace {
48
49 const int POLL_TIMEOUT = 2000;
50
51 void securityClientEnableLogSystem(void) {
52     SecurityManager::Singleton<SecurityManager::Log::LogSystem>::Instance().SetTag("SECURITY_MANAGER_CLIENT");
53 }
54
55 int waitForSocket(int sock, int event, int timeout) {
56     int retval;
57     pollfd desc[1];
58     desc[0].fd = sock;
59     desc[0].events = event;
60
61     while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
62         timeout >>= 1;
63         errno = 0;
64     }
65
66     if (0 == retval) {
67         LogDebug("Poll timeout");
68     } else if (-1 == retval) {
69         int err = errno;
70         LogError("Error in poll: " << strerror(err));
71     }
72     return retval;
73 }
74
75 class SockRAII {
76 public:
77     SockRAII()
78       : m_sock(-1)
79     {}
80
81     virtual ~SockRAII() {
82         if (m_sock > -1)
83             close(m_sock);
84     }
85
86     int Connect(char const * const interface) {
87         sockaddr_un clientAddr;
88         int flags;
89
90         if (m_sock != -1) // guard
91             close(m_sock);
92
93         m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
94         if (m_sock < 0) {
95             int err = errno;
96             LogError("Error creating socket: " << strerror(err));
97             return SECURITY_MANAGER_API_ERROR_SOCKET;
98         }
99
100         if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
101             fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
102         {
103             int err = errno;
104             LogError("Error in fcntl: " << strerror(err));
105             return SECURITY_MANAGER_API_ERROR_SOCKET;
106         }
107
108         memset(&clientAddr, 0, sizeof(clientAddr));
109
110         clientAddr.sun_family = AF_UNIX;
111
112         if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
113             LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
114             return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
115         }
116
117         strcpy(clientAddr.sun_path, interface);
118
119         LogDebug("ClientAddr.sun_path = " << interface);
120
121         int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
122         if ((retval == -1) && (errno == EINPROGRESS)) {
123             if (0 >= waitForSocket(m_sock, POLLIN, POLL_TIMEOUT)) {
124                 LogError("Error in waitForSocket.");
125                 return SECURITY_MANAGER_API_ERROR_SOCKET;
126             }
127             int error = 0;
128             socklen_t len = sizeof(error);
129             retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len);
130
131             if (-1 == retval) {
132                 int err = errno;
133                 LogError("Error in getsockopt: " << strerror(err));
134                 return SECURITY_MANAGER_API_ERROR_SOCKET;
135             }
136
137             if (error == EACCES) {
138                 LogError("Access denied");
139                 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
140             }
141
142             if (error != 0) {
143                 LogError("Error in connect: " << strerror(error));
144                 return SECURITY_MANAGER_API_ERROR_SOCKET;
145             }
146
147             return SECURITY_MANAGER_API_SUCCESS;
148         }
149
150         if (-1 == retval) {
151             int err = errno;
152             LogError("Error connecting socket: " << strerror(err));
153             if (err == EACCES)
154                 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
155             if (err == ENOTSOCK)
156                 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
157             return SECURITY_MANAGER_API_ERROR_SOCKET;
158         }
159
160         return SECURITY_MANAGER_API_SUCCESS;
161     }
162
163     int Get() {
164         return m_sock;
165     }
166
167 private:
168     int m_sock;
169 };
170
171 } // namespace anonymous
172
173 namespace SecurityManager {
174
175 int getSmackLabelFromBinary(char **smackLabel, const char *path)
176 {
177     int ret;
178     struct LabelInfo {
179         const char *xattr;
180         int followSymlinks;
181     };
182     const LabelInfo labels[] = {
183             { XATTR_NAME_SMACKEXEC, 1 },
184             { XATTR_NAME_TIZENEXEC, 1 },
185             { XATTR_NAME_TIZENEXEC, 0 }
186     };
187
188     LogDebug("Entering function: " << __func__ << ". Params: smackLabel=" << smackLabel <<
189             " path=" << path);
190
191     if (smackLabel == NULL) {
192         LogError("getSmackLabelFromBinary: smackLabel is NULL");
193         return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
194     }
195
196     if (path == NULL) {
197         LogError("getSmackLabelFromBinary: path is NULL");
198         return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
199     }
200
201     for (const auto &l : labels) {
202         ret = smack_new_label_from_path(path, l.xattr, l.followSymlinks, smackLabel);
203         if (ret > 0) {
204             return SECURITY_MANAGER_API_SUCCESS;
205         }
206     }
207
208     LogError("Getting exec label from " << path << " failed");
209     return SECURITY_MANAGER_API_ERROR_GETTING_FILE_LABEL_FAILED;
210 }
211
212
213 int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
214     int ret;
215     SockRAII sock;
216     ssize_t done = 0;
217     char buffer[2048];
218
219     if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
220         LogError("Error in SockRAII");
221         return ret;
222     }
223
224     while ((send.size() - done) > 0) {
225         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
226             LogError("Error in poll(POLLOUT)");
227             return SECURITY_MANAGER_API_ERROR_SOCKET;
228         }
229         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
230         if (-1 == temp) {
231             int err = errno;
232             LogError("Error in write: " << strerror(err));
233             return SECURITY_MANAGER_API_ERROR_SOCKET;
234         }
235         done += temp;
236     }
237
238     do {
239         if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
240             LogError("Error in poll(POLLIN)");
241             return SECURITY_MANAGER_API_ERROR_SOCKET;
242         }
243         ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
244         if (-1 == temp) {
245             int err = errno;
246             LogError("Error in read: " << strerror(err));
247             return SECURITY_MANAGER_API_ERROR_SOCKET;
248         }
249
250         if (0 == temp) {
251             LogError("Read return 0/Connection closed by server(?)");
252             return SECURITY_MANAGER_API_ERROR_SOCKET;
253         }
254
255         RawBuffer raw(buffer, buffer+temp);
256         recv.Push(raw);
257     } while(!recv.Ready());
258     return SECURITY_MANAGER_API_SUCCESS;
259 }
260
261 int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) {
262     int ret;
263     SockRAII sock;
264     ssize_t done = 0;
265
266     if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
267         LogError("Error in SockRAII");
268         return ret;
269     }
270
271     while ((send.size() - done) > 0) {
272         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
273             LogError("Error in poll(POLLOUT)");
274             return SECURITY_MANAGER_API_ERROR_SOCKET;
275         }
276         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
277         if (-1 == temp) {
278             int err = errno;
279             LogError("Error in write: " << strerror(err));
280             return SECURITY_MANAGER_API_ERROR_SOCKET;
281         }
282         done += temp;
283     }
284
285     if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
286         LogError("Error in poll(POLLIN)");
287         return SECURITY_MANAGER_API_ERROR_SOCKET;
288     }
289
290     ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC));
291
292     if (temp < 0) {
293         int err = errno;
294         LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err);
295         return SECURITY_MANAGER_API_ERROR_SOCKET;
296     }
297
298     if (0 == temp) {
299         LogError("Read return 0/Connection closed by server(?)");
300         return SECURITY_MANAGER_API_ERROR_SOCKET;
301     }
302
303     return SECURITY_MANAGER_API_SUCCESS;
304 }
305
306 int try_catch(const std::function<int()>& func)
307 {
308     try {
309         return func();
310     } catch (MessageBuffer::Exception::Base &e) {
311         LogError("SecurityManager::MessageBuffer::Exception " << e.DumpToString());
312     } catch (std::exception &e) {
313         LogError("STD exception " << e.what());
314     } catch (...) {
315         LogError("Unknown exception occured");
316     }
317     return SECURITY_MANAGER_API_ERROR_UNKNOWN;
318 }
319
320 } // namespace SecurityMANAGER
321
322 static void init_lib(void) __attribute__ ((constructor));
323 static void init_lib(void)
324 {
325     securityClientEnableLogSystem();
326 }
327
328 static void fini_lib(void) __attribute__ ((destructor));
329 static void fini_lib(void)
330 {
331
332 }
333