Replace RawData with RawBuffer.
[platform/core/security/key-manager.git] / src / manager / client / client-common.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file        client-common.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @author      Zofia Abramowska (z.abramowska@samsung.com)
20  * @version     1.0
21  * @brief       This file is implementation of client-common functions.
22  */
23
24 #include <fcntl.h>
25 #include <poll.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30
31 #include <dpl/log/log.h>
32 #include <dpl/serialization.h>
33 #include <dpl/singleton.h>
34 #include <dpl/singleton_safe_impl.h>
35
36 #include <message-buffer.h>
37
38 #include <ckm/ckm-error.h>
39
40 IMPLEMENT_SAFE_SINGLETON(CKM::Log::LogSystem);
41
42 namespace {
43
44 const int POLL_TIMEOUT = 2000;
45
46 void centKeyClientEnableLogSystem(void) {
47     CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CENT_KEY_CLIENT");
48 }
49
50 int waitForSocket(int sock, int event, int timeout) {
51     int retval;
52     pollfd desc[1];
53     desc[0].fd = sock;
54     desc[0].events = event;
55
56     while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
57         timeout >>= 1;
58         errno = 0;
59     }
60
61     if (0 == retval) {
62         LogDebug("Poll timeout");
63     } else if (-1 == retval) {
64         int err = errno;
65         LogError("Error in poll: " << strerror(err));
66     }
67     return retval;
68 }
69
70 class SockRAII {
71 public:
72     SockRAII()
73       : m_sock(-1)
74     {}
75
76     virtual ~SockRAII() {
77         if (m_sock > -1)
78             close(m_sock);
79     }
80
81     int Connect(char const * const interface) {
82         sockaddr_un clientAddr;
83         int flags;
84
85         if (m_sock != -1) // guard
86             close(m_sock);
87
88         m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
89         if (m_sock < 0) {
90             int err = errno;
91             LogError("Error creating socket: " << strerror(err));
92             return KEY_MANAGER_API_ERROR_SOCKET;
93         }
94
95         if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
96             fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
97         {
98             int err = errno;
99             LogError("Error in fcntl: " << strerror(err));
100             return KEY_MANAGER_API_ERROR_SOCKET;
101         }
102
103         memset(&clientAddr, 0, sizeof(clientAddr));
104
105         clientAddr.sun_family = AF_UNIX;
106
107         if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
108             LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
109             return KEY_MANAGER_API_ERROR_SOCKET;
110         }
111
112         strcpy(clientAddr.sun_path, interface);
113
114         LogDebug("ClientAddr.sun_path = " << interface);
115
116         int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
117         if ((retval == -1) && (errno == EINPROGRESS)) {
118             if (0 >= waitForSocket(m_sock, POLLIN, POLL_TIMEOUT)) {
119                 LogError("Error in waitForSocket.");
120                 return KEY_MANAGER_API_ERROR_SOCKET;
121             }
122             int error = 0;
123             size_t len = sizeof(error);
124             retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len);
125
126             if (-1 == retval) {
127                 int err = errno;
128                 LogError("Error in getsockopt: " << strerror(err));
129                 return KEY_MANAGER_API_ERROR_SOCKET;
130             }
131
132             if (error == EACCES) {
133                 LogError("Access denied");
134                 return KEY_MANAGER_API_ERROR_ACCESS_DENIED;
135             }
136
137             if (error != 0) {
138                 LogError("Error in connect: " << strerror(error));
139                 return KEY_MANAGER_API_ERROR_SOCKET;
140             }
141
142             return KEY_MANAGER_API_SUCCESS;
143         }
144
145         if (-1 == retval) {
146             int err = errno;
147             LogError("Error connecting socket: " << strerror(err));
148             if (err == EACCES)
149                 return KEY_MANAGER_API_ERROR_ACCESS_DENIED;
150             return KEY_MANAGER_API_ERROR_SOCKET;
151         }
152
153         return KEY_MANAGER_API_SUCCESS;
154     }
155
156     int Get() {
157         return m_sock;
158     }
159
160 private:
161     int m_sock;
162 };
163
164 } // namespace anonymous
165
166 namespace CKM {
167
168
169 int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
170     int ret;
171     SockRAII sock;
172     ssize_t done = 0;
173     char buffer[2048];
174
175     if (KEY_MANAGER_API_SUCCESS != (ret = sock.Connect(interface))) {
176         LogError("Error in SockRAII");
177         return ret;
178     }
179
180     while ((send.size() - done) > 0) {
181         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
182             LogError("Error in poll(POLLOUT)");
183             return KEY_MANAGER_API_ERROR_SOCKET;
184         }
185         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
186         if (-1 == temp) {
187             int err = errno;
188             LogError("Error in write: " << strerror(err));
189             return KEY_MANAGER_API_ERROR_SOCKET;
190         }
191         done += temp;
192     }
193
194     do {
195         if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
196             LogError("Error in poll(POLLIN)");
197             return KEY_MANAGER_API_ERROR_SOCKET;
198         }
199         ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
200         if (-1 == temp) {
201             int err = errno;
202             LogError("Error in read: " << strerror(err));
203             return KEY_MANAGER_API_ERROR_SOCKET;
204         }
205
206         if (0 == temp) {
207             LogError("Read return 0/Connection closed by server(?)");
208             return KEY_MANAGER_API_ERROR_SOCKET;
209         }
210
211         RawBuffer raw(buffer, buffer+temp);
212         recv.Push(raw);
213     } while(!recv.Ready());
214     return KEY_MANAGER_API_SUCCESS;
215 }
216
217 int try_catch(const std::function<int()>& func)
218 {
219     try {
220         return func();
221     } catch (MessageBuffer::Exception::Base &e) {
222         LogError("CKM::MessageBuffer::Exception " << e.DumpToString());
223     } catch (std::exception &e) {
224         LogError("STD exception " << e.what());
225     } catch (...) {
226         LogError("Unknown exception occured");
227     }
228     return KEY_MANAGER_API_ERROR_UNKNOWN;
229 }
230
231 } // namespace CKM
232
233 static void init_lib(void) __attribute__ ((constructor));
234 static void init_lib(void)
235 {
236     centKeyClientEnableLogSystem();
237 }
238
239 static void fini_lib(void) __attribute__ ((destructor));
240 static void fini_lib(void)
241 {
242
243 }
244