Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 : Stephen Gallagher <sgallagh@redhat.com>
5 :
6 : Copyright (C) 2013 Red Hat
7 :
8 : InfoPipe responder: Utility functions
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include <sys/param.h>
25 :
26 : #include "db/sysdb.h"
27 : #include "responder/ifp/ifp_private.h"
28 :
29 : #define IFP_USER_DEFAULT_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
30 : SYSDB_GIDNUM, SYSDB_GECOS, \
31 : SYSDB_HOMEDIR, SYSDB_SHELL, \
32 : "groups", \
33 : NULL}
34 :
35 3 : errno_t ifp_req_create(struct sbus_request *dbus_req,
36 : struct ifp_ctx *ifp_ctx,
37 : struct ifp_req **_ifp_req)
38 : {
39 3 : struct ifp_req *ireq = NULL;
40 : errno_t ret;
41 :
42 3 : if (ifp_ctx->sysbus == NULL) {
43 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Responder not connected to sysbus!\n");
44 0 : return EINVAL;
45 : }
46 :
47 3 : ireq = talloc_zero(dbus_req, struct ifp_req);
48 3 : if (ireq == NULL) {
49 0 : return ENOMEM;
50 : }
51 :
52 3 : ireq->ifp_ctx = ifp_ctx;
53 3 : ireq->dbus_req = dbus_req;
54 :
55 3 : if (dbus_req->client == -1) {
56 : /* We got a sysbus message but couldn't identify the
57 : * caller? Bail out! */
58 0 : DEBUG(SSSDBG_CRIT_FAILURE,
59 : "BUG: Received a message without a known caller!\n");
60 0 : ret = EACCES;
61 0 : goto done;
62 : }
63 :
64 6 : ret = check_allowed_uids(dbus_req->client,
65 3 : ifp_ctx->rctx->allowed_uids_count,
66 3 : ifp_ctx->rctx->allowed_uids);
67 3 : if (ret == EACCES) {
68 1 : DEBUG(SSSDBG_MINOR_FAILURE,
69 : "User %"PRIi64" not in ACL\n", dbus_req->client);
70 1 : goto done;
71 2 : } else if (ret != EOK) {
72 0 : DEBUG(SSSDBG_OP_FAILURE,
73 : "Cannot check if user %"PRIi64" is present in ACL\n",
74 : dbus_req->client);
75 0 : goto done;
76 : }
77 :
78 2 : *_ifp_req = ireq;
79 2 : ret = EOK;
80 : done:
81 3 : if (ret != EOK) {
82 1 : talloc_free(ireq);
83 : }
84 3 : return ret;
85 : }
86 :
87 0 : int ifp_req_create_handle_failure(struct sbus_request *dbus_req, errno_t err)
88 : {
89 0 : if (err == EACCES) {
90 0 : return sbus_request_fail_and_finish(dbus_req,
91 0 : sbus_error_new(dbus_req,
92 : DBUS_ERROR_ACCESS_DENIED,
93 : "User %"PRIi64" not in ACL\n",
94 : dbus_req->client));
95 : }
96 :
97 0 : return sbus_request_fail_and_finish(dbus_req,
98 0 : sbus_error_new(dbus_req,
99 : DBUS_ERROR_FAILED,
100 : "Cannot create IFP request\n"));
101 : }
102 :
103 1 : errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
104 : struct ldb_message_element *el)
105 : {
106 : DBusMessageIter iter_dict_entry;
107 : DBusMessageIter iter_dict_val;
108 : DBusMessageIter iter_array;
109 : dbus_bool_t dbret;
110 : unsigned int i;
111 :
112 1 : if (el == NULL) {
113 0 : return EINVAL;
114 : }
115 :
116 1 : dbret = dbus_message_iter_open_container(iter_dict,
117 : DBUS_TYPE_DICT_ENTRY, NULL,
118 : &iter_dict_entry);
119 1 : if (!dbret) {
120 0 : return ENOMEM;
121 : }
122 :
123 : /* Start by appending the key */
124 1 : dbret = dbus_message_iter_append_basic(&iter_dict_entry,
125 1 : DBUS_TYPE_STRING, &(el->name));
126 1 : if (!dbret) {
127 0 : return ENOMEM;
128 : }
129 :
130 1 : dbret = dbus_message_iter_open_container(&iter_dict_entry,
131 : DBUS_TYPE_VARIANT,
132 : DBUS_TYPE_ARRAY_AS_STRING
133 : DBUS_TYPE_STRING_AS_STRING,
134 : &iter_dict_val);
135 1 : if (!dbret) {
136 0 : return ENOMEM;
137 : }
138 :
139 : /* Open container for values */
140 1 : dbret = dbus_message_iter_open_container(&iter_dict_val,
141 : DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
142 : &iter_array);
143 1 : if (!dbret) {
144 0 : return ENOMEM;
145 : }
146 :
147 : /* Now add all the values */
148 3 : for (i = 0; i < el->num_values; i++) {
149 2 : DEBUG(SSSDBG_TRACE_FUNC, "element [%s] has value [%s]\n",
150 : el->name, (const char *) el->values[i].data);
151 :
152 2 : dbret = dbus_message_iter_append_basic(&iter_array,
153 : DBUS_TYPE_STRING,
154 2 : &(el->values[i].data));
155 2 : if (!dbret) {
156 0 : return ENOMEM;
157 : }
158 : }
159 :
160 1 : dbret = dbus_message_iter_close_container(&iter_dict_val,
161 : &iter_array);
162 1 : if (!dbret) {
163 0 : return ENOMEM;
164 : }
165 :
166 1 : dbret = dbus_message_iter_close_container(&iter_dict_entry,
167 : &iter_dict_val);
168 1 : if (!dbret) {
169 0 : return ENOMEM;
170 : }
171 :
172 1 : dbret = dbus_message_iter_close_container(iter_dict,
173 : &iter_dict_entry);
174 1 : if (!dbret) {
175 0 : return ENOMEM;
176 : }
177 :
178 1 : return EOK;
179 : }
180 :
181 :
182 : bool
183 5 : ifp_attr_allowed(const char *whitelist[], const char *attr)
184 : {
185 : size_t i;
186 :
187 5 : if (whitelist == NULL) {
188 1 : return false;
189 : }
190 :
191 7 : for (i = 0; whitelist[i]; i++) {
192 5 : if (strcasecmp(whitelist[i], attr) == 0) {
193 2 : break;
194 : }
195 : }
196 :
197 4 : return (whitelist[i]) ? true : false;
198 : }
199 :
200 : const char **
201 7 : ifp_parse_user_attr_list(TALLOC_CTX *mem_ctx, const char *csv)
202 : {
203 : static const char *defaults[] = IFP_USER_DEFAULT_ATTRS;
204 :
205 7 : return parse_attr_list_ex(mem_ctx, csv, defaults);
206 : }
207 :
208 : const char **
209 0 : ifp_get_user_extra_attributes(TALLOC_CTX *mem_ctx, struct ifp_ctx *ifp_ctx)
210 : {
211 0 : TALLOC_CTX *tmp_ctx = NULL;
212 0 : const char *std[] = IFP_USER_DEFAULT_ATTRS;
213 0 : const char **whitelist = ifp_ctx->user_whitelist;
214 : const char **extra;
215 : bool found;
216 : int extra_num;
217 : int i, j;
218 :
219 0 : tmp_ctx = talloc_new(NULL);
220 0 : if (tmp_ctx == NULL) {
221 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
222 0 : return NULL;
223 : }
224 :
225 0 : for (i = 0; whitelist[i] != NULL; i++) {
226 : /* Just count number of attributes in whitelist. */
227 : }
228 :
229 0 : extra = talloc_zero_array(tmp_ctx, const char *, i + 1);
230 0 : if (extra == NULL) {
231 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
232 0 : goto fail;
233 : }
234 :
235 0 : extra_num = 0;
236 0 : for (i = 0; whitelist[i] != NULL; i++) {
237 0 : found = false;
238 0 : for (j = 0; std[j] != NULL; j++) {
239 0 : if (strcmp(whitelist[i], std[j]) == 0) {
240 0 : found = true;
241 0 : break;
242 : }
243 : }
244 :
245 0 : if (!found) {
246 0 : extra[extra_num] = talloc_strdup(extra, whitelist[i]);
247 0 : if (extra[extra_num] == NULL) {
248 0 : goto fail;
249 : }
250 :
251 0 : extra_num++;
252 : }
253 : }
254 :
255 0 : extra = talloc_realloc(tmp_ctx, extra, const char *, extra_num + 1);
256 0 : if (extra == NULL) {
257 0 : goto fail;
258 : }
259 :
260 0 : talloc_steal(mem_ctx, extra);
261 0 : talloc_free(tmp_ctx);
262 0 : return extra;
263 :
264 : fail:
265 0 : talloc_free(tmp_ctx);
266 0 : return NULL;
267 : }
268 :
269 : bool
270 0 : ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr)
271 : {
272 0 : return ifp_attr_allowed(ifp_ctx->user_whitelist, attr);
273 : }
274 :
275 0 : static uint32_t ifp_list_limit(struct ifp_ctx *ctx, uint32_t limit)
276 : {
277 0 : if (limit == 0) {
278 0 : return ctx->wildcard_limit;
279 0 : } else if (ctx->wildcard_limit) {
280 0 : return MIN(ctx->wildcard_limit, limit);
281 : } else {
282 0 : return limit;
283 : }
284 : }
285 :
286 0 : struct ifp_list_ctx *ifp_list_ctx_new(struct sbus_request *sbus_req,
287 : struct ifp_ctx *ctx,
288 : const char *filter,
289 : uint32_t limit)
290 : {
291 : struct ifp_list_ctx *list_ctx;
292 :
293 0 : list_ctx = talloc_zero(sbus_req, struct ifp_list_ctx);
294 0 : if (list_ctx == NULL) {
295 0 : return NULL;
296 : }
297 :
298 0 : list_ctx->sbus_req = sbus_req;
299 0 : list_ctx->limit = ifp_list_limit(ctx, limit);
300 0 : list_ctx->ctx = ctx;
301 0 : list_ctx->dom = ctx->rctx->domains;
302 0 : list_ctx->filter = filter;
303 0 : list_ctx->paths = talloc_zero_array(list_ctx, const char *, limit);
304 0 : if (list_ctx->paths == NULL) {
305 0 : talloc_free(list_ctx);
306 0 : return NULL;
307 : }
308 :
309 0 : return list_ctx;
310 : }
311 :
312 0 : size_t ifp_list_ctx_remaining_capacity(struct ifp_list_ctx *list_ctx,
313 : size_t entries)
314 : {
315 0 : size_t capacity = list_ctx->limit - list_ctx->path_count;
316 :
317 0 : if (capacity < entries) {
318 0 : DEBUG(SSSDBG_MINOR_FAILURE,
319 : "IFP list request has limit of %"PRIu32" entries but back end "
320 : "returned %zu entries\n", list_ctx->limit, entries);
321 0 : return capacity;
322 : } else {
323 0 : return entries;
324 : }
325 : }
|