Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2015 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <talloc.h>
22 : #include <tevent.h>
23 :
24 : #include "db/sysdb.h"
25 : #include "util/util.h"
26 : #include "responder/common/responder.h"
27 : #include "responder/ifp/ifp_cache.h"
28 : #include "responder/ifp/ifp_users.h"
29 : #include "responder/ifp/ifp_groups.h"
30 : #include "responder/ifp/ifp_iface_generated.h"
31 :
32 : static struct ldb_dn *
33 0 : ifp_cache_build_base_dn(TALLOC_CTX *mem_ctx,
34 : enum ifp_cache_type type,
35 : struct sss_domain_info *domain)
36 : {
37 0 : struct ldb_dn *base_dn = NULL;
38 :
39 0 : switch (type) {
40 : case IFP_CACHE_USER:
41 0 : base_dn = sysdb_user_base_dn(mem_ctx, domain);
42 0 : break;
43 : case IFP_CACHE_GROUP:
44 0 : base_dn = sysdb_group_base_dn(mem_ctx, domain);
45 0 : break;
46 : }
47 :
48 0 : return base_dn;
49 : }
50 :
51 : static char *
52 0 : ifp_cache_build_path(TALLOC_CTX *mem_ctx,
53 : enum ifp_cache_type type,
54 : struct sss_domain_info *domain,
55 : struct ldb_message *msg)
56 : {
57 0 : char *path = NULL;
58 :
59 0 : switch (type) {
60 : case IFP_CACHE_USER:
61 0 : path = ifp_users_build_path_from_msg(mem_ctx, domain, msg);
62 0 : break;
63 : case IFP_CACHE_GROUP:
64 0 : path = ifp_groups_build_path_from_msg(mem_ctx, domain, msg);
65 0 : break;
66 : }
67 :
68 0 : return path;
69 : }
70 :
71 : static const char *
72 0 : ifp_cache_object_class(enum ifp_cache_type type)
73 : {
74 0 : const char *class = NULL;
75 :
76 0 : switch (type) {
77 : case IFP_CACHE_USER:
78 0 : class = SYSDB_USER_CLASS;
79 0 : break;
80 : case IFP_CACHE_GROUP:
81 0 : class = SYSDB_GROUP_CLASS;
82 0 : break;
83 : }
84 :
85 0 : return class;
86 : }
87 :
88 : static errno_t
89 0 : ifp_cache_get_cached_objects(TALLOC_CTX *mem_ctx,
90 : enum ifp_cache_type type,
91 : struct sss_domain_info *domain,
92 : const char ***_paths,
93 : int *_num_paths)
94 : {
95 : TALLOC_CTX *tmp_ctx;
96 : struct ldb_dn *base_dn;
97 : struct ldb_result *result;
98 0 : const char *class = ifp_cache_object_class(type);
99 : const char **paths;
100 : errno_t ret;
101 : int ldb_ret;
102 : int i;
103 0 : const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_UIDNUM,
104 : SYSDB_GIDNUM, NULL};
105 :
106 0 : tmp_ctx = talloc_new(NULL);
107 0 : if (tmp_ctx == NULL) {
108 0 : return ENOMEM;
109 : }
110 :
111 0 : base_dn = ifp_cache_build_base_dn(tmp_ctx, type, domain);
112 0 : if (base_dn == NULL) {
113 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create base dn\n");
114 0 : ret = ENOMEM;
115 0 : goto done;
116 : }
117 :
118 0 : ldb_ret = ldb_search(sysdb_ctx_get_ldb(domain->sysdb), tmp_ctx, &result,
119 : base_dn, LDB_SCOPE_SUBTREE, attrs,
120 : "(&(objectClass=%s)(%s=TRUE))", class,
121 : SYSDB_IFP_CACHED);
122 0 : if (ldb_ret != LDB_SUCCESS) {
123 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to search the cache\n");
124 0 : ret = sysdb_error_to_errno(ldb_ret);
125 0 : goto done;
126 : }
127 :
128 0 : paths = talloc_zero_array(tmp_ctx, const char *, result->count + 1);
129 0 : if (paths == NULL) {
130 0 : ret = ENOMEM;
131 0 : goto done;
132 : }
133 :
134 0 : for (i = 0; i < result->count; i++) {
135 0 : paths[i] = ifp_cache_build_path(paths, type, domain, result->msgs[i]);
136 0 : if (paths[i] == NULL) {
137 0 : ret = ENOMEM;
138 0 : goto done;
139 : }
140 : }
141 :
142 0 : *_paths = talloc_steal(mem_ctx, paths);
143 0 : *_num_paths = result->count;
144 :
145 0 : ret = EOK;
146 :
147 : done:
148 0 : talloc_free(tmp_ctx);
149 0 : return ret;
150 : }
151 :
152 0 : errno_t ifp_cache_list_domains(TALLOC_CTX *mem_ctx,
153 : struct sss_domain_info *domains,
154 : enum ifp_cache_type type,
155 : const char ***_paths,
156 : int *_num_paths)
157 : {
158 : TALLOC_CTX *tmp_ctx;
159 : struct sss_domain_info *domain;
160 : const char **tmp_paths;
161 : int num_tmp_paths;
162 : const char **paths;
163 : int num_paths;
164 : errno_t ret;
165 :
166 0 : tmp_ctx = talloc_new(NULL);
167 0 : if (tmp_ctx == NULL) {
168 0 : return ENOMEM;
169 : }
170 :
171 0 : domain = domains;
172 0 : num_paths = 0;
173 0 : paths = NULL;
174 0 : while (domain != NULL) {
175 0 : ret = ifp_cache_get_cached_objects(tmp_ctx, type, domain,
176 : &tmp_paths, &num_tmp_paths);
177 0 : if (ret != EOK) {
178 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list "
179 : "[%d]: %s\n", ret, sss_strerror(ret));
180 0 : goto done;
181 : }
182 :
183 0 : ret = add_strings_lists(tmp_ctx, paths, tmp_paths, true,
184 : discard_const(&paths));
185 0 : if (ret != EOK) {
186 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list "
187 : "[%d]: %s\n", ret, sss_strerror(ret));
188 0 : goto done;
189 : }
190 :
191 0 : num_paths += num_tmp_paths;
192 :
193 0 : domain = get_next_domain(domain, true);
194 : }
195 :
196 0 : if (_paths != NULL) {
197 0 : *_paths = talloc_steal(mem_ctx, paths);
198 : }
199 :
200 0 : if (_num_paths != NULL) {
201 0 : *_num_paths = num_paths;
202 : }
203 :
204 0 : ret = EOK;
205 :
206 : done:
207 0 : talloc_free(tmp_ctx);
208 0 : return ret;
209 : }
210 :
211 0 : int ifp_cache_list(struct sbus_request *sbus_req,
212 : void *data,
213 : enum ifp_cache_type type)
214 : {
215 : DBusError *error;
216 : struct ifp_ctx *ifp_ctx;
217 : const char **paths;
218 : int num_paths;
219 : errno_t ret;
220 :
221 0 : ifp_ctx = talloc_get_type(data, struct ifp_ctx);
222 0 : if (ifp_ctx == NULL) {
223 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
224 0 : return ERR_INTERNAL;
225 : }
226 :
227 0 : ret = ifp_cache_list_domains(sbus_req, ifp_ctx->rctx->domains, type,
228 : &paths, &num_paths);
229 0 : if (ret != EOK) {
230 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED,
231 : "Unable to build object list [%d]: %s\n",
232 : ret, sss_strerror(ret));
233 0 : return sbus_request_fail_and_finish(sbus_req, error);
234 : }
235 :
236 0 : iface_ifp_cache_List_finish(sbus_req, paths, num_paths);
237 :
238 0 : return EOK;
239 : }
240 :
241 0 : int ifp_cache_list_by_domain(struct sbus_request *sbus_req,
242 : void *data,
243 : const char *domainname,
244 : enum ifp_cache_type type)
245 : {
246 : DBusError *error;
247 : struct sss_domain_info *domain;
248 : struct ifp_ctx *ifp_ctx;
249 : const char **paths;
250 : int num_paths;
251 : errno_t ret;
252 :
253 0 : ifp_ctx = talloc_get_type(data, struct ifp_ctx);
254 0 : if (ifp_ctx == NULL) {
255 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
256 0 : return ERR_INTERNAL;
257 : }
258 :
259 0 : domain = find_domain_by_name(ifp_ctx->rctx->domains, domainname, true);
260 0 : if (domain == NULL) {
261 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Unknown domain");
262 0 : return sbus_request_fail_and_finish(sbus_req, error);
263 : }
264 :
265 0 : ret = ifp_cache_get_cached_objects(sbus_req, type, domain,
266 : &paths, &num_paths);
267 0 : if (ret != EOK) {
268 0 : error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Unable to build "
269 : "object list [%d]: %s\n", ret, sss_strerror(ret));
270 0 : return sbus_request_fail_and_finish(sbus_req, error);
271 : }
272 :
273 0 : iface_ifp_cache_ListByDomain_finish(sbus_req, paths, num_paths);
274 :
275 0 : return EOK;
276 : }
277 :
278 0 : static errno_t ifp_cache_object_set(struct sss_domain_info *domain,
279 : struct ldb_dn *dn,
280 : bool value)
281 : {
282 : struct sysdb_attrs *attrs;
283 : errno_t ret;
284 :
285 0 : attrs = sysdb_new_attrs(NULL);
286 0 : if (attrs == NULL) {
287 0 : return ENOMEM;
288 : }
289 :
290 0 : ret = sysdb_attrs_add_bool(attrs, SYSDB_IFP_CACHED, value);
291 0 : if (ret != EOK) {
292 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute [%d]: %s\n",
293 : ret, sss_strerror(ret));
294 0 : goto done;
295 : }
296 :
297 0 : ret = sysdb_set_entry_attr(domain->sysdb, dn, attrs, SYSDB_MOD_REP);
298 0 : if (ret != EOK) {
299 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to modify entry [%d]: %s\n",
300 : ret, sss_strerror(ret));
301 0 : goto done;
302 : }
303 :
304 0 : ret = EOK;
305 :
306 : done:
307 0 : talloc_free(attrs);
308 :
309 0 : return ret;
310 : }
311 :
312 0 : int ifp_cache_object_store(struct sbus_request *sbus_req,
313 : struct sss_domain_info *domain,
314 : struct ldb_dn *dn)
315 : {
316 : errno_t ret;
317 :
318 0 : ret = ifp_cache_object_set(domain, dn, true);
319 :
320 0 : if (ret == EOK) {
321 0 : iface_ifp_cache_object_Store_finish(sbus_req, true);
322 : } else {
323 0 : iface_ifp_cache_object_Store_finish(sbus_req, false);
324 : }
325 :
326 0 : return EOK;
327 : }
328 :
329 0 : int ifp_cache_object_remove(struct sbus_request *sbus_req,
330 : struct sss_domain_info *domain,
331 : struct ldb_dn *dn)
332 : {
333 : errno_t ret;
334 :
335 0 : ret = ifp_cache_object_set(domain, dn, false);
336 :
337 0 : if (ret == EOK) {
338 0 : iface_ifp_cache_object_Remove_finish(sbus_req, true);
339 : } else {
340 0 : iface_ifp_cache_object_Remove_finish(sbus_req, false);
341 : }
342 :
343 0 : return EOK;
344 : }
|