b7bc28ae670335b72cb6bbd7ea6ec695c8302d72
[framework/security/security-server.git] / src / server2 / service / privilege-by-pid.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        privilege-by-pid.cpp
20  * @author      Jan Cybulski (j.cybulski@samsung.com)
21  * @version     1.0
22  * @brief       Implementation of check-privilege-by-pid service.
23  */
24
25 #include <sys/smack.h>
26
27 #include <dpl/log/log.h>
28 #include <dpl/serialization.h>
29
30 #include <protocols.h>
31 #include <privilege-by-pid.h>
32
33 #include <security-server.h>
34 #include <security-server-util.h>
35 #include <smack-check.h>
36
37 #include <privilege-control.h>
38
39
40 namespace {
41 // Service may open more than one socket.
42 // These ID's will be assigned to sockets
43 // and will be used only by service.
44 // When new connection arrives, AcceptEvent
45 // will be generated with proper ID to inform
46 // service about input socket.
47 //
48 // Please note: SocketManaged does not use it and
49 // does not check it in any way.
50 //
51 // If your service require only one socket
52 // (uses only one socket labeled with smack)
53 // you may ignore this ID (just pass 0)
54 const int SERVICE_SOCKET_ID = 0;
55
56 } // namespace anonymous
57
58 namespace SecurityServer {
59
60 GenericSocketService::ServiceDescriptionVector PrivilegeByPidService::GetServiceDescription() {
61     ServiceDescription sd = {
62         "*",
63         SERVICE_SOCKET_ID,
64         SERVICE_SOCKET_PRIVILEGE_BY_PID
65     };
66     ServiceDescriptionVector v;
67     v.push_back(sd);
68     return v;
69 }
70
71 void PrivilegeByPidService::accept(const AcceptEvent &event) {
72     LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
73         << " ConnectionID.counter: " << event.connectionID.counter
74         << " ServiceID: " << event.interfaceID);
75 }
76
77 void PrivilegeByPidService::write(const WriteEvent &event) {
78     LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
79         " Size: " << event.size << " Left: " << event.left);
80     if (event.left == 0)
81         m_serviceManager->Close(event.connectionID);
82 }
83
84 bool PrivilegeByPidService::readOne(const ConnectionID &conn, SocketBuffer &buffer) {
85     LogDebug("Iteration begin");
86
87
88     int retval;
89     int pid;
90     std::string object;
91     std::string access_rights;
92
93
94     int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
95
96
97     if (!buffer.Ready()) {
98         LogDebug("Got part of message. Service is waiting for the rest.");
99         return false;
100     }
101
102     Try {
103         SecurityServer::Deserialization des;
104         des.Deserialize(buffer, pid);
105         des.Deserialize(buffer, object);
106         des.Deserialize(buffer, access_rights);
107     } Catch (SocketBuffer::Exception::Base) {
108         LogDebug("Broken protocol. Closing socket.");
109         m_serviceManager->Close(conn);
110         return false;
111     }
112
113     if (smack_check()) {
114         char subject[SMACK_LABEL_LEN + 1];
115         subject[0]='\0';
116         retval = smack_pid_have_access(pid, object.c_str(), access_rights.c_str());
117         LogDebug("smack_pid_have_access returned " << retval);
118
119         if (get_smack_label_from_process(pid, subject) != PC_OPERATION_SUCCESS) {
120             // subject label is set to empty string
121             LogError("get_smack_label_from_process failed. Subject label has not been read.");
122         } else {
123             SECURE_SLOGD("Subject label of client PID %d is: %s", pid, subject);
124         }
125     } else {
126         LogDebug("SMACK is not available. Subject label has not been read.");
127         retval = 1;
128     }
129
130     char *path = read_exe_path_from_proc(pid);
131
132     if (retval > 0)
133         SECURE_SLOGD("SS_SMACK: caller_pid=%d, subject=%s, object=%s, access=%s, result=%d, caller_path=%s", pid, subject, object, access_rights, retval, path);
134     else
135         SECURE_SLOGW("SS_SMACK: caller_pid=%d, subject=%s, object=%s, access=%s, result=%d, caller_path=%s", pid, subject, object, access_rights, retval, path);
136
137     if (path != NULL)
138         free(path);
139
140     if (retval == 1)   //there is permission
141         retCode = SECURITY_SERVER_API_SUCCESS;
142     else                //there is no permission
143         retCode = SECURITY_SERVER_API_ERROR_ACCESS_DENIED;
144
145     SecurityServer::Serialization ser;
146     SocketBuffer sendBuffer;
147     ser.Serialize(sendBuffer, retCode);
148     m_serviceManager->Write(conn, sendBuffer.Pop());
149     return true;
150 }
151
152 void PrivilegeByPidService::read(const ReadEvent &event) {
153     LogDebug("Read event for counter: " << event.connectionID.counter);
154     auto &buffer = m_socketBufferMap[event.connectionID.counter];
155     buffer.Push(event.rawBuffer);
156
157     LogDebug("Pushed to buffer ptr: " << (void*)&buffer);
158     // We can get several requests in one package.
159     // Extract and process them all
160     while(readOne(event.connectionID, buffer));
161 }
162
163 void PrivilegeByPidService::close(const CloseEvent &event) {
164     LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
165     m_socketBufferMap.erase(event.connectionID.counter);
166 }
167
168 void PrivilegeByPidService::error(const ErrorEvent &event) {
169     LogDebug("ErrorEvent. ConnectionID: " << event.connectionID.sock);
170     m_serviceManager->Close(event.connectionID);
171 }
172
173 } // namespace SecurityServer
174