Line data Source code
1 : /*
2 : SSSD
3 :
4 : Data Provider Helpers
5 :
6 : Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "data_provider.h"
23 :
24 : /* =Copy-Option-From-Subdomain-If-Allowed================================= */
25 17 : void dp_option_inherit(char **inherit_opt_list,
26 : int option,
27 : struct dp_option *parent_opts,
28 : struct dp_option *subdom_opts)
29 : {
30 : errno_t ret;
31 : bool inherit_option;
32 :
33 17 : inherit_option = string_in_list(parent_opts[option].opt_name,
34 : inherit_opt_list, false);
35 17 : if (inherit_option == false) {
36 11 : DEBUG(SSSDBG_CONF_SETTINGS,
37 : "Option %s is not set up to be inherited\n",
38 : parent_opts[option].opt_name);
39 28 : return;
40 : }
41 :
42 6 : DEBUG(SSSDBG_CONF_SETTINGS,
43 : "Will inherit option %s\n", parent_opts[option].opt_name);
44 6 : switch (parent_opts[option].type) {
45 : case DP_OPT_NUMBER:
46 2 : ret = dp_opt_set_int(subdom_opts,
47 : option,
48 : dp_opt_get_int(parent_opts,
49 : option));
50 2 : break;
51 : case DP_OPT_STRING:
52 1 : ret = dp_opt_set_string(subdom_opts,
53 : option,
54 : dp_opt_get_string(parent_opts,
55 : option));
56 1 : break;
57 : case DP_OPT_BLOB:
58 1 : ret = dp_opt_set_blob(subdom_opts,
59 : option,
60 : dp_opt_get_blob(parent_opts,
61 : option));
62 1 : break;
63 : case DP_OPT_BOOL:
64 2 : ret = dp_opt_set_bool(subdom_opts,
65 : option,
66 : dp_opt_get_bool(parent_opts,
67 : option));
68 2 : break;
69 : default:
70 0 : ret = EINVAL;
71 0 : break;
72 : }
73 :
74 6 : if (ret != EOK) {
75 0 : DEBUG(SSSDBG_MINOR_FAILURE,
76 : "Failed to inherit option %s\n", parent_opts[option].opt_name);
77 : /* Not fatal */
78 : }
79 : }
80 :
81 : /* =Retrieve-Options====================================================== */
82 :
83 32 : int dp_get_options(TALLOC_CTX *memctx,
84 : struct confdb_ctx *cdb,
85 : const char *conf_path,
86 : struct dp_option *def_opts,
87 : int num_opts,
88 : struct dp_option **_opts)
89 : {
90 : struct dp_option *opts;
91 : int i, ret;
92 :
93 32 : opts = talloc_zero_array(memctx, struct dp_option, num_opts);
94 32 : if (!opts) return ENOMEM;
95 :
96 3266 : for (i = 0; i < num_opts; i++) {
97 : char *tmp;
98 :
99 1601 : opts[i].opt_name = def_opts[i].opt_name;
100 1601 : opts[i].type = def_opts[i].type;
101 1601 : opts[i].def_val = def_opts[i].def_val;
102 :
103 1601 : switch (def_opts[i].type) {
104 : case DP_OPT_STRING:
105 2511 : ret = confdb_get_string(cdb, opts, conf_path,
106 837 : opts[i].opt_name,
107 837 : opts[i].def_val.cstring,
108 837 : &opts[i].val.string);
109 1674 : if (ret != EOK ||
110 1011 : ((opts[i].def_val.string != NULL) &&
111 174 : (opts[i].val.string == NULL))) {
112 0 : DEBUG(SSSDBG_CRIT_FAILURE,
113 : "Failed to retrieve value for option (%s)\n",
114 : opts[i].opt_name);
115 0 : if (ret == EOK) ret = EINVAL;
116 0 : goto done;
117 : }
118 837 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
119 : opts[i].opt_name,
120 : opts[i].val.cstring ? "" : " no",
121 : opts[i].val.cstring ? opts[i].val.cstring : "");
122 837 : break;
123 :
124 : case DP_OPT_BLOB:
125 18 : ret = confdb_get_string(cdb, opts, conf_path,
126 18 : opts[i].opt_name,
127 : NULL, &tmp);
128 18 : if (ret != EOK) {
129 0 : DEBUG(SSSDBG_CRIT_FAILURE,
130 : "Failed to retrieve value for option (%s)\n",
131 : opts[i].opt_name);
132 0 : goto done;
133 : }
134 :
135 18 : if (tmp) {
136 1 : opts[i].val.blob.data = (uint8_t *)tmp;
137 1 : opts[i].val.blob.length = strlen(tmp);
138 17 : } else if (opts[i].def_val.blob.data != NULL) {
139 1 : opts[i].val.blob.data = opts[i].def_val.blob.data;
140 1 : opts[i].val.blob.length = opts[i].def_val.blob.length;
141 : } else {
142 16 : opts[i].val.blob.data = NULL;
143 16 : opts[i].val.blob.length = 0;
144 : }
145 :
146 18 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has %s binary value.\n",
147 : opts[i].opt_name, opts[i].val.blob.length?"a":"no");
148 18 : break;
149 :
150 : case DP_OPT_NUMBER:
151 1200 : ret = confdb_get_int(cdb, conf_path,
152 400 : opts[i].opt_name,
153 400 : opts[i].def_val.number,
154 400 : &opts[i].val.number);
155 400 : if (ret != EOK) {
156 0 : DEBUG(SSSDBG_CRIT_FAILURE,
157 : "Failed to retrieve value for option (%s)\n",
158 : opts[i].opt_name);
159 0 : goto done;
160 : }
161 400 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has value %d\n",
162 : opts[i].opt_name, opts[i].val.number);
163 400 : break;
164 :
165 : case DP_OPT_BOOL:
166 1038 : ret = confdb_get_bool(cdb, conf_path,
167 346 : opts[i].opt_name,
168 346 : opts[i].def_val.boolean,
169 346 : &opts[i].val.boolean);
170 346 : if (ret != EOK) {
171 0 : DEBUG(SSSDBG_CRIT_FAILURE,
172 : "Failed to retrieve value for option (%s)\n",
173 : opts[i].opt_name);
174 0 : goto done;
175 : }
176 346 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s is %s\n",
177 : opts[i].opt_name, opts[i].val.boolean?"TRUE":"FALSE");
178 346 : break;
179 : }
180 : }
181 :
182 32 : ret = EOK;
183 32 : *_opts = opts;
184 :
185 : done:
186 32 : if (ret != EOK) talloc_zfree(opts);
187 32 : return ret;
188 : }
189 :
190 : /* =Basic-Option-Helpers================================================== */
191 21 : static int dp_copy_options_ex(TALLOC_CTX *memctx,
192 : bool copy_values,
193 : struct dp_option *src_opts,
194 : int num_opts,
195 : struct dp_option **_opts)
196 : {
197 : struct dp_option *opts;
198 21 : int i, ret = EOK;
199 :
200 21 : opts = talloc_zero_array(memctx, struct dp_option, num_opts);
201 21 : if (!opts) return ENOMEM;
202 :
203 1095 : for (i = 0; i < num_opts; i++) {
204 1074 : opts[i].opt_name = src_opts[i].opt_name;
205 1074 : opts[i].type = src_opts[i].type;
206 1074 : opts[i].def_val = src_opts[i].def_val;
207 1074 : ret = EOK;
208 :
209 1074 : switch (src_opts[i].type) {
210 : case DP_OPT_STRING:
211 532 : if (copy_values) {
212 2 : ret = dp_opt_set_string(opts, i, src_opts[i].val.string);
213 : } else {
214 530 : ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string);
215 : }
216 532 : if (ret != EOK) {
217 0 : DEBUG(SSSDBG_CRIT_FAILURE,
218 : "Failed to copy value for option (%s)\n",
219 : opts[i].opt_name);
220 0 : goto done;
221 : }
222 532 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
223 : opts[i].opt_name,
224 : opts[i].val.cstring ? "" : " no",
225 : opts[i].val.cstring ? opts[i].val.cstring : "");
226 532 : break;
227 :
228 : case DP_OPT_BLOB:
229 29 : if (copy_values) {
230 2 : ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob);
231 : } else {
232 27 : ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob);
233 : }
234 29 : if (ret != EOK) {
235 0 : DEBUG(SSSDBG_CRIT_FAILURE,
236 : "Failed to retrieve value for option (%s)\n",
237 : opts[i].opt_name);
238 0 : goto done;
239 : }
240 29 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has %s binary value.\n",
241 : opts[i].opt_name, opts[i].val.blob.length?"a":"no");
242 29 : break;
243 :
244 : case DP_OPT_NUMBER:
245 273 : if (copy_values) {
246 2 : ret = dp_opt_set_int(opts, i, src_opts[i].val.number);
247 : } else {
248 271 : ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number);
249 : }
250 273 : if (ret != EOK) {
251 0 : DEBUG(SSSDBG_CRIT_FAILURE,
252 : "Failed to retrieve value for option (%s)\n",
253 : opts[i].opt_name);
254 0 : goto done;
255 : }
256 273 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s has value %d\n",
257 : opts[i].opt_name, opts[i].val.number);
258 273 : break;
259 :
260 : case DP_OPT_BOOL:
261 240 : if (copy_values) {
262 2 : ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean);
263 : } else {
264 238 : ret = dp_opt_set_bool(opts, i, src_opts[i].def_val.boolean);
265 : }
266 240 : if (ret != EOK) {
267 0 : DEBUG(SSSDBG_CRIT_FAILURE,
268 : "Failed to retrieve value for option (%s)\n",
269 : opts[i].opt_name);
270 0 : goto done;
271 : }
272 240 : DEBUG(SSSDBG_TRACE_FUNC, "Option %s is %s\n",
273 : opts[i].opt_name, opts[i].val.boolean?"TRUE":"FALSE");
274 240 : break;
275 : }
276 : }
277 :
278 21 : *_opts = opts;
279 :
280 : done:
281 21 : if (ret != EOK) talloc_zfree(opts);
282 21 : return ret;
283 : }
284 :
285 1 : int dp_copy_options(TALLOC_CTX *memctx,
286 : struct dp_option *src_opts,
287 : int num_opts,
288 : struct dp_option **_opts)
289 : {
290 1 : return dp_copy_options_ex(memctx, true, src_opts, num_opts, _opts);
291 : }
292 :
293 20 : int dp_copy_defaults(TALLOC_CTX *memctx,
294 : struct dp_option *src_opts,
295 : int num_opts,
296 : struct dp_option **_opts)
297 : {
298 20 : return dp_copy_options_ex(memctx, false, src_opts, num_opts, _opts);
299 : }
300 :
301 0 : static const char *dp_opt_type_to_string(enum dp_opt_type type)
302 : {
303 0 : switch (type) {
304 : case DP_OPT_STRING:
305 0 : return "String";
306 : case DP_OPT_BLOB:
307 0 : return "Blob";
308 : case DP_OPT_NUMBER:
309 0 : return "Number";
310 : case DP_OPT_BOOL:
311 0 : return "Boolean";
312 : }
313 0 : return NULL;
314 : }
315 :
316 : /* Getters */
317 0 : const char *_dp_opt_get_cstring(struct dp_option *opts,
318 : int id, const char *location)
319 : {
320 0 : if (opts[id].type != DP_OPT_STRING) {
321 0 : DEBUG(SSSDBG_FATAL_FAILURE,
322 : "[%s] Requested type 'String' for option '%s'"
323 : " but value is of type '%s'!\n",
324 : location, opts[id].opt_name,
325 : dp_opt_type_to_string(opts[id].type));
326 0 : return NULL;
327 : }
328 0 : return opts[id].val.cstring;
329 : }
330 :
331 264 : char *_dp_opt_get_string(struct dp_option *opts,
332 : int id, const char *location)
333 : {
334 264 : if (opts[id].type != DP_OPT_STRING) {
335 0 : DEBUG(SSSDBG_FATAL_FAILURE,
336 : "[%s] Requested type 'String' for option '%s'"
337 : " but value is of type '%s'!\n",
338 : location, opts[id].opt_name,
339 : dp_opt_type_to_string(opts[id].type));
340 0 : return NULL;
341 : }
342 264 : return opts[id].val.string;
343 : }
344 :
345 26 : struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
346 : int id, const char *location)
347 : {
348 26 : struct dp_opt_blob null_blob = { NULL, 0 };
349 26 : if (opts[id].type != DP_OPT_BLOB) {
350 0 : DEBUG(SSSDBG_FATAL_FAILURE, "[%s] Requested type 'Blob' for option '%s'"
351 : " but value is of type '%s'!\n",
352 : location, opts[id].opt_name,
353 : dp_opt_type_to_string(opts[id].type));
354 0 : return null_blob;
355 : }
356 26 : return opts[id].val.blob;
357 : }
358 :
359 171 : int _dp_opt_get_int(struct dp_option *opts,
360 : int id, const char *location)
361 : {
362 171 : if (opts[id].type != DP_OPT_NUMBER) {
363 0 : DEBUG(SSSDBG_FATAL_FAILURE,
364 : "[%s] Requested type 'Number' for option '%s'"
365 : " but value is of type '%s'!\n",
366 : location, opts[id].opt_name,
367 : dp_opt_type_to_string(opts[id].type));
368 0 : return 0;
369 : }
370 171 : return opts[id].val.number;
371 : }
372 :
373 91 : bool _dp_opt_get_bool(struct dp_option *opts,
374 : int id, const char *location)
375 : {
376 91 : if (opts[id].type != DP_OPT_BOOL) {
377 0 : DEBUG(SSSDBG_FATAL_FAILURE,
378 : "[%s] Requested type 'Boolean' for option '%s'"
379 : " but value is of type '%s'!\n",
380 : location, opts[id].opt_name,
381 : dp_opt_type_to_string(opts[id].type));
382 0 : return false;
383 : }
384 91 : return opts[id].val.boolean;
385 : }
386 :
387 : /* Setters */
388 627 : int _dp_opt_set_string(struct dp_option *opts, int id,
389 : const char *s, const char *location)
390 : {
391 627 : if (opts[id].type != DP_OPT_STRING) {
392 0 : DEBUG(SSSDBG_FATAL_FAILURE,
393 : "[%s] Requested type 'String' for option '%s'"
394 : " but type is '%s'!\n",
395 : location, opts[id].opt_name,
396 : dp_opt_type_to_string(opts[id].type));
397 0 : return EINVAL;
398 : }
399 :
400 627 : if (opts[id].val.string) {
401 21 : talloc_zfree(opts[id].val.string);
402 : }
403 627 : if (s) {
404 209 : opts[id].val.string = talloc_strdup(opts, s);
405 209 : if (!opts[id].val.string) {
406 0 : DEBUG(SSSDBG_FATAL_FAILURE, "talloc_strdup() failed!\n");
407 0 : return ENOMEM;
408 : }
409 : }
410 :
411 627 : return EOK;
412 : }
413 :
414 35 : int _dp_opt_set_blob(struct dp_option *opts, int id,
415 : struct dp_opt_blob b, const char *location)
416 : {
417 35 : if (opts[id].type != DP_OPT_BLOB) {
418 0 : DEBUG(SSSDBG_FATAL_FAILURE, "[%s] Requested type 'Blob' for option '%s'"
419 : " but type is '%s'!\n",
420 : location, opts[id].opt_name,
421 : dp_opt_type_to_string(opts[id].type));
422 0 : return EINVAL;
423 : }
424 :
425 35 : if (opts[id].val.blob.data) {
426 1 : talloc_zfree(opts[id].val.blob.data);
427 1 : opts[id].val.blob.length = 0;
428 : }
429 35 : if (b.data) {
430 14 : opts[id].val.blob.data = talloc_memdup(opts, b.data, b.length);
431 14 : if (!opts[id].val.blob.data) {
432 0 : DEBUG(SSSDBG_FATAL_FAILURE, "talloc_memdup() failed!\n");
433 0 : return ENOMEM;
434 : }
435 : }
436 35 : opts[id].val.blob.length = b.length;
437 :
438 35 : return EOK;
439 : }
440 :
441 285 : int _dp_opt_set_int(struct dp_option *opts, int id,
442 : int i, const char *location)
443 : {
444 285 : if (opts[id].type != DP_OPT_NUMBER) {
445 0 : DEBUG(SSSDBG_FATAL_FAILURE,
446 : "[%s] Requested type 'Number' for option '%s'"
447 : " but type is '%s'!\n",
448 : location, opts[id].opt_name,
449 : dp_opt_type_to_string(opts[id].type));
450 0 : return EINVAL;
451 : }
452 :
453 285 : opts[id].val.number = i;
454 :
455 285 : return EOK;
456 : }
457 :
458 254 : int _dp_opt_set_bool(struct dp_option *opts, int id,
459 : bool b, const char *location)
460 : {
461 254 : if (opts[id].type != DP_OPT_BOOL) {
462 0 : DEBUG(SSSDBG_FATAL_FAILURE,
463 : "[%s] Requested type 'Boolean' for option '%s'"
464 : " but type is '%s'!\n",
465 : location, opts[id].opt_name,
466 : dp_opt_type_to_string(opts[id].type));
467 0 : return EINVAL;
468 : }
469 :
470 254 : opts[id].val.boolean = b;
471 :
472 254 : return EOK;
473 : }
474 :
|