Add missing header files in cookie module.
[platform/core/security/security-manager.git] / src / server2 / service / cookie-jar.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        cookie-jar.cpp
20  * @author      Pawel Polawski (p.polawski@partner.samsung.com)
21  * @version     1.0
22  * @brief       This function contain implementation of CookieJar class which holds cookies structures
23  */
24
25 #include <cookie-jar.h>
26 #include <protocols.h>
27 #include <dpl/log/log.h>
28 #include <dpl/exception.h>
29 #include <vector>
30 #include <stdbool.h>
31 #include <unistd.h>
32 #include <smack-check.h>
33 #include <privilege-control.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/smack.h>
38 #include <fstream>
39 #include <linux/limits.h>
40
41 namespace SecurityServer {
42
43 CookieJar::CookieJar(void)
44 {
45     LogDebug("Created CookieJar for handling cookies");
46 }
47
48 CookieJar::~CookieJar(void)
49 {
50     LogDebug("Deleted CookieJar");
51 }
52
53 const Cookie * CookieJar::GenerateCookie(int pid)
54 {
55     char key[COOKIE_SIZE];
56     int retval;
57
58     LogDebug("Cookie creation called");
59
60     //create empty cookie class
61     Cookie newCookie;
62     newCookie.pid = pid;
63
64     //check if there is no cookie for specified PID
65     const Cookie *searchResult = SearchCookie(newCookie, CompareType::PID);
66     if (searchResult != NULL) {
67         LogDebug("Cookie exist for specified PID");
68         return searchResult;
69     }
70
71     searchResult = &newCookie;   //only for searchResult != NULL
72     while(searchResult != NULL) {
73         //generate unique key
74         std::ifstream urandom("/dev/urandom", std::ifstream::binary);
75         urandom.read(key, COOKIE_SIZE);
76         newCookie.cookieId.assign(key, key + COOKIE_SIZE);
77
78         //check if key is unique
79         searchResult = SearchCookie(newCookie, CompareType::COOKIE_ID);
80         if (searchResult != NULL)
81             LogDebug("Key is not unique");
82     }
83
84     //obtain process path
85     char link[PATH_MAX];
86     char path[PATH_MAX];
87
88     snprintf(link, PATH_MAX, "/proc/%d/exe", pid);
89     retval = readlink(link, path, PATH_MAX);
90     if (retval < 0) {
91         LogDebug("Unable to get process path");
92         return NULL;
93     }
94     path[retval] = '\0';
95     newCookie.binaryPath = path;
96
97     //get smack label if smack enabled
98     if (smack_check()) {
99         char label[SMACK_LABEL_LEN + 1];
100         retval = get_smack_label_from_process(pid, label);
101         if (retval != PC_OPERATION_SUCCESS) {
102             LogDebug("Unable to get smack label of process");
103             return NULL;
104         }
105         newCookie.smackLabel = label;
106     } else
107         newCookie.smackLabel = "smack_disabled";
108
109
110     //get GID list
111     const int LINE_LEN = 128;
112     const int NAME_SIZE = 64;
113     char line[LINE_LEN]; //for storing parsed lines
114     char filename[NAME_SIZE];
115
116     snprintf(filename, NAME_SIZE, "/proc/%d/status", pid);
117     std::ifstream status(filename, std::ifstream::binary);
118
119     while (status.getline(line, LINE_LEN)) {  //read line from file
120         if (strncmp(line, "Groups:", 7) == 0)
121             break;
122     }
123
124     char delim[] = ": ";    //separators for strtok: ' ' and ':'
125     char *token = strtok(line, delim);  //1st string is "Group:"
126     while ((token = strtok(NULL, delim))) {
127         int gid = atoi(token);
128         newCookie.permissions.push_back(gid);
129     }
130
131     //DEBUG ONLY
132     //print info about cookie
133     LogDebug("Cookie created");
134     LogDebug("PID: " << newCookie.pid);
135     LogDebug("PATH: " << newCookie.binaryPath);
136     LogDebug("LABEL: " << newCookie.smackLabel);
137     for (size_t k = 0; k < newCookie.permissions.size(); k++)
138         LogDebug("GID: " << newCookie.permissions[k]);
139
140     m_cookieList.push_back(newCookie);
141     return &m_cookieList[m_cookieList.size() - 1];
142 }
143
144 void CookieJar::DeleteCookie(const Cookie &pattern, CompareType criterion)
145 {
146     if (m_cookieList.size() == 0) {
147         LogDebug("Cookie list empty");
148         return;
149     }
150
151     //for each cookie in list
152     for (size_t i = 0; i < m_cookieList.size();) {
153         if (CompareCookies(pattern, m_cookieList[i], criterion)) {
154             LogDebug("Deleting cookie");
155             if (i != m_cookieList.size() - 1)
156                 m_cookieList[i] = *m_cookieList.rbegin();
157             m_cookieList.pop_back();
158         } else
159             ++i;
160     }
161 }
162
163 const Cookie * CookieJar::SearchCookie(const Cookie &pattern, CompareType criterion) const
164 {
165     LogDebug("Searching for cookie");
166
167     if (m_cookieList.size() == 0) {
168         LogDebug("Cookie list empty");
169         return NULL;
170     }
171
172     //for each cookie in list
173     for (size_t i = 0; i < m_cookieList.size(); i++) {
174         if (CompareCookies(pattern, m_cookieList[i], criterion)) {
175             LogDebug("Cookie found");
176             return &(m_cookieList[i]);
177         }
178     }
179
180     LogDebug("Cookie not found");
181     return NULL;
182 }
183
184 bool CookieJar::CompareCookies(const Cookie &c1, const Cookie &c2, CompareType criterion) const
185 {
186     size_t permSize1 = c1.permissions.size();
187     size_t permSize2 = c2.permissions.size();
188
189     switch(criterion) {
190     case CompareType::COOKIE_ID:
191         return (c1.cookieId == c2.cookieId);
192
193     case CompareType::PID:
194         return (c1.pid == c2.pid);
195
196     case CompareType::PATH:
197         return (c1.binaryPath == c2.binaryPath);
198
199     case CompareType::SMACKLABEL:
200         return (c1.smackLabel == c2.smackLabel);
201
202     case CompareType::PERMISSIONS:
203         //we search for at least one the same GID
204         for(size_t i = 0; i < permSize1; i++)
205             for (size_t k = 0; k < permSize2; k++)
206                 if (c1.permissions[i] == c2.permissions[k])
207                     return true;
208         return false;
209
210     default:
211         LogDebug("Wrong function parameters");
212         return false;
213     };
214 }
215
216 } // namespace SecurityServer