aa0ed601c72a9f7a0c2b5e1faf4c6601f75ddf39
[platform/core/security/security-manager.git] / src / common / include / cynara.h
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Rafal Krypa <r.krypa@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        cynara.h
20  * @author      Rafal Krypa <r.krypa@samsung.com>
21  * @brief       Wrapper class for Cynara interface
22  */
23
24 #ifndef _SECURITY_MANAGER_CYNARA_
25 #define _SECURITY_MANAGER_CYNARA_
26
27 #include <cynara-client-async.h>
28 #include <cynara-admin.h>
29 #include <dpl/exception.h>
30 #include <string>
31 #include <vector>
32 #include <map>
33 #include <mutex>
34 #include <thread>
35 #include <future>
36
37 #include <poll.h>
38 #include <sys/eventfd.h>
39
40 #include "security-manager.h"
41
42 namespace SecurityManager {
43
44 enum class Bucket
45 {
46     PRIVACY_MANAGER,
47     MAIN,
48     USER_TYPE_ADMIN,
49     USER_TYPE_NORMAL,
50     USER_TYPE_GUEST,
51     USER_TYPE_SYSTEM,
52     ADMIN,
53     MANIFESTS
54 };
55
56 class CynaraException
57 {
58 public:
59     DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
60     DECLARE_EXCEPTION_TYPE(Base, MaxPendingRequests)
61     DECLARE_EXCEPTION_TYPE(Base, OutOfMemory)
62     DECLARE_EXCEPTION_TYPE(Base, InvalidParam)
63     DECLARE_EXCEPTION_TYPE(Base, ServiceNotAvailable)
64     DECLARE_EXCEPTION_TYPE(Base, MethodNotSupported)
65     DECLARE_EXCEPTION_TYPE(Base, OperationNotAllowed)
66     DECLARE_EXCEPTION_TYPE(Base, OperationFailed)
67     DECLARE_EXCEPTION_TYPE(Base, BucketNotFound)
68     DECLARE_EXCEPTION_TYPE(Base, UnknownError)
69 };
70
71 struct CynaraAdminPolicy : cynara_admin_policy
72 {
73     enum class Operation {
74         Deny = CYNARA_ADMIN_DENY,
75         Allow = CYNARA_ADMIN_ALLOW,
76         Delete = CYNARA_ADMIN_DELETE,
77         Bucket = CYNARA_ADMIN_BUCKET,
78     };
79
80     CynaraAdminPolicy(const std::string &client, const std::string &user,
81         const std::string &privilege, int operation,
82         const std::string &bucket = std::string(CYNARA_ADMIN_DEFAULT_BUCKET));
83
84     CynaraAdminPolicy(const std::string &client, const std::string &user,
85         const std::string &privilege, const std::string &goToBucket,
86         const std::string &bucket = std::string(CYNARA_ADMIN_DEFAULT_BUCKET));
87
88     /* Don't provide copy constructor, it would cause pointer trouble. */
89     CynaraAdminPolicy(const CynaraAdminPolicy &that) = delete;
90
91     /* Move constructor is the way to go. */
92     CynaraAdminPolicy(CynaraAdminPolicy &&that);
93     CynaraAdminPolicy& operator=(CynaraAdminPolicy &&that);
94
95     ~CynaraAdminPolicy();
96 };
97
98 class CynaraAdmin
99 {
100 public:
101
102     typedef std::map<Bucket, const std::string > BucketsMap;
103     static BucketsMap Buckets;
104
105     typedef  std::map<int, std::string> TypeToDescriptionMap;
106     typedef  std::map<std::string, int> DescriptionToTypeMap;
107
108     virtual ~CynaraAdmin();
109
110     static CynaraAdmin &getInstance();
111
112     /**
113      * Update Cynara policies.
114      * Caller must have permission to access Cynara administrative socket.
115      *
116      * @param policies vector of CynaraAdminPolicy objects to send to Cynara
117      */
118     void SetPolicies(const std::vector<CynaraAdminPolicy> &policies);
119
120     /**
121      * Update Cynara policies for the package and the user, using two vectors
122      * of privileges: privileges set before (and already enabled in Cynara)
123      * and new privileges, to be set in Cynara.
124      * Difference will be calculated, removing old unneeded privileges and
125      * adding new, previously not enabled privileges.
126      * Caller must have permission to access Cynara administrative socket.
127      *
128      * @param label application Smack label
129      * @param user user identifier
130      * @param oldPrivileges previously enabled privileges for the package.
131      *        Must be sorted and without duplicates.
132      * @param newPrivileges currently enabled privileges for the package.
133      *        Must be sorted and without duplicates.
134      *
135      * TODO: drop oldPrivileges argument and get them directly from Cynara.
136      * Appropriate Cynara interface is needed first.
137      */
138     void UpdateAppPolicy(const std::string &label, const std::string &user,
139         const std::vector<std::string> &oldPrivileges,
140         const std::vector<std::string> &newPrivileges);
141
142     /**
143      * Depending on user type, create link between MAIN bucket and appropriate
144      * USER_TYPE_* bucket for newly added user uid to apply permissions for that
145      * user type.
146      * @throws CynaraException::InvalidParam.
147      *
148      * @param uid new user uid
149      * @param userType type as enumerated in security-manager.h
150      */
151     void UserInit(uid_t uid, security_manager_user_type userType);
152
153     /**
154      * List all users registered in Cynara
155      *
156      * @param[out] listOfUsers list of users
157      */
158     void ListUsers(std::vector<uid_t> &listOfUsers);
159
160     /**
161      * Removes all entries for a user from cynara database
162      *
163      * @param uid removed user uid
164      */
165     void UserRemove(uid_t uid);
166
167     /**
168      * List Cynara policies that match selected criteria in given bucket.
169      *
170      * @param bucketName name of the bucket to search policies in
171      * @param appId string with id of app to match in search
172      * @param user user string to match in search
173      * @param privilege privilege string to match in search
174      * @param policies empty vector for results of policies filtering.
175      *
176      */
177     void ListPolicies(const std::string &bucketName,
178         const std::string &appId,
179         const std::string &user,
180         const std::string &privilege,
181         std::vector<CynaraAdminPolicy> &policies);
182
183     /**
184      * Wrapper for Cynara API function cynara_admin_list_policies_descriptions.
185      * It collects all policies descriptions, extracts names
186      * of policies and returns as std strings. Caller is responsible for clearing
187      * vector passed as argument.
188      *
189      * @param policiesDescriptions empty vector for policies descriptions.
190      */
191     void ListPoliciesDescriptions(std::vector<std::string> &policiesDescriptions);
192
193     /**
194      * Function translates internal Cynara policy type integer to string
195      * description. Descriptions are retrieved from Cynara using
196      * ListPoliciesDescriptions() function. Caller can force refetching of
197      * descriptions list from Cynara on each call.
198      *
199      * @throws std::out_of_range
200      *
201      * @param policyType Cynara policy result type.
202      * @param forceRefresh switch to force refetching of descriptions from Cynara.
203      */
204     std::string convertToPolicyDescription(const int policyType, bool forceRefresh = false);
205
206     /**
207      * Function translates Cynara policy result string
208      * description to internal Cynara policy type integer.
209      * Descriptions are retrieved from Cynara using
210      * ListPoliciesDescriptions() function. Caller can force refetching of
211      * descriptions list from Cynara on each call.
212      *
213      * @throws std::out_of_range
214      *
215      * @param policy Cynara policy result string description.
216      * @param forceRefresh switch to force refetching of descriptions from Cynara.
217      */
218     int convertToPolicyType(const std::string &policy, bool forceRefresh = false);
219
220     /**
221      * Ask Cynara for permission starting the search at specified bucket.
222      * Essentialy a wrapper on cynara_admin_check.
223      *
224      * @param label application Smack label
225      * @param privilege privilege string to match in search
226      * @param user user string to match in search
227      * @param bucket name of the bucket to search policies in
228      * @param result integer to return policy result
229      * @param resultExtra string to return additional information about policy
230      *        result. If result is Bucket then resultExtra is the name of
231      *        bucket.
232      * @param recursive flag to indicate if check should be done recursively in
233      *        all buckets linked with bucket provided
234      */
235     void Check(const std::string &label,
236         const std::string &user,
237         const std::string &privilege,
238         const std::string &bucket,
239         int &result,
240         std::string &resultExtra,
241         const bool recursive);
242
243     /**
244      * Get current policy level for privilege-manager functionality
245      * Returns current policy value for given application, user and privilege
246      * identifiers.
247      *
248      * @param label application Smack label
249      * @param user user identifier (uid)
250      * @param privilege privilege identifier
251      * @return current policy value
252      */
253     int GetPrivilegeManagerCurrLevel(const std::string &label, const std::string &user,
254         const std::string &privilege);
255
256     /**
257      * Get maximum policy level for privilege-manager functionality
258      * Returns maximum possible policy value for given application, user and privilege
259      * identifiers. The maximum limit is imposed by other policy settings that are
260      * currently in place.
261      *
262      * @param label application Smack label
263      * @param user user identifier (uid)
264      * @param privilege privilege identifier
265      * @return maximum policy value for PRIVACY_MANAGER bucket
266      */
267     int GetPrivilegeManagerMaxLevel(const std::string &label, const std::string &user,
268         const std::string &privilege);
269
270 private:
271     CynaraAdmin();
272
273     /**
274      * Empty bucket using filter - matching rules will be removed
275      *
276      * @param bucketName name of the bucket to be emptied
277      * @param recursive flag to remove privileges recursively
278      * @param client client name
279      * @param user user name
280      * @param privilege privilege name
281      */
282     void EmptyBucket(const std::string &bucketName, bool recursive,
283         const std::string &client, const std::string &user, const std::string &privilege);
284
285     /**
286      * Get Cynara policies result descriptions and cache them in std::map
287      *
288      * @param forceRefresh true if you want to reinitialize mappings
289      */
290     void FetchCynaraPolicyDescriptions(bool forceRefresh = false);
291
292     struct cynara_admin *m_CynaraAdmin;
293
294     static TypeToDescriptionMap TypeToDescription;
295     static DescriptionToTypeMap DescriptionToType;
296     bool m_policyDescriptionsInitialized;
297 };
298
299 class Cynara
300 {
301 public:
302     ~Cynara();
303
304     static Cynara &getInstance();
305
306     /**
307      * Ask Cynara for permission.
308      *
309      * @param label application Smack label
310      * @param privilege privilege identifier
311      * @param user user identifier (uid)
312      * @param session session identifier
313      * @return true if access is permitted, false if denied
314      */
315     bool check(const std::string &label, const std::string &privilege,
316         const std::string &user, const std::string &session);
317
318 private:
319     Cynara();
320
321     static void statusCallback(int oldFd, int newFd,
322         cynara_async_status status, void *ptr);
323
324     static void responseCallback(cynara_check_id checkId,
325         cynara_async_call_cause cause, int response, void *ptr);
326
327     void run();
328
329     void threadNotifyPut();
330     void threadNotifyGet();
331
332     cynara_async *cynara;
333     struct pollfd pollFds[2];
334     std::mutex mutex;
335     std::thread thread;
336     std::atomic<bool> terminate{false};
337 };
338
339 } // namespace SecurityManager
340
341 #endif // _SECURITY_MANAGER_CYNARA_