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
22 #include <systemd/sd-daemon.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
27 #include <sys/signalfd.h>
28 #include <sys/select.h>
34 #include <dpl/log/log.h>
35 #include "ace_service_callbacks_api.h"
36 #include "ocsp_service_callbacks_api.h"
37 #include "popup_service_callbacks_api.h"
38 #include "security_daemon_socket_config.h"
39 #include "security_socket_service.h"
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 int SecuritySocketService::get_systemd_socket(std::string &path) {
87 int type = SOCK_STREAM;
93 // Gets number of created by systemd file descriptors that represent open sockets.
96 // Check open sockets count (must be 1)
100 // File descriptor calculation
101 fd = SD_LISTEN_FDS_START + 0;
103 // File descriptor veryfication.
104 if (sd_is_socket_unix(fd, type, listening, path.c_str(), length) > 0) {
105 activatedBySystemd = true;
109 // No proper socket or error
113 void SecuritySocketService::initialize(){
115 LogInfo("Initializing...");
116 m_serverAddress = WrtSecurity::SecurityDaemonSocketConfig::SERVER_ADDRESS();
117 m_signalToClose = SIGNAL_TO_CLOSE;
119 //registering Ace callbacks
120 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
121 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().first,
122 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().second);
124 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
125 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_INSTALL_METHOD_CALLBACK().first,
126 WrtSecurity::AceServiceCallbacksApi::CHECK_ACCESS_INSTALL_METHOD_CALLBACK().second);
128 registerServiceCallback(WrtSecurity::AceServerApi::INTERFACE_NAME(),
129 WrtSecurity::AceServiceCallbacksApi::UPDATE_POLICY_METHOD_CALLBACK().first,
130 WrtSecurity::AceServiceCallbacksApi::UPDATE_POLICY_METHOD_CALLBACK().second);
131 LogInfo("Registered Ace callbacks");
133 //registering Ocsp callbacks
134 registerServiceCallback(WrtSecurity::OcspServerApi::INTERFACE_NAME(),
135 WrtSecurity::OcspServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().first,
136 WrtSecurity::OcspServiceCallbacksApi::CHECK_ACCESS_METHOD_CALLBACK().second);
137 LogInfo("Registered Ocsp callbacks");
139 //registering Popup callbacks
140 registerServiceCallback(WrtSecurity::PopupServerApi::INTERFACE_NAME(),
141 WrtSecurity::PopupServiceCallbacksApi::VALIDATION_METHOD_CALLBACK().first,
142 WrtSecurity::PopupServiceCallbacksApi::VALIDATION_METHOD_CALLBACK().second);
143 LogInfo("Registered Popup callbacks");
145 // Get systemd socket
146 activatedBySystemd = false;
147 m_listenFd = get_systemd_socket(m_serverAddress);
148 if (m_listenFd >= 0) {
149 LogInfo("Initialized");
153 // Default socket initialization
154 if(-1 == (m_listenFd = socket(AF_UNIX, SOCK_STREAM, 0))){
155 throwWithErrnoMessage("socket()");
157 LogInfo("Server socket created");
159 //socket needs to be nonblocking, because read can block after select
161 if (-1 == (flags = fcntl(m_listenFd, F_GETFL, 0)))
163 if(-1 == (fcntl(m_listenFd, F_SETFL, flags | O_NONBLOCK))){
164 throwWithErrnoMessage("fcntl");
167 sockaddr_un server_address;
168 bzero(&server_address, sizeof(server_address));
169 server_address.sun_family = AF_UNIX;
170 strcpy(server_address.sun_path, m_serverAddress.c_str());
171 unlink(server_address.sun_path);
173 mode_t socket_umask, original_umask;
175 original_umask = umask(socket_umask);
177 if(-1 == bind(m_listenFd, (struct sockaddr *)&server_address, SUN_LEN(&server_address))){
178 throwWithErrnoMessage("bind()");
181 umask(original_umask);
183 LogInfo("Initialized");
186 void SecuritySocketService::start(){
188 LogInfo("Starting...");
189 if(m_serverAddress.empty()){
190 LogError("Server not initialized");
191 ThrowMsg(DPL::Exception, "Server not initialized");
195 sigemptyset(&sigset);
196 if(-1 == sigaddset(&sigset, m_signalToClose)){
197 throwWithErrnoMessage("sigaddset()");
200 if ((returned_value = pthread_sigmask(SIG_BLOCK, &sigset, NULL)) < 0) {
201 errno = returned_value;
202 throwWithErrnoMessage("pthread_sigmask()");
205 pthread_t mainThread;
206 if((returned_value = pthread_create(&mainThread, NULL, &serverThread, this)) < 0){
207 errno = returned_value;
208 throwWithErrnoMessage("pthread_create()");
210 m_mainThread = mainThread;
215 void * SecuritySocketService::serverThread(void * data){
216 pthread_detach(pthread_self());
217 SecuritySocketService &t = *static_cast<SecuritySocketService *>(data);
218 LogInfo("Running server main thread");
221 } Catch (DPL::Exception) {
222 LogError("Socket server error. Exiting...");
230 void SecuritySocketService::mainLoop(){
232 if(!activatedBySystemd && listen(m_listenFd, MAX_LISTEN) == -1){
233 throwWithErrnoMessage("listen()");
236 //Settings to catch closing signal in select
239 if(-1 == (sigemptyset(&sigset))){
240 throwWithErrnoMessage("sigemptyset()");
242 if(-1 == (sigaddset(&sigset, m_signalToClose))) {
243 throwWithErrnoMessage("sigaddset()");
245 if((signal_fd = signalfd(-1, &sigset, 0)) < 0){
246 throwWithErrnoMessage("signalfd()");
249 //Setting descriptors for pselect
253 FD_SET(m_listenFd, &allset);
254 FD_SET(signal_fd, &allset);
255 maxfd = (m_listenFd > signal_fd) ? (m_listenFd) : (signal_fd);
257 //this will block SIGPIPE for this thread and every thread created in it
258 //reason : from here on we don't won't to receive SIGPIPE on writing to closed socket
259 //instead of signal we want to receive error from write - hence blocking SIGPIPE
262 sigaddset(&set, SIGPIPE);
263 pthread_sigmask(SIG_BLOCK, &set, NULL);
267 if(-1 == pselect(maxfd, &rset, NULL, NULL, NULL, NULL)){
269 throwWithErrnoMessage("pselect()");
272 if(FD_ISSET(signal_fd, &rset)){
273 LogInfo("Got signal to close");
274 signalfd_siginfo siginfo;
276 res = read(signal_fd, &siginfo, sizeof(siginfo));
279 throwWithErrnoMessage("read()");
281 if((size_t)res != sizeof(siginfo)){
283 LogError("couldn't read whole siginfo");
284 ThrowMsg(DPL::Exception, "couldn't read whole siginfo");
286 if((int)siginfo.ssi_signo == m_signalToClose){
287 LogInfo("Server thread got signal to close");
291 LogInfo("Got not handled signal");
294 if(FD_ISSET(m_listenFd, &rset)){
296 if(-1 == (client_fd = accept(m_listenFd, NULL, NULL))){
298 throwWithErrnoMessage("accept()");
300 LogInfo("Got incoming connection");
301 Connection_Info * connection = new Connection_Info(client_fd, (void *)this);
303 pthread_t client_thread;
304 if((res = pthread_create(&client_thread, NULL, &connectionThread, connection)) < 0){
308 throwWithErrnoMessage("pthread_create()");
310 addClientSocket(client_fd);
315 void * SecuritySocketService::connectionThread(void * data){
316 pthread_detach(pthread_self());
317 std::auto_ptr<Connection_Info> c (static_cast<Connection_Info *>(data));
318 SecuritySocketService &t = *static_cast<SecuritySocketService *>(c->data);
319 LogInfo("Starting connection thread");
321 t.connectionService(c->connfd);
322 } Catch (DPL::Exception){
323 LogError("Connection thread error : " << _rethrown_exception.DumpToString());
324 t.removeClientSocket(c->connfd);
328 LogInfo("Client serviced");
332 void SecuritySocketService::connectionService(int fd){
334 SocketConnection connector = SocketConnection(fd);
335 std::string interfaceName, methodName;
338 connector.read(&interfaceName, &methodName);
339 } Catch (SocketConnection::Exception::SocketConnectionException){
340 LogError("Socket Connection read error");
341 ReThrowMsg(DPL::Exception, "Socket Connection read error");
344 LogDebug("Got interface : " << interfaceName);
345 LogDebug("Got method : " << methodName);
347 if( m_callbackMap.find(interfaceName) == m_callbackMap.end()){
348 LogError("Unknown interface : " << interfaceName);
349 ThrowMsg(DPL::Exception, "Unknown interface : " << interfaceName);
352 if(m_callbackMap[interfaceName].find(methodName) == m_callbackMap[interfaceName].end()){
353 LogError("Unknown method : " << methodName);
354 ThrowMsg(DPL::Exception, "Unknown method");
357 if(m_callbackMap[interfaceName][methodName]->securityCallback != NULL){
358 if(!m_callbackMap[interfaceName][methodName]->securityCallback(fd)){
359 LogError("Security check returned false");
360 ThrowMsg(DPL::Exception, "Security check returned false");
364 LogInfo("Calling service");
366 m_callbackMap[interfaceName][methodName]->serviceCallback(&connector);
367 } Catch (ServiceCallbackApi::Exception::ServiceCallbackException){
368 LogError("Service callback error");
369 ReThrowMsg(DPL::Exception, "Service callback error");
372 LogInfo("Removing client");
373 removeClientSocket(fd);
376 LogInfo("Call served");
380 void SecuritySocketService::stop(){
382 if(-1 == close(m_listenFd))
383 if(errno != ENOTCONN)
384 throwWithErrnoMessage("close()");
386 if((returned_value = pthread_kill(m_mainThread, m_signalToClose)) < 0){
387 errno = returned_value;
388 throwWithErrnoMessage("pthread_kill()");
390 pthread_join(m_mainThread, NULL);
395 void SecuritySocketService::closeConnections(){
398 LogInfo("Closing client sockets");
399 while(popClientSocket(&clientSocket)){
400 if(-1 == close(clientSocket)){
401 LogError("close() : " << strerror(errno));
405 LogInfo("Connections closed");
408 void SecuritySocketService::deinitialize(){
409 m_serverAddress.clear();
411 LogInfo("Deinitialized");
415 #ifdef SOCKET_CONNECTION
416 DAEMON_REGISTER_SERVICE_MODULE(SecuritySocketService)