2 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Bumjin Im <bj.im@samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * @file privilege-by-pid.cpp
20 * @author Jan Cybulski (j.cybulski@samsung.com)
22 * @brief Implementation of check-privilege-by-pid service.
25 #include <sys/smack.h>
27 #include <dpl/log/log.h>
28 #include <dpl/serialization.h>
30 #include <protocols.h>
31 #include <privilege-by-pid.h>
33 #include <security-server.h>
34 #include <security-server-util.h>
35 #include <smack-check.h>
37 #include <privilege-control.h>
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.
48 // Please note: SocketManaged does not use it and
49 // does not check it in any way.
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;
56 } // namespace anonymous
58 namespace SecurityServer {
60 GenericSocketService::ServiceDescriptionVector PrivilegeByPidService::GetServiceDescription() {
61 ServiceDescription sd = {
64 SERVICE_SOCKET_PRIVILEGE_BY_PID
66 ServiceDescriptionVector v;
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);
77 void PrivilegeByPidService::write(const WriteEvent &event) {
78 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
79 " Size: " << event.size << " Left: " << event.left);
81 m_serviceManager->Close(event.connectionID);
84 bool PrivilegeByPidService::readOne(const ConnectionID &conn, SocketBuffer &buffer) {
85 LogDebug("Iteration begin");
91 std::string access_rights;
94 int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
97 if (!buffer.Ready()) {
98 LogDebug("Got part of message. Service is waiting for the rest.");
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);
114 char subject[SMACK_LABEL_LEN + 1];
116 retval = smack_pid_have_access(pid, object.c_str(), access_rights.c_str());
117 LogDebug("smack_pid_have_access returned " << retval);
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.");
123 SECURE_SLOGD("Subject label of client PID %d is: %s", pid, subject);
126 LogDebug("SMACK is not available. Subject label has not been read.");
130 char *path = read_exe_path_from_proc(pid);
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);
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);
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;
145 SecurityServer::Serialization ser;
146 SocketBuffer sendBuffer;
147 ser.Serialize(sendBuffer, retCode);
148 m_serviceManager->Write(conn, sendBuffer.Pop());
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);
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));
163 void PrivilegeByPidService::close(const CloseEvent &event) {
164 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
165 m_socketBufferMap.erase(event.connectionID.counter);
168 void PrivilegeByPidService::error(const ErrorEvent &event) {
169 LogDebug("ErrorEvent. ConnectionID: " << event.connectionID.sock);
170 m_serviceManager->Close(event.connectionID);
173 } // namespace SecurityServer