Rewrite and fix CynaraAdmin::SetPolicies
[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 application and the user.
122      * Difference will be calculated, removing old unneeded privileges and
123      * adding new, previously not enabled privileges.
124      * Caller must have permission to access Cynara administrative socket.
125      *
126      * @param label application Smack label
127      * @param user user identifier
128      * @param privileges currently enabled privileges
129      *
130      */
131     void UpdateAppPolicy(const std::string &label, const std::string &user,
132         const std::vector<std::string> &privileges);
133
134     /**
135      * Depending on user type, create link between MAIN bucket and appropriate
136      * USER_TYPE_* bucket for newly added user uid to apply permissions for that
137      * user type.
138      * @throws CynaraException::InvalidParam.
139      *
140      * @param uid new user uid
141      * @param userType type as enumerated in security-manager.h
142      */
143     void UserInit(uid_t uid, security_manager_user_type userType);
144
145     /**
146      * List all users registered in Cynara
147      *
148      * @param[out] listOfUsers list of users
149      */
150     void ListUsers(std::vector<uid_t> &listOfUsers);
151
152     /**
153      * Removes all entries for a user from cynara database
154      *
155      * @param uid removed user uid
156      */
157     void UserRemove(uid_t uid);
158
159     /**
160      * List Cynara policies that match selected criteria in given bucket.
161      *
162      * @param bucketName name of the bucket to search policies in
163      * @param appId string with id of app to match in search
164      * @param user user string to match in search
165      * @param privilege privilege string to match in search
166      * @param policies empty vector for results of policies filtering.
167      *
168      */
169     void ListPolicies(const std::string &bucketName,
170         const std::string &appId,
171         const std::string &user,
172         const std::string &privilege,
173         std::vector<CynaraAdminPolicy> &policies);
174
175     /**
176      * Wrapper for Cynara API function cynara_admin_list_policies_descriptions.
177      * It collects all policies descriptions, extracts names
178      * of policies and returns as std strings. Caller is responsible for clearing
179      * vector passed as argument.
180      *
181      * @param policiesDescriptions empty vector for policies descriptions.
182      */
183     void ListPoliciesDescriptions(std::vector<std::string> &policiesDescriptions);
184
185     /**
186      * Function translates internal Cynara policy type integer to string
187      * description. Descriptions are retrieved from Cynara using
188      * ListPoliciesDescriptions() function. Caller can force refetching of
189      * descriptions list from Cynara on each call.
190      *
191      * @throws std::out_of_range
192      *
193      * @param policyType Cynara policy result type.
194      * @param forceRefresh switch to force refetching of descriptions from Cynara.
195      */
196     std::string convertToPolicyDescription(const int policyType, bool forceRefresh = false);
197
198     /**
199      * Function translates Cynara policy result string
200      * description to internal Cynara policy type integer.
201      * Descriptions are retrieved from Cynara using
202      * ListPoliciesDescriptions() function. Caller can force refetching of
203      * descriptions list from Cynara on each call.
204      *
205      * @throws std::out_of_range
206      *
207      * @param policy Cynara policy result string description.
208      * @param forceRefresh switch to force refetching of descriptions from Cynara.
209      */
210     int convertToPolicyType(const std::string &policy, bool forceRefresh = false);
211
212     /**
213      * Ask Cynara for permission starting the search at specified bucket.
214      * Essentialy a wrapper on cynara_admin_check.
215      *
216      * @param label application Smack label
217      * @param privilege privilege string to match in search
218      * @param user user string to match in search
219      * @param bucket name of the bucket to search policies in
220      * @param result integer to return policy result
221      * @param resultExtra string to return additional information about policy
222      *        result. If result is Bucket then resultExtra is the name of
223      *        bucket.
224      * @param recursive flag to indicate if check should be done recursively in
225      *        all buckets linked with bucket provided
226      */
227     void Check(const std::string &label,
228         const std::string &user,
229         const std::string &privilege,
230         const std::string &bucket,
231         int &result,
232         std::string &resultExtra,
233         const bool recursive);
234
235     /**
236      * Get current policy level for privilege-manager functionality
237      * Returns current policy value for given application, user and privilege
238      * identifiers.
239      *
240      * @param label application Smack label
241      * @param user user identifier (uid)
242      * @param privilege privilege identifier
243      * @return current policy value
244      */
245     int GetPrivilegeManagerCurrLevel(const std::string &label, const std::string &user,
246         const std::string &privilege);
247
248     /**
249      * Get maximum policy level for privilege-manager functionality
250      * Returns maximum possible policy value for given application, user and privilege
251      * identifiers. The maximum limit is imposed by other policy settings that are
252      * currently in place.
253      *
254      * @param label application Smack label
255      * @param user user identifier (uid)
256      * @param privilege privilege identifier
257      * @return maximum policy value for PRIVACY_MANAGER bucket
258      */
259     int GetPrivilegeManagerMaxLevel(const std::string &label, const std::string &user,
260         const std::string &privilege);
261
262 private:
263     CynaraAdmin();
264
265     /**
266      * Empty bucket using filter - matching rules will be removed
267      *
268      * @param bucketName name of the bucket to be emptied
269      * @param recursive flag to remove privileges recursively
270      * @param client client name
271      * @param user user name
272      * @param privilege privilege name
273      */
274     void EmptyBucket(const std::string &bucketName, bool recursive,
275         const std::string &client, const std::string &user, const std::string &privilege);
276
277     /**
278      * Get Cynara policies result descriptions and cache them in std::map
279      *
280      * @param forceRefresh true if you want to reinitialize mappings
281      */
282     void FetchCynaraPolicyDescriptions(bool forceRefresh = false);
283
284     struct cynara_admin *m_CynaraAdmin;
285
286     static TypeToDescriptionMap TypeToDescription;
287     static DescriptionToTypeMap DescriptionToType;
288     bool m_policyDescriptionsInitialized;
289 };
290
291 class Cynara
292 {
293 public:
294     ~Cynara();
295
296     static Cynara &getInstance();
297
298     /**
299      * Ask Cynara for permission.
300      *
301      * @param label application Smack label
302      * @param privilege privilege identifier
303      * @param user user identifier (uid)
304      * @param session session identifier
305      * @return true if access is permitted, false if denied
306      */
307     bool check(const std::string &label, const std::string &privilege,
308         const std::string &user, const std::string &session);
309
310 private:
311     Cynara();
312
313     static void statusCallback(int oldFd, int newFd,
314         cynara_async_status status, void *ptr);
315
316     static void responseCallback(cynara_check_id checkId,
317         cynara_async_call_cause cause, int response, void *ptr);
318
319     void run();
320
321     void threadNotifyPut();
322     void threadNotifyGet();
323
324     cynara_async *cynara;
325     struct pollfd pollFds[2];
326     std::mutex mutex;
327     std::thread thread;
328     std::atomic<bool> terminate{false};
329 };
330
331 } // namespace SecurityManager
332
333 #endif // _SECURITY_MANAGER_CYNARA_