bcb8659e5f167cfe52e7486f7497c109207ca87f
[platform/core/security/security-manager.git] / src / server / 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 namespace SecurityServer {
40
41 GenericSocketService::ServiceDescriptionVector PrivilegeByPidService::GetServiceDescription() {
42     return ServiceDescriptionVector
43         {{SERVICE_SOCKET_PRIVILEGE_BY_PID, "security-server::api-privilege-by-pid" }};
44 }
45
46 void PrivilegeByPidService::accept(const AcceptEvent &event) {
47     LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
48         << " ConnectionID.counter: " << event.connectionID.counter
49         << " ServiceID: " << event.interfaceID);
50 }
51
52 void PrivilegeByPidService::write(const WriteEvent &event) {
53     LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
54         " Size: " << event.size << " Left: " << event.left);
55     if (event.left == 0)
56         m_serviceManager->Close(event.connectionID);
57 }
58
59 bool PrivilegeByPidService::processOne(const ConnectionID &conn, MessageBuffer &buffer) {
60     LogDebug("Iteration begin");
61
62     int retval;
63     int pid;
64     std::string object;
65     std::string access_rights;
66     char subject[SMACK_LABEL_LEN + 1] = {0};
67
68     int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
69
70
71     if (!buffer.Ready()) {
72         return false;
73     }
74
75     Try {
76         Deserialization::Deserialize(buffer, pid);
77         Deserialization::Deserialize(buffer, object);
78         Deserialization::Deserialize(buffer, access_rights);
79     } Catch (MessageBuffer::Exception::Base) {
80         LogDebug("Broken protocol. Closing socket.");
81         m_serviceManager->Close(conn);
82         return false;
83     }
84
85     if (smack_check()) {
86         retval = smack_pid_have_access(pid, object.c_str(), access_rights.c_str());
87         LogDebug("smack_pid_have_access returned " << retval);
88
89         if (get_smack_label_from_process(pid, subject) != PC_OPERATION_SUCCESS) {
90             // subject label is set to empty string
91             LogError("get_smack_label_from_process failed. Subject label has not been read.");
92         } else {
93             LogSecureDebug("Subject label of client PID " << pid << " is: " << subject);
94         }
95     } else {
96         LogDebug("SMACK is not available. Subject label has not been read.");
97         retval = 1;
98     }
99 //    char *path = read_exe_path_from_proc(pid);
100 //
101 //    if (retval > 0)
102 //        LogDebug("SS_SMACK: "
103 //                << "caller_pid=" << pid
104 //                << ", subject=" << subject
105 //                << ", object=" << object
106 //                << ", access=" << access_rights
107 //                << ", result=" << retval
108 //                << ", caller_path=" << path);
109 //    else
110 //        LogError("SS_SMACK: "
111 //                << "caller_pid=" << pid
112 //                << ", subject=" << subject
113 //                << ", object=" << object
114 //                << ", access=" << access_rights
115 //                << ", result=" << retval
116 //                << ", caller_path=" << path);
117 //
118 //    if (path != NULL)
119 //        free(path);
120
121
122     if (retval == 1)   //there is permission
123         retCode = SECURITY_SERVER_API_SUCCESS;
124     else                //there is no permission
125         retCode = SECURITY_SERVER_API_ERROR_ACCESS_DENIED;
126
127     MessageBuffer sendBuffer;
128     Serialization::Serialize(sendBuffer, retCode);
129     m_serviceManager->Write(conn, sendBuffer.Pop());
130
131     if (retval != 1) {
132         char *path = read_exe_path_from_proc(pid);
133
134         LogSmackAudit("SS_SMACK: "
135             << "caller_pid=" << pid
136             << ", subject="  << subject
137             << ", object="   << object
138             << ", access="   << access_rights
139             << ", result="   << retval
140             << ", caller_path=" << (path ? path : ""));
141
142         free(path);
143     }
144
145     return true;
146 }
147
148 void PrivilegeByPidService::process(const ReadEvent &event) {
149     LogDebug("Read event for counter: " << event.connectionID.counter);
150     auto &buffer = m_messageBufferMap[event.connectionID.counter];
151     buffer.Push(event.rawBuffer);
152
153     // We can get several requests in one package.
154     // Extract and process them all
155     while(processOne(event.connectionID, buffer));
156 }
157
158 void PrivilegeByPidService::close(const CloseEvent &event) {
159     LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
160     m_messageBufferMap.erase(event.connectionID.counter);
161 }
162
163 } // namespace SecurityServer
164