2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file security_socket_service.cpp
18 * @author Zofia Abramowska (z.abramowska@samsung.com)
20 * @brief Implementation of socket server
23 #include <sys/types.h>
24 #include <sys/socket.h>
26 #include <sys/signalfd.h>
27 #include <sys/select.h>
32 #include <dpl/log/log.h>
33 #include "ace_service_callbacks_api.h"
34 #include "ocsp_service_callbacks_api.h"
35 #include "popup_service_callbacks_api.h"
36 #include "security_daemon_socket_config.h"
37 #include "security_socket_service.h"
40 #define TIMEOUT_NSEC 100000000
42 #define SIGNAL_TO_CLOSE SIGUSR1
44 void SecuritySocketService::throwWithErrnoMessage(const std::string& specificInfo){
45 LogError(specificInfo << " : " << strerror(errno));
46 ThrowMsg(DPL::Exception, specificInfo << " : " << strerror(errno));
49 void SecuritySocketService::registerServiceCallback(const std::string &interfaceName,
50 const std::string &methodName,
51 socketServerCallback callbackMethod,
52 securityCheck securityMethod){
53 if(NULL == callbackMethod){
54 LogError("Null callback");
55 ThrowMsg(DPL::Exception, "Null callback");
57 if(interfaceName.empty() || methodName.empty()){
58 LogError("Interface and method name cannot be empty");
59 ThrowMsg(DPL::Exception, "Empty interface or method name");
62 auto serviceCallbackPtr = std::make_shared<ServiceCallback>(ServiceCallback(callbackMethod, securityMethod));
63 m_callbackMap[interfaceName][methodName] = serviceCallbackPtr;
66 void SecuritySocketService::addClientSocket(int clientSocket){
67 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
68 m_clientSocketList.push_back(clientSocket);
71 void SecuritySocketService::removeClientSocket(int clientSocket){
72 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
73 m_clientSocketList.remove(clientSocket);
76 bool SecuritySocketService::popClientSocket(int * clientSocket){
77 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
78 if(m_clientSocketList.empty())
80 *clientSocket = m_clientSocketList.front();
81 m_clientSocketList.pop_front();
85 void SecuritySocketService::initialize(){
87 LogInfo("Initializing...");
88 m_serverAddress = WrtSecurity::SecurityDaemonSocketConfig::SERVER_ADDRESS();
89 m_signalToClose = SIGNAL_TO_CLOSE;
91 //registering Ace callbacks
92 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
93 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().first,
94 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().second);
96 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
97 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_INSTALL_METHOD_CALLBACK().first,
98 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_INSTALL_METHOD_CALLBACK().second);
100 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
101 WrtSecurity::AceServiceCallbacksApi::UPDATE_POLICY_METHOD_CALLBACK().first,
102 WrtSecurity::AceServiceCallbacksApi::UPDATE_POLICY_METHOD_CALLBACK().second);
103 LogInfo("Registered Ace callbacks");
105 //registering Ocsp callbacks
106 registerServiceCallback(WrtSecurity::OcspServerApi::INTERFACE_NAME(),
107 WrtSecurity::OcspServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().first,
108 WrtSecurity::OcspServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().second);
109 LogInfo("Registered Ocsp callbacks");
111 //registering Popup callbacks
112 registerServiceCallback(WrtSecurity::PopupServerApi::INTERFACE_NAME(),
113 WrtSecurity::PopupServiceCallbacksApi::VALIDATION_METHOD_CALLBACK().first,
114 WrtSecurity::PopupServiceCallbacksApi::VALIDATION_METHOD_CALLBACK().second);
115 LogInfo("Registered Popup callbacks");
117 if(-1 == (m_listenFd = socket(AF_UNIX, SOCK_STREAM, 0))){
118 throwWithErrnoMessage("socket()");
120 LogInfo("Server socket created");
122 //socket needs to be nonblocking, because read can block after select
124 if (-1 == (flags = fcntl(m_listenFd, F_GETFL, 0)))
126 if(-1 == (fcntl(m_listenFd, F_SETFL, flags | O_NONBLOCK))){
127 throwWithErrnoMessage("fcntl");
130 sockaddr_un server_address;
131 bzero(&server_address, sizeof(server_address));
132 server_address.sun_family = AF_UNIX;
133 strcpy(server_address.sun_path, m_serverAddress.c_str());
134 unlink(server_address.sun_path);
136 mode_t socket_umask, original_umask;
138 original_umask = umask(socket_umask);
140 if(-1 == bind(m_listenFd, (struct sockaddr *)&server_address, SUN_LEN(&server_address))){
141 throwWithErrnoMessage("bind()");
144 umask(original_umask);
146 LogInfo("Initialized");
149 void SecuritySocketService::start(){
151 LogInfo("Starting...");
152 if(m_serverAddress.empty()){
153 LogError("Server not initialized");
154 ThrowMsg(DPL::Exception, "Server not initialized");
158 sigemptyset(&sigset);
159 if(-1 == sigaddset(&sigset, m_signalToClose)){
160 throwWithErrnoMessage("sigaddset()");
163 if ((returned_value = pthread_sigmask(SIG_BLOCK, &sigset, NULL)) < 0) {
164 errno = returned_value;
165 throwWithErrnoMessage("pthread_sigmask()");
168 pthread_t mainThread;
170 if((returned_value = pthread_create(&mainThread, NULL, &serverThread, this)) < 0){
171 errno = returned_value;
172 throwWithErrnoMessage("pthread_create()");
174 m_mainThread = mainThread;
179 void * SecuritySocketService::serverThread(void * data){
180 pthread_detach(pthread_self());
181 SecuritySocketService &t = *static_cast<SecuritySocketService *>(data);
182 LogInfo("Running server main thread");
185 } Catch (DPL::Exception) {
186 LogError("Socket server error. Exiting...");
194 void SecuritySocketService::mainLoop(){
196 if(listen(m_listenFd, MAX_LISTEN) == -1){
197 throwWithErrnoMessage("listen()");
200 //Settings to catch closing signal in select
203 if(-1 == (sigemptyset(&sigset))){
204 throwWithErrnoMessage("sigemptyset()");
206 if(-1 == (sigaddset(&sigset, m_signalToClose))) {
207 throwWithErrnoMessage("sigaddset()");
209 if((signal_fd = signalfd(-1, &sigset, 0)) < 0){
210 throwWithErrnoMessage("signalfd()");
213 //Setting descriptors for pselect
217 FD_SET(m_listenFd, &allset);
218 FD_SET(signal_fd, &allset);
220 maxfd = (m_listenFd > signal_fd) ? (m_listenFd) : (signal_fd);
222 //this will block SIGPIPE for this thread and every thread created in it
223 //reason : from here on we don't won't to receive SIGPIPE on writing to closed socket
224 //instead of signal we want to receive error from write - hence blocking SIGPIPE
227 sigaddset(&set, SIGPIPE);
228 pthread_sigmask(SIG_BLOCK, &set, NULL);
231 timeout.tv_sec = TIMEOUT_SEC;
232 timeout.tv_nsec = TIMEOUT_NSEC;
234 if(-1 == pselect(maxfd, &rset, NULL, NULL, &timeout, NULL)){
236 throwWithErrnoMessage("pselect()");
239 if(FD_ISSET(signal_fd, &rset)){
240 LogInfo("Got signal to close");
241 signalfd_siginfo siginfo;
243 res = read(signal_fd, &siginfo, sizeof(siginfo));
246 throwWithErrnoMessage("read()");
248 if((size_t)res != sizeof(siginfo)){
250 LogError("couldn't read whole siginfo");
251 ThrowMsg(DPL::Exception, "couldn't read whole siginfo");
253 if((int)siginfo.ssi_signo == m_signalToClose){
254 LogInfo("Server thread got signal to close");
258 LogInfo("Got not handled signal");
261 if(FD_ISSET(m_listenFd, &rset)){
263 if(-1 == (client_fd = accept(m_listenFd, NULL, NULL))){
265 throwWithErrnoMessage("accept()");
267 LogInfo("Got incoming connection");
268 Connection_Info * connection = new Connection_Info(client_fd, (void *)this);
270 pthread_t client_thread;
271 if((res = pthread_create(&client_thread, NULL, &connectionThread, connection)) < 0){
275 throwWithErrnoMessage("pthread_create()");
277 addClientSocket(client_fd);
282 void * SecuritySocketService::connectionThread(void * data){
283 pthread_detach(pthread_self());
284 std::auto_ptr<Connection_Info> c (static_cast<Connection_Info *>(data));
285 SecuritySocketService &t = *static_cast<SecuritySocketService *>(c->data);
286 LogInfo("Starting connection thread");
288 t.connectionService(c->connfd);
289 } Catch (DPL::Exception){
290 LogError("Connection thread error : " << _rethrown_exception.DumpToString());
291 t.removeClientSocket(c->connfd);
295 LogInfo("Client serviced");
299 void SecuritySocketService::connectionService(int fd){
301 SocketConnection connector = SocketConnection(fd);
302 std::string interfaceName, methodName;
305 connector.read(&interfaceName, &methodName);
306 } Catch (SocketConnection::Exception::SocketConnectionException){
307 LogError("Socket Connection read error");
308 ReThrowMsg(DPL::Exception, "Socket Connection read error");
311 LogDebug("Got interface : " << interfaceName);
312 LogDebug("Got method : " << methodName);
314 if( m_callbackMap.find(interfaceName) == m_callbackMap.end()){
315 LogError("Unknown interface : " << interfaceName);
316 ThrowMsg(DPL::Exception, "Unknown interface : " << interfaceName);
319 if(m_callbackMap[interfaceName].find(methodName) == m_callbackMap[interfaceName].end()){
320 LogError("Unknown method : " << methodName);
321 ThrowMsg(DPL::Exception, "Unknown method");
324 if(m_callbackMap[interfaceName][methodName]->securityCallback != NULL){
325 if(!m_callbackMap[interfaceName][methodName]->securityCallback(fd)){
326 LogError("Security check returned false");
327 ThrowMsg(DPL::Exception, "Security check returned false");
331 LogInfo("Calling service");
333 m_callbackMap[interfaceName][methodName]->serviceCallback(&connector);
334 } Catch (ServiceCallbackApi::Exception::ServiceCallbackException){
335 LogError("Service callback error");
336 ReThrowMsg(DPL::Exception, "Service callback error");
339 LogInfo("Removing client");
340 removeClientSocket(fd);
343 LogInfo("Call served");
347 void SecuritySocketService::stop(){
349 if(-1 == close(m_listenFd))
350 if(errno != ENOTCONN)
351 throwWithErrnoMessage("close()");
353 if((returned_value = pthread_kill(m_mainThread, m_signalToClose)) < 0){
354 errno = returned_value;
355 throwWithErrnoMessage("pthread_kill()");
357 pthread_join(m_mainThread, NULL);
362 void SecuritySocketService::closeConnections(){
365 LogInfo("Closing client sockets");
366 while(popClientSocket(&clientSocket)){
367 if(-1 == close(clientSocket)){
368 LogError("close() : " << strerror(errno));
372 LogInfo("Connections closed");
375 void SecuritySocketService::deinitialize(){
376 m_serverAddress.clear();
378 LogInfo("Deinitialized");
382 #ifdef SOCKET_CONNECTION
383 DAEMON_REGISTER_SERVICE_MODULE(SecuritySocketService)