a7a183f2d9bf27e68d10c2d94a00070fad9510c5
[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 #include <client-common.h>
41
42 IMPLEMENT_SAFE_SINGLETON(CKM::Log::LogSystem);
43
44 namespace {
45
46 const int POLL_TIMEOUT = 8000;
47
48 void centKeyClientEnableLogSystem(void) {
49     CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CKM_CLIENT");
50 }
51
52 int waitForSocket(int sock, int event, int timeout) {
53     int retval;
54     pollfd desc[1];
55     desc[0].fd = sock;
56     desc[0].events = event;
57
58     while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
59         timeout >>= 1;
60         errno = 0;
61     }
62
63     if (0 == retval) {
64         LogDebug("Poll timeout");
65     } else if (-1 == retval) {
66         int err = errno;
67         LogError("Error in poll: " << strerror(err));
68     }
69     return retval;
70 }
71
72 } // namespace anonymous
73
74 namespace CKM {
75
76
77 int connectSocket(int& sock, char const * const interface) {
78     sockaddr_un clientAddr;
79     int flags;
80
81     if (sock != -1) // guard
82         close(sock);
83
84     sock = socket(AF_UNIX, SOCK_STREAM, 0);
85     if (sock < 0) {
86         int err = errno;
87         LogError("Error creating socket: " << strerror(err));
88         return CKM_API_ERROR_SOCKET;
89     }
90
91     if ((flags = fcntl(sock, F_GETFL, 0)) < 0 ||
92         fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
93     {
94         int err = errno;
95         LogError("Error in fcntl: " << strerror(err));
96         return CKM_API_ERROR_SOCKET;
97     }
98
99     memset(&clientAddr, 0, sizeof(clientAddr));
100
101     clientAddr.sun_family = AF_UNIX;
102
103     if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
104         LogError("Error: interface name " << interface << "is too long. Max len is:" <<
105                  sizeof(clientAddr.sun_path));
106         return CKM_API_ERROR_SOCKET;
107     }
108
109     strcpy(clientAddr.sun_path, interface);
110
111     LogDebug("ClientAddr.sun_path = " << interface);
112
113     int retval = TEMP_FAILURE_RETRY(
114         connect(sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
115     if ((retval == -1) && (errno == EINPROGRESS)) {
116         if (0 >= waitForSocket(sock, POLLOUT, POLL_TIMEOUT)) {
117             LogError("Error in waitForSocket.");
118             return CKM_API_ERROR_SOCKET;
119         }
120         int error = 0;
121         socklen_t len = sizeof(error);
122         retval = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len);
123
124         if (-1 == retval) {
125             int err = errno;
126             LogError("Error in getsockopt: " << strerror(err));
127             return CKM_API_ERROR_SOCKET;
128         }
129
130         if (error == EACCES) {
131             LogError("Access denied");
132             return CKM_API_ERROR_ACCESS_DENIED;
133         }
134
135         if (error != 0) {
136             LogError("Error in connect: " << strerror(error));
137             return CKM_API_ERROR_SOCKET;
138         }
139
140         return CKM_API_SUCCESS;
141     }
142
143     if (-1 == retval) {
144         int err = errno;
145         LogError("Error connecting socket: " << strerror(err));
146         if (err == EACCES)
147             return CKM_API_ERROR_ACCESS_DENIED;
148         return CKM_API_ERROR_SOCKET;
149     }
150
151     return CKM_API_SUCCESS;
152 }
153
154 int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
155     int ret;
156     SockRAII sock;
157     ssize_t done = 0;
158     char buffer[2048];
159
160     if (CKM_API_SUCCESS != (ret = sock.Connect(interface))) {
161         LogError("Error in SockRAII");
162         return ret;
163     }
164
165     while ((send.size() - done) > 0) {
166         if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
167             LogError("Error in poll(POLLOUT)");
168             return CKM_API_ERROR_SOCKET;
169         }
170         ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
171         if (-1 == temp) {
172             int err = errno;
173             LogError("Error in write: " << strerror(err));
174             return CKM_API_ERROR_SOCKET;
175         }
176         done += temp;
177     }
178
179     do {
180         if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
181             LogError("Error in poll(POLLIN)");
182             return CKM_API_ERROR_SOCKET;
183         }
184         ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
185         if (-1 == temp) {
186             int err = errno;
187             LogError("Error in read: " << strerror(err));
188             return CKM_API_ERROR_SOCKET;
189         }
190
191         if (0 == temp) {
192             LogError("Read return 0/Connection closed by server(?)");
193             return CKM_API_ERROR_SOCKET;
194         }
195
196         RawBuffer raw(buffer, buffer+temp);
197         recv.Push(raw);
198     } while(!recv.Ready());
199     return CKM_API_SUCCESS;
200 }
201
202 int try_catch(const std::function<int()>& func)
203 {
204     try {
205         return func();
206     } catch (MessageBuffer::Exception::Base &e) {
207         LogError("CKM::MessageBuffer::Exception " << e.DumpToString());
208     } catch (std::exception &e) {
209         LogError("STD exception " << e.what());
210     } catch (...) {
211         LogError("Unknown exception occured");
212     }
213     return CKM_API_ERROR_UNKNOWN;
214 }
215
216 } // namespace CKM
217
218 static void init_lib(void) __attribute__ ((constructor));
219 static void init_lib(void)
220 {
221     centKeyClientEnableLogSystem();
222 }
223
224 static void fini_lib(void) __attribute__ ((destructor));
225 static void fini_lib(void)
226 {
227
228 }
229