fdcb2fcf0050a61b634e94f088fc7ca100305c27
[framework/security/security-server.git] / src / server2 / service / get-object-name.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        get-object-name.cpp
20  * @author      Jan Olszak (j.olszak@samsung.com)
21  * @version     1.0
22  * @brief       Implementation of api-get-object-name service.
23  */
24
25 #include <sys/smack.h>
26 #include <grp.h>
27
28 #include <dpl/log/log.h>
29 #include <dpl/serialization.h>
30
31 #include <protocols.h>
32 #include <get-object-name.h>
33 #include <security-server.h>
34
35 #include <vector>
36
37 namespace SecurityServer {
38
39 GetObjectNameService::ServiceDescriptionVector GetObjectNameService::GetServiceDescription() {
40     ServiceDescription sd = {
41         "*",
42         0,
43         SERVICE_SOCKET_GET_OBJECT_NAME
44     };
45     ServiceDescriptionVector v;
46     v.push_back(sd);
47     return v;
48 }
49
50 void GetObjectNameService::accept(const AcceptEvent &event) {
51     LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock
52         << " ConnectionID.counter: " << event.connectionID.counter
53         << " ServiceID: " << event.interfaceID);
54 }
55
56 void GetObjectNameService::write(const WriteEvent &event) {
57     LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
58         " Size: " << event.size << " Left: " << event.left);
59     if (event.left == 0)
60         m_serviceManager->Close(event.connectionID);
61 }
62
63
64
65 /*
66  * Searches for group NAME by given group id
67  */
68 int GetObjectNameService::setName(const gid_t gid)
69 {
70     int ret = 0;
71     struct group *grpbuf = NULL;
72     struct group grp;
73     std::vector<char> buf;
74
75     /*
76      * The maximum needed size for buf can be found using sysconf(3)
77      * with the argument _SC_GETGR_R_SIZE_MAX. If _SC_GETGR_R_SIZE_MAX is not
78      * returned we set max_buf_size to 1024 bytes. Enough to store few groups.
79      */
80     long int maxBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
81     if (maxBufSize == -1)
82         maxBufSize = 1024;
83
84
85     /*
86      * There can be some corner cases when for example user is assigned to a
87      * lot of groups. In that case if buffer is to small getgrnam_r will
88      * return ERANGE error. Solution could be calling getgrnam_r with bigger
89      * buffer until it's big enough.
90      */
91     do {
92         try{
93             buf.resize(maxBufSize);
94         }catch(std::bad_alloc&) {
95             ret = SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY;
96             LogError("Out Of Memory");
97             return ret;
98         }
99         maxBufSize *= 2;
100
101     } while ((ret = getgrgid_r(gid, &grp, &(buf[0]), buf.size(), &grpbuf)) == ERANGE);
102
103     // Check for errors:
104     if (ret != 0){
105         ret = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
106         LogError("getgrgid_r failed with error: " << strerror(errno));
107         return ret;
108
109     } else if (grpbuf == NULL) {
110         ret = SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT;
111         LogError("Cannot find name for group: " << gid);
112         return ret;
113     }
114
115     m_name = grpbuf->gr_name;
116
117     return ret;
118 }
119
120
121 bool GetObjectNameService::readOne(const ConnectionID &conn, SocketBuffer &buffer) {
122     LogDebug("Iteration begin");
123     gid_t gid;
124     int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
125     if (!buffer.Ready()) {
126         LogDebug("Got part of message. Service is waiting for the rest.");
127         return false;
128     }
129
130     // Get objects GID:
131     Try {
132         SecurityServer::Deserialization des;
133         des.Deserialize(buffer, gid);
134      } Catch (SocketBuffer::Exception::Base) {
135         LogDebug("Broken protocol. Closing socket.");
136         m_serviceManager->Close(conn);
137         return false;
138     }
139
140     // Get name
141     retCode = setName(gid);
142
143     // Send the result
144     SecurityServer::Serialization ser;
145     SocketBuffer sendBuffer;
146     ser.Serialize(sendBuffer, retCode);
147     ser.Serialize(sendBuffer, m_name);
148     m_serviceManager->Write(conn, sendBuffer.Pop());
149     return true;
150 }
151
152 void GetObjectNameService::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);
156
157     LogDebug("Pushed to buffer ptr: " << (void*)&buffer);
158
159     // We can get several requests in one package.
160     // Extract and process them all
161     while(readOne(event.connectionID, buffer));
162 }
163
164 void GetObjectNameService::close(const CloseEvent &event) {
165     LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
166     m_socketBufferMap.erase(event.connectionID.counter);
167 }
168
169 void GetObjectNameService::error(const ErrorEvent &event) {
170     LogError("ErrorEvent. ConnectionID: " << event.connectionID.sock);
171     m_serviceManager->Close(event.connectionID);
172 }
173
174 } // namespace SecurityServer
175