Change smack labeling to be appId based.
[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
42 #include <protocols.h>
43
44 IMPLEMENT_SAFE_SINGLETON(SecurityManager::Log::LogSystem);
45
46 namespace {
47
48 const int POLL_TIMEOUT = 2000;
49
50 void securityClientEnableLogSystem(void) {
51     SecurityManager::Singleton<SecurityManager::Log::LogSystem>::Instance().SetTag("SECURITY_MANAGER_CLIENT");
52 }
53
54 int waitForSocket(int sock, int event, int timeout) {
55     int retval;
56     pollfd desc[1];
57     desc[0].fd = sock;
58     desc[0].events = event;
59
60     while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
61         timeout >>= 1;
62         errno = 0;
63     }
64
65     if (0 == retval) {
66         LogDebug("Poll timeout");
67     } else if (-1 == retval) {
68         int err = errno;
69         LogError("Error in poll: " << strerror(err));
70     }
71     return retval;
72 }
73
74 class SockRAII {
75 public:
76     SockRAII()
77       : m_sock(-1)
78     {}
79
80     virtual ~SockRAII() {
81         if (m_sock > -1)
82             close(m_sock);
83     }
84
85     int Connect(char const * const interface) {
86         sockaddr_un clientAddr;
87         int flags;
88
89         if (m_sock != -1) // guard
90             close(m_sock);
91
92         m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
93         if (m_sock < 0) {
94             int err = errno;
95             LogError("Error creating socket: " << strerror(err));
96             return SECURITY_MANAGER_API_ERROR_SOCKET;
97         }
98
99         if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
100             fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
101         {
102             int err = errno;
103             LogError("Error in fcntl: " << strerror(err));
104             return SECURITY_MANAGER_API_ERROR_SOCKET;
105         }
106
107         memset(&clientAddr, 0, sizeof(clientAddr));
108
109         clientAddr.sun_family = AF_UNIX;
110
111         if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
112             LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
113             return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
114         }
115
116         strcpy(clientAddr.sun_path, interface);
117
118         LogDebug("ClientAddr.sun_path = " << interface);
119
120         int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
121         if ((retval == -1) && (errno == EINPROGRESS)) {
122             if (0 >= waitForSocket(m_sock, POLLOUT, POLL_TIMEOUT)) {
123                 LogError("Error in waitForSocket.");
124                 return SECURITY_MANAGER_API_ERROR_SOCKET;
125             }
126             int error = 0;
127             socklen_t len = sizeof(error);
128             retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len);
129
130             if (-1 == retval) {
131                 int err = errno;
132                 LogError("Error in getsockopt: " << strerror(err));
133                 return SECURITY_MANAGER_API_ERROR_SOCKET;
134             }
135
136             if (error == EACCES) {
137                 LogError("Access denied");
138                 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
139             }
140
141             if (error != 0) {
142                 LogError("Error in connect: " << strerror(error));
143                 return SECURITY_MANAGER_API_ERROR_SOCKET;
144             }
145
146             return SECURITY_MANAGER_API_SUCCESS;
147         }
148
149         if (-1 == retval) {
150             int err = errno;
151             LogError("Error connecting socket: " << strerror(err));
152             if (err == EACCES)
153                 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
154             if (err == ENOTSOCK)
155                 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
156             return SECURITY_MANAGER_API_ERROR_SOCKET;
157         }
158
159         return SECURITY_MANAGER_API_SUCCESS;
160     }
161
162     int Get() {
163         return m_sock;
164     }
165
166 private:
167     int m_sock;
168 };
169
170 } // namespace anonymous
171
172 namespace SecurityManager {
173
174 int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
175     int ret;
176     SockRAII sock;
177     ssize_t done = 0;
178     char buffer[2048];
179
180     if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
181         LogError("Error in SockRAII");
182         return ret;
183     }
184
185     while ((send.size() - done) > 0) {
186         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
187             LogError("Error in poll(POLLOUT)");
188             return SECURITY_MANAGER_API_ERROR_SOCKET;
189         }
190         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
191         if (-1 == temp) {
192             int err = errno;
193             LogError("Error in write: " << strerror(err));
194             return SECURITY_MANAGER_API_ERROR_SOCKET;
195         }
196         done += temp;
197     }
198
199     do {
200         if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
201             LogError("Error in poll(POLLIN)");
202             return SECURITY_MANAGER_API_ERROR_SOCKET;
203         }
204         ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
205         if (-1 == temp) {
206             int err = errno;
207             LogError("Error in read: " << strerror(err));
208             return SECURITY_MANAGER_API_ERROR_SOCKET;
209         }
210
211         if (0 == temp) {
212             LogError("Read return 0/Connection closed by server(?)");
213             return SECURITY_MANAGER_API_ERROR_SOCKET;
214         }
215
216         RawBuffer raw(buffer, buffer+temp);
217         recv.Push(raw);
218     } while(!recv.Ready());
219     return SECURITY_MANAGER_API_SUCCESS;
220 }
221
222 int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) {
223     int ret;
224     SockRAII sock;
225     ssize_t done = 0;
226
227     if (SECURITY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
228         LogError("Error in SockRAII");
229         return ret;
230     }
231
232     while ((send.size() - done) > 0) {
233         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
234             LogError("Error in poll(POLLOUT)");
235             return SECURITY_MANAGER_API_ERROR_SOCKET;
236         }
237         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
238         if (-1 == temp) {
239             int err = errno;
240             LogError("Error in write: " << strerror(err));
241             return SECURITY_MANAGER_API_ERROR_SOCKET;
242         }
243         done += temp;
244     }
245
246     if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
247         LogError("Error in poll(POLLIN)");
248         return SECURITY_MANAGER_API_ERROR_SOCKET;
249     }
250
251     ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC));
252
253     if (temp < 0) {
254         int err = errno;
255         LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err);
256         return SECURITY_MANAGER_API_ERROR_SOCKET;
257     }
258
259     if (0 == temp) {
260         LogError("Read return 0/Connection closed by server(?)");
261         return SECURITY_MANAGER_API_ERROR_SOCKET;
262     }
263
264     return SECURITY_MANAGER_API_SUCCESS;
265 }
266
267 int try_catch(const std::function<int()>& func)
268 {
269     try {
270         return func();
271     } catch (MessageBuffer::Exception::Base &e) {
272         LogError("SecurityManager::MessageBuffer::Exception " << e.DumpToString());
273     } catch (std::exception &e) {
274         LogError("STD exception " << e.what());
275     } catch (...) {
276         LogError("Unknown exception occured");
277     }
278     return SECURITY_MANAGER_API_ERROR_UNKNOWN;
279 }
280
281 } // namespace SecurityMANAGER
282
283 static void init_lib(void) __attribute__ ((constructor));
284 static void init_lib(void)
285 {
286     securityClientEnableLogSystem();
287 }
288
289 static void fini_lib(void) __attribute__ ((destructor));
290 static void fini_lib(void)
291 {
292
293 }
294