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
20 * @author Pawel Polawski (p.polawski@partner.samsung.com)
22 * @brief This function contain implementation of CookieService
26 #include <dpl/log/log.h>
27 #include <dpl/serialization.h>
28 #include <protocols.h>
29 #include <cookie-common.h>
30 #include <security-server.h>
32 #include <smack-check.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/smack.h>
36 #include <linux/limits.h>
39 const int INTERFACE_GET = 0;
40 const int INTERFACE_CHECK = 1;
42 namespace SecurityServer {
44 GenericSocketService::ServiceDescriptionVector CookieService::GetServiceDescription() {
45 return ServiceDescriptionVector {
46 {SERVICE_SOCKET_COOKIE_GET, "*", INTERFACE_GET },
47 {SERVICE_SOCKET_COOKIE_CHECK, "security-server::api-cookie-check", INTERFACE_CHECK}
51 void CookieService::accept(const AcceptEvent &event) {
52 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
53 << " ConnectionID.counter: " << event.connectionID.counter
54 << " ServiceID: " << event.interfaceID);
55 auto &info = m_connectionInfoMap[event.connectionID.counter];
56 info.interfaceID = event.interfaceID;
59 void CookieService::write(const WriteEvent &event) {
60 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
61 " Size: " << event.size << " Left: " << event.left);
63 m_serviceManager->Close(event.connectionID);
66 void CookieService::process(const ReadEvent &event) {
67 LogDebug("Read event for counter: " << event.connectionID.counter);
68 auto &info = m_connectionInfoMap[event.connectionID.counter];
69 info.buffer.Push(event.rawBuffer);
71 // We can get several requests in one package.
72 // Extract and process them all
73 while(processOne(event.connectionID, info.buffer, info.interfaceID));
76 void CookieService::close(const CloseEvent &event) {
77 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
78 m_connectionInfoMap.erase(event.connectionID.counter);
81 bool CookieService::processOne(const ConnectionID &conn, MessageBuffer &buffer, InterfaceID interfaceID)
83 LogDebug("Iteration begin");
84 MessageBuffer send, recv;
86 bool removeGarbage = false;
88 //waiting for all data
89 if (!buffer.Ready()) {
93 //receive data from buffer and check MSG_ID
96 Deserialization::Deserialize(buffer, msgTypeInt); //receive MSG_ID
97 msgType = static_cast<CookieCall>(msgTypeInt);
98 } Catch (MessageBuffer::Exception::Base) {
99 LogDebug("Broken protocol. Closing socket.");
100 m_serviceManager->Close(conn);
107 if (interfaceID == INTERFACE_GET) {
109 case CookieCall::GET_COOKIE:
110 LogDebug("Entering get-cookie server side handler");
111 retval = cookieRequest(send, conn.sock);
112 removeGarbage = true;
116 LogDebug("Error, unknown function called by client");
120 } else if (interfaceID == INTERFACE_CHECK) {
122 case CookieCall::CHECK_PID:
123 LogDebug("Entering pid-by-cookie server side handler");
124 retval = pidByCookieRequest(buffer, send);
127 case CookieCall::CHECK_SMACKLABEL:
128 LogDebug("Entering smacklabel-by-cookie server side handler");
129 retval = smackLabelByCookieRequest(buffer, send);
132 case CookieCall::CHECK_PRIVILEGE_GID:
133 LogDebug("Entering check-privilege-by-cookie-gid server side handler");
134 retval = privilegeByCookieGidRequest(buffer, send);
137 case CookieCall::CHECK_PRIVILEGE:
138 LogDebug("Entering check-privilege-by-cookie side handler");
139 retval = privilegeByCookieRequest(buffer, send);
142 case CookieCall::CHECK_UID:
143 LogDebug("Entering get-uid-by-cookie side handler");
144 retval = uidByCookieRequest(buffer, send);
147 case CookieCall::CHECK_GID:
148 LogDebug("Entering get-gid-by-cookie side handler");
149 retval = gidByCookieRequest(buffer, send);
153 LogDebug("Error, unknown function called by client");
158 LogDebug("Error, wrong interface");
164 m_serviceManager->Write(conn, send.Pop());
166 LogDebug("Closing socket because of error");
167 m_serviceManager->Close(conn);
170 // Each time you add one cookie check 2 others.
172 m_cookieJar.GarbageCollector(2);
177 bool CookieService::cookieRequest(MessageBuffer &send, int socket)
180 unsigned len = sizeof(cr);
182 if (0 != getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &cr, &len))
185 const Cookie *generatedCookie = m_cookieJar.GenerateCookie(cr.pid);
187 if (generatedCookie == NULL) {
188 //unable to create cookie
189 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_UNKNOWN);
193 //checking if binary path match created / found cookie
195 int ret = getPidPath(path, PATH_MAX, cr.pid);
198 LogError("Unable to check process binary path");
199 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_UNKNOWN);
201 if (generatedCookie->binaryPath.compare(path)) {
202 LogDebug("Found cookie but no match in bin path");
203 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_UNKNOWN);
205 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
206 Serialization::Serialize(send, generatedCookie->cookieId);
213 bool CookieService::pidByCookieRequest(MessageBuffer &buffer, MessageBuffer &send)
215 std::vector<char> cookieKey;
218 Deserialization::Deserialize(buffer, cookieKey);
219 } Catch (MessageBuffer::Exception::Base) {
220 LogDebug("Broken protocol. Closing socket.");
224 Cookie searchPattern;
225 searchPattern.cookieId = cookieKey;
227 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
229 if (searchResult != NULL) {
230 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
231 Serialization::Serialize(send, (int)searchResult->pid);
233 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
239 bool CookieService::smackLabelByCookieRequest(MessageBuffer &buffer, MessageBuffer &send)
241 std::vector<char> cookieKey;
244 Deserialization::Deserialize(buffer, cookieKey);
245 } Catch (MessageBuffer::Exception::Base) {
246 LogDebug("Broken protocol. Closing socket.");
250 Cookie searchPattern;
251 searchPattern.cookieId = cookieKey;
253 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
255 if (searchResult != NULL) {
256 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
257 Serialization::Serialize(send, searchResult->smackLabel);
259 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
265 bool CookieService::privilegeByCookieGidRequest(MessageBuffer &buffer, MessageBuffer &send)
267 std::vector<char> cookieKey;
271 Deserialization::Deserialize(buffer, cookieKey);
272 Deserialization::Deserialize(buffer, gid);
273 } Catch (MessageBuffer::Exception::Base) {
274 LogDebug("Broken protocol. Closing socket.");
278 Cookie searchPattern;
279 searchPattern.cookieId = cookieKey;
281 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
283 if (searchResult != NULL)
284 //search for specified GID on permissions list
285 for (size_t i = 0; i < searchResult->permissions.size(); i++)
286 if (searchResult->permissions[i] == gid) {
287 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
291 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_ACCESS_DENIED);
296 bool CookieService::privilegeByCookieRequest(MessageBuffer &buffer, MessageBuffer &send)
298 std::vector<char> cookieKey;
304 Deserialization::Deserialize(buffer, cookieKey);
305 Deserialization::Deserialize(buffer, object);
306 Deserialization::Deserialize(buffer, access);
307 } Catch (MessageBuffer::Exception::Base) {
308 LogDebug("Broken protocol. Closing socket.");
312 Cookie searchPattern;
313 searchPattern.cookieId = cookieKey;
315 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
317 if (searchResult != NULL) {
318 if (!smack_check()) {
319 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
321 subject = searchResult->smackLabel;
324 if ((retval = smack_have_access(subject.c_str(), object.c_str(), access.c_str())) == 1)
325 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
327 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_ACCESS_DENIED);
328 LogSmackAudit("SS_SMACK: "
329 << " subject=" << subject
330 << ", object=" << object
331 << ", access=" << access
332 << ", result=" << retval);
336 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
342 bool CookieService::uidByCookieRequest(MessageBuffer &buffer, MessageBuffer &send)
344 std::vector<char> cookieKey;
347 Deserialization::Deserialize(buffer, cookieKey);
348 } Catch (MessageBuffer::Exception::Base) {
349 LogDebug("Broken protocol. Closing socket.");
353 Cookie searchPattern;
354 searchPattern.cookieId = cookieKey;
356 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
358 if (searchResult != NULL) {
359 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
360 Serialization::Serialize(send, (int)searchResult->uid);
362 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
368 bool CookieService::gidByCookieRequest(MessageBuffer &buffer, MessageBuffer &send)
370 std::vector<char> cookieKey;
373 Deserialization::Deserialize(buffer, cookieKey);
374 } Catch (MessageBuffer::Exception::Base) {
375 LogDebug("Broken protocol. Closing socket.");
379 Cookie searchPattern;
380 searchPattern.cookieId = cookieKey;
382 const Cookie *searchResult = m_cookieJar.SearchCookie(searchPattern, CompareType::COOKIE_ID);
384 if (searchResult != NULL) {
385 Serialization::Serialize(send, (int)SECURITY_SERVER_API_SUCCESS);
386 Serialization::Serialize(send, (int)searchResult->gid);
388 Serialization::Serialize(send, (int)SECURITY_SERVER_API_ERROR_NO_SUCH_COOKIE);
394 } // namespace SecurityServer