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