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.
25 #include <sys/smack.h>
28 #include <dpl/log/log.h>
29 #include <dpl/serialization.h>
31 #include <protocols.h>
33 #include <security-server.h>
35 namespace SecurityServer {
37 GenericSocketService::ServiceDescriptionVector GetGidService::GetServiceDescription() {
38 ServiceDescription sd = {
41 SERVICE_SOCKET_GET_GID
43 ServiceDescriptionVector v;
48 void GetGidService::accept(const AcceptEvent &event) {
49 LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
50 << " ConnectionID.counter: " << event.connectionID.counter
51 << " ServiceID: " << event.interfaceID);
54 void GetGidService::write(const WriteEvent &event) {
55 LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
56 " Size: " << event.size << " Left: " << event.left);
58 m_serviceManager->Close(event.connectionID);
63 * Searches for group ID by given group name
65 int GetGidService::setGid(std::string& obj)
68 struct group *grpbuf = NULL;
70 std::vector<char> buf;
73 * The maximum needed size for buf can be found using sysconf(3)
74 * with the argument _SC_GETGR_R_SIZE_MAX. If _SC_GETGR_R_SIZE_MAX is not
75 * returned we set max_buf_size to 1024 bytes. Enough to store few groups.
77 long int maxBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
83 * There can be some corner cases when for example user is assigned to a
84 * lot of groups. In that case if buffer is to small getgrnam_r will
85 * return ERANGE error. Solution could be calling getgrnam_r with bigger
86 * buffer until it's big enough.
90 buf.resize(maxBufSize);
91 }catch(std::bad_alloc&) {
92 ret = SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY;
93 LogError("Out Of Memory");
97 } while ((ret = getgrnam_r(obj.c_str(), &grp, &(buf[0]), buf.size(), &grpbuf)) == ERANGE);
101 ret = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
102 LogError("getgrnam_r failed with error: " << strerror(errno));
105 } else if (grpbuf == NULL) {
106 ret = SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT;
107 LogError("Cannot find gid for group: " << obj);
111 m_gid = grpbuf->gr_gid;
117 bool GetGidService::readOne(const ConnectionID &conn, SocketBuffer &buffer) {
118 LogDebug("Iteration begin");
119 std::string objectName;
120 int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
122 if (!buffer.Ready()) {
128 SecurityServer::Deserialization des;
129 des.Deserialize(buffer, objectName);
130 } Catch (SocketBuffer::Exception::Base) {
131 LogDebug("Broken protocol. Closing socket.");
132 m_serviceManager->Close(conn);
137 retCode = setGid(objectName);
140 SecurityServer::Serialization ser;
141 SocketBuffer sendBuffer;
142 ser.Serialize(sendBuffer, retCode);
143 ser.Serialize(sendBuffer, m_gid);
144 m_serviceManager->Write(conn, sendBuffer.Pop());
148 void GetGidService::read(const ReadEvent &event) {
149 LogDebug("Read event for counter: " << event.connectionID.counter);
150 auto &buffer = m_socketBufferMap[event.connectionID.counter];
151 buffer.Push(event.rawBuffer);
153 // We can get several requests in one package.
154 // Extract and process them all
155 while(readOne(event.connectionID, buffer));
158 void GetGidService::close(const CloseEvent &event) {
159 LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
160 m_socketBufferMap.erase(event.connectionID.counter);
163 void GetGidService::error(const ErrorEvent &event) {
164 LogDebug("ErrorEvent. ConnectionID: " << event.connectionID.sock);
165 m_serviceManager->Close(event.connectionID);
168 } // namespace SecurityServer