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 Jan Olszak (j.olszak@samsung.com)
22 * @brief Implementation of api-get-gid service.
26 #include <sys/smack.h>
30 #include <dpl/log/log.h>
31 #include <dpl/serialization.h>
33 #include <protocols.h>
35 #include <security-server.h>
37 namespace SecurityServer {
39 GenericSocketService::ServiceDescriptionVector GetGidService::GetServiceDescription() {
40 return ServiceDescriptionVector
41 {{SERVICE_SOCKET_GET_GID, "security-server::api-get-gid"}};
44 void GetGidService::accept(const AcceptEvent &event) {
45 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
46 << " ConnectionID.counter: " << event.connectionID.counter
47 << " ServiceID: " << event.interfaceID);
50 void GetGidService::write(const WriteEvent &event) {
51 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
52 " Size: " << event.size << " Left: " << event.left);
54 m_serviceManager->Close(event.connectionID);
59 * Searches for group ID by given group name
61 int GetGidService::setGid(std::string& obj)
64 struct group *grpbuf = NULL;
66 std::vector<char> buf;
69 * The maximum needed size for buf can be found using sysconf(3)
70 * with the argument _SC_GETGR_R_SIZE_MAX. If _SC_GETGR_R_SIZE_MAX is not
71 * returned we set max_buf_size to 1024 bytes. Enough to store few groups.
73 long int maxBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
79 * There can be some corner cases when for example user is assigned to a
80 * lot of groups. In that case if buffer is to small getgrnam_r will
81 * return ERANGE error. Solution could be calling getgrnam_r with bigger
82 * buffer until it's big enough.
86 buf.resize(maxBufSize);
87 }catch(std::bad_alloc&) {
88 ret = SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY;
89 LogError("Out Of Memory");
93 } while ((ret = getgrnam_r(obj.c_str(), &grp, &(buf[0]), buf.size(), &grpbuf)) == ERANGE);
97 ret = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
98 LogError("getgrnam_r failed with error: " << strerror(errno));
101 } else if (grpbuf == NULL) {
102 ret = SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT;
103 LogError("Cannot find gid for group: " << obj);
107 m_gid = grpbuf->gr_gid;
113 bool GetGidService::processOne(const ConnectionID &conn, MessageBuffer &buffer) {
114 LogDebug("Iteration begin");
115 std::string objectName;
116 int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
118 if (!buffer.Ready()) {
124 Deserialization::Deserialize(buffer, objectName);
125 } Catch (MessageBuffer::Exception::Base) {
126 LogDebug("Broken protocol. Closing socket.");
127 m_serviceManager->Close(conn);
132 retCode = setGid(objectName);
135 MessageBuffer sendBuffer;
136 Serialization::Serialize(sendBuffer, retCode);
137 Serialization::Serialize(sendBuffer, m_gid);
138 m_serviceManager->Write(conn, sendBuffer.Pop());
142 void GetGidService::process(const ReadEvent &event) {
143 LogDebug("Read event for counter: " << event.connectionID.counter);
144 auto &buffer = m_messageBufferMap[event.connectionID.counter];
145 buffer.Push(event.rawBuffer);
147 // We can get several requests in one package.
148 // Extract and process them all
149 while(processOne(event.connectionID, buffer));
152 void GetGidService::close(const CloseEvent &event) {
153 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
154 m_messageBufferMap.erase(event.connectionID.counter);
157 } // namespace SecurityServer