Add smackfs check to Installer service.
[platform/core/security/security-manager.git] / src / server / service / get-gid.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-gid.cpp
20  * @author      Jan Olszak (j.olszak@samsung.com)
21  * @version     1.0
22  * @brief       Implementation of api-get-gid service.
23  */
24
25 #include <unistd.h>
26 #include <sys/smack.h>
27 #include <grp.h>
28 #include <unistd.h>
29
30 #include <dpl/log/log.h>
31 #include <dpl/serialization.h>
32
33 #include <protocols.h>
34 #include <get-gid.h>
35 #include <security-server.h>
36
37 namespace SecurityServer {
38
39 GenericSocketService::ServiceDescriptionVector GetGidService::GetServiceDescription() {
40     return ServiceDescriptionVector
41         {{SERVICE_SOCKET_GET_GID, "security-server::api-get-gid"}};
42 }
43
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);
48 }
49
50 void GetGidService::write(const WriteEvent &event) {
51     LogDebug("WriteEvent. ConnectionID: " << event.connectionID.sock <<
52         " Size: " << event.size << " Left: " << event.left);
53     if (event.left == 0)
54         m_serviceManager->Close(event.connectionID);
55 }
56
57
58 /*
59  * Searches for group ID by given group name
60  */
61 int GetGidService::setGid(std::string& obj)
62 {
63     int ret = 0;
64     struct group *grpbuf = NULL;
65     struct group grp;
66     std::vector<char> buf;
67
68     /*
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.
72      */
73     long int maxBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
74     if (maxBufSize == -1)
75         maxBufSize = 1024;
76
77
78     /*
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.
83      */
84     do {
85         try{
86             buf.resize(maxBufSize);
87         }catch(std::bad_alloc&) {
88             ret = SECURITY_SERVER_API_ERROR_OUT_OF_MEMORY;
89             LogError("Out Of Memory");
90             return ret;
91         }
92         maxBufSize *= 2;
93     } while ((ret = getgrnam_r(obj.c_str(), &grp, &(buf[0]), buf.size(), &grpbuf)) == ERANGE);
94
95     // Check for errors:
96     if (ret != 0){
97         ret = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
98         LogError("getgrnam_r failed with error: " << strerror(errno));
99         return ret;
100
101     } else if (grpbuf == NULL) {
102         ret = SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT;
103         LogError("Cannot find gid for group: " << obj);
104         return ret;
105     }
106
107     m_gid = grpbuf->gr_gid;
108
109     return ret;
110 }
111
112
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;
117
118     if (!buffer.Ready()) {
119         return false;
120     }
121
122     // Get objects name:
123     Try {
124         Deserialization::Deserialize(buffer, objectName);
125      } Catch (MessageBuffer::Exception::Base) {
126         LogDebug("Broken protocol. Closing socket.");
127         m_serviceManager->Close(conn);
128         return false;
129     }
130
131     // Get GID
132     retCode = setGid(objectName);
133
134     // Send the result
135     MessageBuffer sendBuffer;
136     Serialization::Serialize(sendBuffer, retCode);
137     Serialization::Serialize(sendBuffer, m_gid);
138     m_serviceManager->Write(conn, sendBuffer.Pop());
139     return true;
140 }
141
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);
146
147     // We can get several requests in one package.
148     // Extract and process them all
149     while(processOne(event.connectionID, buffer));
150 }
151
152 void GetGidService::close(const CloseEvent &event) {
153     LogDebug("CloseEvent. ConnectionID: " << event.connectionID.sock);
154     m_messageBufferMap.erase(event.connectionID.counter);
155 }
156
157 } // namespace SecurityServer
158