tizen 2.4 release
[framework/security/key-manager.git] / src / manager / main / socket-manager.cpp
1 /*
2  *  Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Bumjin Im <bj.im@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        socket-manager.cpp
20  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
21  * @version     1.0
22  * @brief       Implementation of SocketManager.
23  */
24
25 #include <set>
26
27 #include <signal.h>
28 #include <sys/select.h>
29 #include <sys/signalfd.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <signal.h>
36 #include <errno.h>
37 #include <time.h>
38
39 #include <systemd/sd-daemon.h>
40
41 #include <dpl/errno_string.h>
42 #include <dpl/log/log.h>
43 #include <dpl/assert.h>
44
45 #include <ckm/ckm-client-info.h>
46 #include <socket-manager.h>
47
48 namespace {
49 const time_t SOCKET_TIMEOUT = 1000;
50
51 int getCredentialsFromSocket(int sock, CKM::Credentials &cred, vsm_context_h &vsmCtx)
52 {
53     std::vector<char> result(1);
54     socklen_t length = 1;
55     ucred peerCred;
56
57     if ((0 > getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length))
58         && errno != ERANGE)
59     {
60         LogError("getsockopt failed");
61         return -1;
62     }
63
64     result.resize(length);
65
66     if (0 > getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length)) {
67         LogError("getsockopt failed");
68         return -1;
69     }
70
71     length = sizeof(ucred);
72
73     if (0 > getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peerCred, &length)) {
74         LogError("getsockopt failed");
75         return -1;
76     }
77
78     result.push_back('\0');
79     cred.smackLabel = result.data();
80     if (!vsmCtx) {
81         CKM::ClientInfo clientInfo(peerCred.uid);
82         cred.clientID = clientInfo.getClientID();
83         LogError("vsmCtx == NULL. ClientID[" << cred.clientID << "]");
84     } else {
85         vsm_zone_h _vsm_zone = vsm_lookup_zone_by_pid(vsmCtx, peerCred.pid);
86         if (!_vsm_zone) {
87             if (0 > vsm_cleanup_context(vsmCtx)) {
88                 LogError("Failed to vsm_cleanup_context.");
89             } else if (!(vsmCtx = vsm_create_context())) {
90                 LogError("Failed to vsm_create_context.");
91                 return -1;
92             }
93             LogDebug("Recreate vsm context Success. vsm_lookup_zone_by_pid:[" << peerCred.pid << "] returned NULL");
94             _vsm_zone = vsm_lookup_zone_by_pid(vsmCtx, peerCred.pid);
95
96             if (!_vsm_zone) {
97                 LogError("Failed. vsm_zone lookedup by pid:[" << peerCred.pid << "]");
98                 vsm_cleanup_context(vsmCtx);
99                 vsmCtx = NULL;
100                 return -1;
101             }
102             LogDebug("Success. vsm_lookup_zone_by_pid:[" << peerCred.pid << "]");
103         }
104
105         // construct clientInfo with default zone
106         CKM::ClientInfo clientInfo(peerCred.uid);
107
108         if (!vsm_is_host_zone(_vsm_zone))
109             clientInfo = CKM::ClientInfo(std::string(vsm_get_zone_name(_vsm_zone)), peerCred.uid);
110
111         cred.clientID = clientInfo.getClientID();
112         LogDebug("sock[" << sock << "] clientID[" << cred.clientID << "]");
113     }
114     return 0;
115 }
116 } // namespace anonymous
117
118 namespace CKM {
119
120 struct DummyService : public GenericSocketService {
121     ServiceDescriptionVector GetServiceDescription() {
122         return ServiceDescriptionVector();
123     }
124     void Event(const AcceptEvent &event) { (void)event; }
125     void Event(const WriteEvent &event) { (void)event; }
126     void Event(const ReadEvent &event) { (void)event; }
127     void Event(const CloseEvent &event) { (void)event; }
128 };
129
130 struct SignalService : public GenericSocketService {
131     int GetDescriptor() {
132         LogInfo("set up");
133         sigset_t mask;
134         sigemptyset(&mask);
135         sigaddset(&mask, SIGTERM);
136         if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL))
137             return -1;
138         return signalfd(-1, &mask, 0);
139     }
140
141     ServiceDescriptionVector GetServiceDescription() {
142         return ServiceDescriptionVector();
143     }
144
145     void Event(const AcceptEvent &event) { (void)event; } // not supported
146     void Event(const WriteEvent &event) { (void)event; }  // not supported
147     void Event(const CloseEvent &event) { (void)event; }  // not supported
148
149     void Event(const ReadEvent &event) {
150         LogDebug("Get signal information");
151
152         if(sizeof(struct signalfd_siginfo) != event.rawBuffer.size()) {
153             LogError("Wrong size of signalfd_siginfo struct. Expected: "
154                 << sizeof(signalfd_siginfo) << " Get: "
155                 << event.rawBuffer.size());
156             return;
157         }
158
159         signalfd_siginfo *siginfo = (signalfd_siginfo*)(&(event.rawBuffer[0]));
160
161         if (siginfo->ssi_signo == SIGTERM) {
162             LogInfo("Got signal: SIGTERM");
163             static_cast<SocketManager*>(m_serviceManager)->MainLoopStop();
164             return;
165         }
166
167         LogInfo("This should not happend. Got signal: " << siginfo->ssi_signo);
168     }
169 };
170
171 SocketManager::SocketDescription&
172 SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout)
173 {
174     if ((int)m_socketDescriptionVector.size() <= sock)
175         m_socketDescriptionVector.resize(sock+20);
176
177     auto &desc = m_socketDescriptionVector[sock];
178     desc.isListen = false;
179     desc.isOpen = true;
180     desc.interfaceID = 0;
181     desc.service = NULL;
182     desc.counter = ++m_counter;
183
184     if (timeout) {
185         desc.timeout = time(NULL) + SOCKET_TIMEOUT;
186         if (false == desc.isTimeout) {
187             Timeout tm;
188             tm.time = desc.timeout;
189             tm.sock = sock;
190             m_timeoutQueue.push(tm);
191         }
192     }
193
194     desc.isTimeout = timeout;
195
196     FD_SET(sock, &m_readSet);
197     m_maxDesc = sock > m_maxDesc ? sock : m_maxDesc;
198     return desc;
199 }
200
201 SocketManager::SocketManager()
202   : m_maxDesc(0)
203   , m_counter(0)
204   , m_vsmCtx(NULL)
205 {
206     FD_ZERO(&m_readSet);
207     FD_ZERO(&m_writeSet);
208     if (-1 == pipe(m_notifyMe)) {
209         int err = errno;
210         ThrowMsg(Exception::InitFailed, "Error in pipe: " << GetErrnoString(err));
211     }
212     LogInfo("Pipe: Read desc: " << m_notifyMe[0] << " Write desc: " << m_notifyMe[1]);
213
214     auto &desc = CreateDefaultReadSocketDescription(m_notifyMe[0], false);
215     desc.service = new DummyService;
216
217     // std::thread bases on pthread so this should work fine
218     sigset_t set;
219     sigemptyset(&set);
220     sigaddset(&set, SIGPIPE);
221     pthread_sigmask(SIG_BLOCK, &set, NULL);
222
223     // add support for TERM signal (passed from systemd)
224     auto *signalService = new SignalService;
225     signalService->SetSocketManager(this);
226     int filefd = signalService->GetDescriptor();
227     if (-1 == filefd) {
228         LogError("Error in SignalService.GetDescriptor()");
229         delete signalService;
230     } else {
231         auto &desc2 = CreateDefaultReadSocketDescription(filefd, false);
232         desc2.service = signalService;
233         LogInfo("SignalService mounted on " << filefd << " descriptor");
234     }
235     m_vsmCtx = vsm_create_context();
236     // TODO: handle error
237 }
238
239 SocketManager::~SocketManager() {
240     std::set<GenericSocketService*> serviceMap;
241
242     // Find all services. Set is used to remove duplicates.
243     // In this implementation, services are not able to react in any way.
244     for (size_t i=0; i < m_socketDescriptionVector.size(); ++i)
245         if (m_socketDescriptionVector[i].isOpen)
246             serviceMap.insert(m_socketDescriptionVector[i].service);
247
248     // Time to destroy all services.
249     for(auto it = serviceMap.begin(); it != serviceMap.end(); ++it) {
250         LogDebug("delete " << (void*)(*it));
251         delete *it;
252     }
253
254     for (size_t i = 0; i < m_socketDescriptionVector.size(); ++i)
255         if (m_socketDescriptionVector[i].isOpen)
256             close(i);
257
258     // All socket except one were closed. Now pipe input must be closed.
259     close(m_notifyMe[1]);
260 }
261
262 void SocketManager::ReadyForAccept(int sock) {
263     struct sockaddr_un clientAddr;
264     unsigned int clientLen = sizeof(clientAddr);
265     int client = accept4(sock, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK);
266 //    LogInfo("Accept on sock: " << sock << " Socket opended: " << client);
267     if (-1 == client) {
268         int err = errno;
269         LogDebug("Error in accept: " << GetErrnoString(err));
270         return;
271     }
272
273     Credentials peerCred;
274     if (0 > getCredentialsFromSocket(client, peerCred, m_vsmCtx)) {
275         LogDebug("Error in getCredentialsFromSocket. Socket closed.");
276         TEMP_FAILURE_RETRY(close(client));
277         return;
278     }
279
280     auto &desc = CreateDefaultReadSocketDescription(client, true);
281     desc.interfaceID = m_socketDescriptionVector[sock].interfaceID;
282     desc.service = m_socketDescriptionVector[sock].service;
283
284     GenericSocketService::AcceptEvent event;
285     event.connectionID.sock = client;
286     event.connectionID.counter = desc.counter;
287     event.interfaceID = desc.interfaceID;
288     event.credentials = peerCred;
289     desc.service->Event(event);
290 }
291
292 void SocketManager::ReadyForRead(int sock) {
293     if (m_socketDescriptionVector[sock].isListen) {
294         ReadyForAccept(sock);
295         return;
296     }
297
298     GenericSocketService::ReadEvent event;
299     event.connectionID.sock = sock;
300     event.connectionID.counter = m_socketDescriptionVector[sock].counter;
301     event.rawBuffer.resize(4096);
302
303     auto &desc = m_socketDescriptionVector[sock];
304     desc.timeout = time(NULL) + SOCKET_TIMEOUT;
305
306     ssize_t size = read(sock, &event.rawBuffer[0], 4096);
307
308     if (size == 0) {
309         CloseSocket(sock);
310     } else if (size >= 0) {
311         event.rawBuffer.resize(size);
312         desc.service->Event(event);
313     } else if (size == -1) {
314         int err = errno;
315         switch(err) {
316             case EAGAIN:
317             case EINTR:
318                 break;
319             default:
320                 LogDebug("Reading sock error: " << GetErrnoString(err));
321                 CloseSocket(sock);
322         }
323     }
324 }
325
326 void SocketManager::ReadyForWriteBuffer(int sock) {
327     auto &desc = m_socketDescriptionVector[sock];
328     size_t size = desc.rawBuffer.size();
329     ssize_t result = write(sock, &desc.rawBuffer[0], size);
330     if (result == -1) {
331         int err = errno;
332         switch(err) {
333         case EAGAIN:
334         case EINTR:
335             // select will trigger write once again, nothing to do
336             break;
337         case EPIPE:
338         default:
339             LogDebug("Error during write: " << GetErrnoString(err));
340             CloseSocket(sock);
341             break;
342         }
343         return; // We do not want to propagate error to next layer
344     }
345
346     desc.rawBuffer.erase(desc.rawBuffer.begin(), desc.rawBuffer.begin()+result);
347
348     desc.timeout = time(NULL) + SOCKET_TIMEOUT;
349
350     if (desc.rawBuffer.empty())
351         FD_CLR(sock, &m_writeSet);
352
353     GenericSocketService::WriteEvent event;
354     event.connectionID.sock = sock;
355     event.connectionID.counter = desc.counter;
356     event.size = result;
357     event.left = desc.rawBuffer.size();
358
359     desc.service->Event(event);
360 }
361
362 void SocketManager::ReadyForWrite(int sock) {
363         ReadyForWriteBuffer(sock);
364 }
365
366 void SocketManager::MainLoop() {
367     // remove evironment values passed by systemd
368     // uncomment it after removing old security-server code
369     // sd_listen_fds(1);
370
371     // Daemon is ready to work.
372     sd_notify(0, "READY=1");
373
374     m_working = true;
375     while(m_working) {
376         fd_set readSet = m_readSet;
377         fd_set writeSet = m_writeSet;
378
379         timeval localTempTimeout;
380         timeval *ptrTimeout = &localTempTimeout;
381
382         // I need to extract timeout from priority_queue.
383         // Timeout in priority_queue may be deprecated.
384         // I need to find some actual one.
385         while(!m_timeoutQueue.empty()) {
386             auto &top = m_timeoutQueue.top();
387             auto &desc = m_socketDescriptionVector[top.sock];
388
389             if (top.time == desc.timeout) {
390                 // This timeout matches timeout from socket.
391                 // It can be used.
392                 break;
393             } else {
394                 // This socket was used after timeout in priority queue was set up.
395                 // We need to update timeout and find some useable one.
396                 Timeout tm = { desc.timeout , top.sock};
397                 m_timeoutQueue.pop();
398                 m_timeoutQueue.push(tm);
399             }
400         }
401
402         if (m_timeoutQueue.empty()) {
403             LogDebug("No usaable timeout found.");
404             ptrTimeout = NULL; // select will wait without timeout
405         } else {
406             time_t currentTime = time(NULL);
407             auto &pqTimeout = m_timeoutQueue.top();
408
409             // 0 means that select won't block and socket will be closed ;-)
410             ptrTimeout->tv_sec =
411               currentTime < pqTimeout.time ? pqTimeout.time - currentTime : 0;
412             ptrTimeout->tv_usec = 0;
413 //            LogDebug("Set up timeout: " << (int)ptrTimeout->tv_sec
414 //                << " seconds. Socket: " << pqTimeout.sock);
415         }
416
417         int ret = select(m_maxDesc+1, &readSet, &writeSet, NULL, ptrTimeout);
418
419         if (0 == ret) { // timeout
420             Assert(!m_timeoutQueue.empty());
421
422             Timeout pqTimeout = m_timeoutQueue.top();
423             m_timeoutQueue.pop();
424
425             auto &desc = m_socketDescriptionVector[pqTimeout.sock];
426
427             if (!desc.isTimeout || !desc.isOpen) {
428                 // Connection was closed. Timeout is useless...
429                 desc.isTimeout = false;
430                 continue;
431             }
432
433             if (pqTimeout.time < desc.timeout) {
434                 // Is it possible?
435                 // This socket was used after timeout. We need to update timeout.
436                 pqTimeout.time = desc.timeout;
437                 m_timeoutQueue.push(pqTimeout);
438                 continue;
439             }
440
441             // timeout from m_timeoutQueue matches with socket.timeout
442             // and connection is open. Time to close it!
443             // Putting new timeout in queue here is pointless.
444             desc.isTimeout = false;
445             CloseSocket(pqTimeout.sock);
446
447             // All done. Now we should process next select ;-)
448             continue;
449         }
450
451         if (-1 == ret) {
452             switch(errno) {
453             case EINTR:
454                 LogDebug("EINTR in select");
455                 break;
456             default:
457                 int err = errno;
458                 LogError("Error in select: " << GetErrnoString(err));
459                 return;
460             }
461             continue;
462         }
463         for(int i = 0; i<m_maxDesc+1 && ret; ++i) {
464             if (FD_ISSET(i, &readSet)) {
465                 ReadyForRead(i);
466                 --ret;
467             }
468             if (FD_ISSET(i, &writeSet)) {
469                 ReadyForWrite(i);
470                 --ret;
471             }
472         }
473         ProcessQueue();
474     }
475 }
476
477 void SocketManager::MainLoopStop()
478 {
479     m_working = false;
480     NotifyMe();
481 }
482
483 int SocketManager::GetSocketFromSystemD(
484     const GenericSocketService::ServiceDescription &desc)
485 {
486     int fd;
487
488     // TODO optimalization - do it once in object constructor
489     //                       and remember all information path->sockfd
490     int n = sd_listen_fds(0);
491
492     LogInfo("sd_listen_fds returns: " << n);
493
494     if (n < 0) {
495         LogError("Error in sd_listend_fds");
496         ThrowMsg(Exception::InitFailed, "Error in sd_listend_fds");
497     }
498
499     for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+n; ++fd) {
500         if (0 < sd_is_socket_unix(fd, SOCK_STREAM, 1, desc.serviceHandlerPath.c_str(), 0)) {
501             LogInfo("Useable socket " << desc.serviceHandlerPath <<
502                 " was passed by SystemD under descriptor " << fd);
503             if (m_vsmCtx) {
504                 int ret = vsm_declare_link(m_vsmCtx, desc.serviceHandlerPath.c_str(), desc.serviceHandlerPath.c_str());
505                 if (ret)
506                     LogError("Failed to socket declare link: " << desc.serviceHandlerPath.c_str());
507             }
508             return fd;
509         }
510     }
511
512     ThrowMsg(Exception::GetSystemdSocketFailed, "No useable sockets were passed by systemd.");
513 }
514
515 void SocketManager::CreateDomainSocket(
516     GenericSocketService *service,
517     const GenericSocketService::ServiceDescription &desc)
518 {
519     int sockfd = GetSocketFromSystemD(desc);
520
521     auto &description = CreateDefaultReadSocketDescription(sockfd, false);
522
523     description.isListen = true;
524     description.interfaceID = desc.interfaceID;
525     description.service = service;
526
527     LogDebug("Listen on socket: " << sockfd <<
528         " Handler: " << desc.serviceHandlerPath.c_str());
529 }
530
531 void SocketManager::RegisterSocketService(
532     GenericSocketService *service)
533 {
534     service->SetSocketManager(this);
535     auto serviceVector = service->GetServiceDescription();
536     Try {
537         for (auto iter = serviceVector.begin(); iter != serviceVector.end(); ++iter)
538             CreateDomainSocket(service, *iter);
539     } Catch (Exception::Base) {
540         for (int i =0; i < (int)m_socketDescriptionVector.size(); ++i)
541         {
542             auto &desc = m_socketDescriptionVector[i];
543             if (desc.service == service && desc.isOpen) {
544                 close(i);
545                 desc.isOpen = false;
546             }
547         }
548         ReThrow(Exception::Base);
549     }
550 }
551
552 void SocketManager::Close(ConnectionID connectionID) {
553     {
554         std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
555         m_closeQueue.push(connectionID);
556     }
557     NotifyMe();
558 }
559
560 void SocketManager::Write(ConnectionID connectionID, const RawBuffer &rawBuffer) {
561     WriteBuffer buffer;
562     buffer.connectionID = connectionID;
563     buffer.rawBuffer = rawBuffer;
564     {
565         std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
566         m_writeBufferQueue.push(buffer);
567     }
568     NotifyMe();
569 }
570
571 void SocketManager::NotifyMe() {
572     TEMP_FAILURE_RETRY(write(m_notifyMe[1], "You have message ;-)", 1));
573 }
574
575 void SocketManager::ProcessQueue() {
576     WriteBuffer buffer;
577     {
578         std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
579         while (!m_writeBufferQueue.empty()) {
580             buffer = m_writeBufferQueue.front();
581             m_writeBufferQueue.pop();
582
583             auto &desc = m_socketDescriptionVector[buffer.connectionID.sock];
584
585             if (!desc.isOpen) {
586                 LogDebug("Received packet for write but connection is closed. Packet ignored!");
587                 continue;
588             }
589
590             if (desc.counter != buffer.connectionID.counter)
591             {
592                 LogDebug("Received packet for write but counter is broken. Packet ignored!");
593                 continue;
594             }
595
596             std::copy(
597                 buffer.rawBuffer.begin(),
598                 buffer.rawBuffer.end(),
599                 std::back_inserter(desc.rawBuffer));
600
601             FD_SET(buffer.connectionID.sock, &m_writeSet);
602         }
603
604     }
605
606     while (1) {
607         ConnectionID connection;
608         {
609             std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
610             if (m_closeQueue.empty())
611                 return;
612             connection = m_closeQueue.front();
613             m_closeQueue.pop();
614         }
615
616         if (!m_socketDescriptionVector[connection.sock].isOpen)
617             continue;
618
619         if (connection.counter != m_socketDescriptionVector[connection.sock].counter)
620             continue;
621
622         CloseSocket(connection.sock);
623     }
624 }
625
626 void SocketManager::CloseSocket(int sock) {
627 //    LogInfo("Closing socket: " << sock);
628     auto &desc = m_socketDescriptionVector[sock];
629
630     if (!(desc.isOpen)) {
631         // This may happend when some information was waiting for write to the
632         // socket and in the same time socket was closed by the client.
633         LogError("Socket " << sock << " is not open. Nothing to do!");
634         return;
635     }
636
637     GenericSocketService::CloseEvent event;
638     event.connectionID.sock = sock;
639     event.connectionID.counter = desc.counter;
640     auto service = desc.service;
641
642     desc.isOpen = false;
643     desc.service = NULL;
644     desc.interfaceID = -1;
645     desc.rawBuffer.clear();
646
647     if (service)
648         service->Event(event);
649     else
650         LogError("Critical! Service is NULL! This should never happend!");
651
652     TEMP_FAILURE_RETRY(close(sock));
653     FD_CLR(sock, &m_readSet);
654     FD_CLR(sock, &m_writeSet);
655 }
656
657 } // namespace CKM