Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2014 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 <augeas.h>
22 : #include <talloc.h>
23 : #include <string.h>
24 : #include "util/sss_config.h"
25 :
26 : #define PATH_SECTION "/files/%s/target[. = \"%s\"]"
27 : #define PATH_OPTION PATH_SECTION "/%s"
28 :
29 : #define build_section_path(mem_ctx, config_ctx, section) \
30 : talloc_asprintf(mem_ctx, PATH_SECTION, config_ctx->file, section)
31 :
32 : #define build_option_path(mem_ctx, config_ctx, section, option) \
33 : talloc_asprintf(mem_ctx, PATH_OPTION, config_ctx->file, section, option)
34 :
35 : struct sss_config_ctx
36 : {
37 : augeas *auges_ctx;
38 : const char *file;
39 : };
40 :
41 : static errno_t
42 10 : sss_config_set_option(struct sss_config_ctx *ctx,
43 : const char *section,
44 : const char *option,
45 : const char *value)
46 : {
47 10 : TALLOC_CTX *tmp_ctx = NULL;
48 10 : char *target_path = NULL;
49 10 : char *option_path = NULL;
50 : errno_t ret;
51 : int aug_ret;
52 :
53 10 : tmp_ctx = talloc_new(NULL);
54 10 : if (tmp_ctx == NULL) {
55 0 : return ENOMEM;
56 : }
57 :
58 10 : target_path = build_section_path(tmp_ctx, ctx, section);
59 10 : if (target_path == NULL) {
60 0 : ret = ENOMEM;
61 0 : goto done;
62 : }
63 :
64 10 : option_path = build_option_path(tmp_ctx, ctx, section, option);
65 10 : if (option_path == NULL) {
66 0 : ret = ENOMEM;
67 0 : goto done;
68 : }
69 :
70 : /* Set configuration option:
71 : *
72 : * # make sure the section exists
73 : * set /files/$file/target[. = "$section"] $section
74 : *
75 : * # set value
76 : * set /files/$file/target[. = "$section"]/$option $value
77 : */
78 :
79 10 : aug_ret = aug_set(ctx->auges_ctx, target_path, section);
80 10 : if (aug_ret != 0) {
81 0 : ret = EIO;
82 0 : goto done;
83 : }
84 :
85 10 : aug_ret = aug_set(ctx->auges_ctx, option_path, value);
86 10 : if (aug_ret != 0) {
87 0 : ret = EIO;
88 0 : goto done;
89 : }
90 :
91 10 : ret = EOK;
92 :
93 : done:
94 10 : talloc_free(tmp_ctx);
95 10 : return ret;
96 : }
97 :
98 : static errno_t
99 2 : sss_config_rm_option(struct sss_config_ctx *ctx,
100 : const char *section,
101 : const char *option)
102 : {
103 2 : TALLOC_CTX *tmp_ctx = NULL;
104 2 : char *option_path = NULL;
105 : errno_t ret;
106 : int aug_ret;
107 :
108 2 : tmp_ctx = talloc_new(NULL);
109 2 : if (tmp_ctx == NULL) {
110 0 : return ENOMEM;
111 : }
112 :
113 2 : option_path = build_option_path(tmp_ctx, ctx, section, option);
114 2 : if (option_path == NULL) {
115 0 : ret = ENOMEM;
116 0 : goto done;
117 : }
118 :
119 : /* Remove configuration option:
120 : *
121 : * rm /files/$file/target[. = "$section"]/$option
122 : */
123 :
124 2 : aug_ret = aug_rm(ctx->auges_ctx, option_path);
125 2 : if (aug_ret != 1) {
126 0 : ret = EIO;
127 0 : goto done;
128 : }
129 :
130 2 : ret = EOK;
131 :
132 : done:
133 2 : talloc_free(tmp_ctx);
134 2 : return ret;
135 : }
136 :
137 : static errno_t
138 10 : sss_config_set_list(struct sss_config_ctx *ctx,
139 : const char *section,
140 : const char *option,
141 : char **list)
142 : {
143 10 : TALLOC_CTX *tmp_ctx = NULL;
144 10 : char *value = NULL;
145 : errno_t ret;
146 : int i;
147 :
148 10 : if (list == NULL) {
149 0 : return EINVAL;
150 : }
151 :
152 10 : tmp_ctx = talloc_new(NULL);
153 10 : if (tmp_ctx == NULL) {
154 0 : return ENOMEM;
155 : }
156 :
157 10 : if (list[0] == NULL) {
158 2 : ret = sss_config_rm_option(ctx, section, option);
159 2 : goto done;
160 : }
161 :
162 8 : value = talloc_strdup(tmp_ctx, list[0]);
163 8 : if (value == NULL) {
164 0 : ret = ENOMEM;
165 0 : goto done;
166 : }
167 :
168 11 : for (i = 1; list[i] != NULL; i++) {
169 3 : value = talloc_asprintf_append(value, ", %s", list[i]);
170 3 : if (value == NULL) {
171 0 : ret = ENOMEM;
172 0 : goto done;
173 : }
174 : }
175 :
176 8 : ret = sss_config_set_option(ctx, section, option, value);
177 :
178 : done:
179 10 : talloc_free(tmp_ctx);
180 10 : return ret;
181 : }
182 :
183 : static errno_t
184 22 : sss_config_get_list(TALLOC_CTX *mem_ctx,
185 : struct sss_config_ctx *ctx,
186 : const char *section,
187 : const char *option,
188 : char ***_list)
189 : {
190 22 : TALLOC_CTX *tmp_ctx = NULL;
191 22 : char *option_path = NULL;
192 22 : const char *value = NULL;
193 22 : char **list = NULL;
194 : errno_t ret;
195 : int aug_ret;
196 :
197 22 : tmp_ctx = talloc_new(NULL);
198 22 : if (tmp_ctx == NULL) {
199 0 : return ENOMEM;
200 : }
201 :
202 22 : option_path = build_option_path(tmp_ctx, ctx, section, option);
203 22 : if (option_path == NULL) {
204 0 : ret = ENOMEM;
205 0 : goto done;
206 : }
207 :
208 22 : aug_ret = aug_get(ctx->auges_ctx, option_path, &value);
209 22 : if (aug_ret == 0 || (aug_ret == 1 && (value == NULL || *value == '\0'))) {
210 : /* option is not present, return empty list */
211 12 : list = talloc_zero_array(tmp_ctx, char*, 1);
212 12 : if (list == NULL) {
213 0 : ret = ENOMEM;
214 0 : goto done;
215 : }
216 :
217 12 : ret = EOK;
218 12 : goto done;
219 10 : } else if (aug_ret != 1) {
220 : /* error: more than one value found */
221 0 : ret = EINVAL;
222 0 : goto done;
223 : }
224 :
225 10 : ret = split_on_separator(tmp_ctx, value, ',', true, true, &list, NULL);
226 10 : if (ret != EOK) {
227 0 : goto done;
228 : }
229 :
230 10 : *_list = talloc_steal(mem_ctx, list);
231 10 : ret = EOK;
232 :
233 : done:
234 22 : talloc_free(tmp_ctx);
235 22 : return ret;
236 : }
237 :
238 : static errno_t
239 8 : sss_config_is_in_list(struct sss_config_ctx *ctx,
240 : const char *section,
241 : const char *option,
242 : const char *value,
243 : bool *_result)
244 : {
245 8 : char **list = NULL;
246 : errno_t ret;
247 :
248 8 : ret = sss_config_get_list(ctx, ctx, section, option, &list);
249 8 : if (ret != EOK) {
250 0 : goto done;
251 : }
252 :
253 8 : *_result = string_in_list(value, list, true);
254 :
255 : done:
256 8 : talloc_free(list);
257 8 : return ret;
258 : }
259 :
260 : static errno_t
261 6 : sss_config_add_to_list(struct sss_config_ctx *ctx,
262 : const char *section,
263 : const char *option,
264 : const char *value)
265 : {
266 6 : TALLOC_CTX *tmp_ctx = NULL;
267 6 : char **list = NULL;
268 : errno_t ret;
269 6 : bool result = false;
270 :
271 6 : tmp_ctx = talloc_new(NULL);
272 6 : if (tmp_ctx == NULL) {
273 0 : return ENOMEM;
274 : }
275 :
276 6 : ret = sss_config_get_list(tmp_ctx, ctx, section, option, &list);
277 6 : if (ret != EOK) {
278 0 : goto done;
279 : }
280 :
281 6 : result = string_in_list(value, list, true);
282 6 : if (result == true) {
283 0 : ret = EOK;
284 0 : goto done;
285 : }
286 :
287 6 : ret = add_string_to_list(tmp_ctx, value, &list);
288 6 : if (ret != EOK) {
289 0 : goto done;
290 : }
291 :
292 6 : ret = sss_config_set_list(ctx, section, option, list);
293 :
294 : done:
295 6 : talloc_free(tmp_ctx);
296 6 : return ret;
297 : }
298 :
299 : static errno_t
300 8 : sss_config_del_from_list(struct sss_config_ctx *ctx,
301 : const char *section,
302 : const char *option,
303 : const char *value)
304 : {
305 8 : TALLOC_CTX *tmp_ctx = NULL;
306 8 : char **list = NULL;
307 : errno_t ret;
308 : bool found;
309 : int i;
310 :
311 8 : tmp_ctx = talloc_new(NULL);
312 8 : if (tmp_ctx == NULL) {
313 0 : return ENOMEM;
314 : }
315 :
316 8 : ret = sss_config_get_list(tmp_ctx, ctx, section, option, &list);
317 8 : if (ret != EOK) {
318 0 : goto done;
319 : }
320 :
321 8 : if (list == NULL) {
322 4 : goto done;
323 : }
324 :
325 4 : found = false;
326 10 : for (i = 0; list[i] != NULL; i++) {
327 6 : if (strcmp(list[i], value) == 0) {
328 4 : found = true;
329 : }
330 :
331 6 : if (found) {
332 6 : list[i] = list[i + 1];
333 : }
334 : }
335 :
336 4 : ret = sss_config_set_list(ctx, section, option, list);
337 :
338 : done:
339 8 : talloc_free(tmp_ctx);
340 8 : return ret;
341 : }
342 :
343 24 : static int sss_config_ctx_destructor(struct sss_config_ctx *ctx)
344 : {
345 24 : if (ctx->auges_ctx != NULL) {
346 24 : aug_close(ctx->auges_ctx);
347 24 : ctx->auges_ctx = NULL;
348 : }
349 :
350 24 : return 0;
351 : }
352 :
353 : struct sss_config_ctx *
354 24 : sss_config_open(TALLOC_CTX *mem_ctx,
355 : const char *root,
356 : const char *file)
357 : {
358 24 : struct sss_config_ctx *ctx = NULL;
359 : errno_t ret;
360 : int aug_ret;
361 :
362 24 : ctx = talloc_zero(mem_ctx, struct sss_config_ctx);
363 24 : if (ctx == NULL) {
364 0 : return NULL;
365 : }
366 :
367 24 : talloc_set_destructor(ctx, sss_config_ctx_destructor);
368 :
369 24 : ctx->auges_ctx = aug_init(root, NULL, AUG_NO_LOAD | AUG_NO_MODL_AUTOLOAD
370 : | AUG_SAVE_BACKUP);
371 24 : if (ctx->auges_ctx == NULL) {
372 0 : ret = ENOMEM;
373 0 : goto done;
374 : }
375 :
376 24 : ctx->file = talloc_strdup(ctx, file);
377 24 : if (ctx->file == NULL) {
378 0 : ret = ENOMEM;
379 0 : goto done;
380 : }
381 :
382 : /* Load configuration file
383 : *
384 : * set /augeas/load/sssd/lens sssd.lns
385 : * set /augeas/load/sssd/incl $file
386 : * load
387 : */
388 :
389 24 : aug_ret = aug_set(ctx->auges_ctx, "/augeas/load/sssd/lens", "sssd.lns");
390 24 : if (aug_ret != 0) {
391 0 : ret = EIO;
392 0 : goto done;
393 : }
394 :
395 24 : aug_ret = aug_set(ctx->auges_ctx, "/augeas/load/sssd/incl", ctx->file);
396 24 : if (aug_ret != 0) {
397 0 : ret = EIO;
398 0 : goto done;
399 : }
400 :
401 24 : aug_ret = aug_load(ctx->auges_ctx);
402 24 : if (aug_ret != 0) {
403 0 : ret = EIO;
404 0 : goto done;
405 : }
406 :
407 24 : ret = EOK;
408 :
409 : done:
410 24 : if (ret != EOK) {
411 0 : talloc_free(ctx);
412 : }
413 :
414 24 : return ctx;
415 : }
416 :
417 : errno_t
418 16 : sss_config_save(struct sss_config_ctx *ctx)
419 : {
420 : int aug_ret;
421 :
422 16 : aug_ret = aug_save(ctx->auges_ctx);
423 16 : if (aug_ret != 0) {
424 0 : return EIO;
425 : }
426 :
427 16 : return EOK;
428 : }
429 :
430 : void
431 24 : sss_config_close(struct sss_config_ctx **_ctx)
432 : {
433 24 : if (_ctx == NULL || *_ctx == NULL) {
434 24 : return;
435 : }
436 :
437 24 : talloc_free(*_ctx);
438 24 : *_ctx = NULL;
439 : }
440 :
441 : errno_t
442 2 : sss_config_set_debug_level(struct sss_config_ctx *ctx,
443 : const char *section,
444 : uint32_t level)
445 : {
446 2 : char *level_str = NULL;
447 : errno_t ret;
448 :
449 2 : level_str = talloc_asprintf(ctx, "%#.4x", level);
450 2 : if (level_str == NULL) {
451 0 : return ENOMEM;
452 : }
453 :
454 2 : ret = sss_config_set_option(ctx, section, CONFDB_SERVICE_DEBUG_LEVEL,
455 : level_str);
456 :
457 2 : talloc_free(level_str);
458 2 : return ret;
459 : }
460 :
461 : errno_t
462 4 : sss_config_service_is_enabled(struct sss_config_ctx *ctx,
463 : const char *service,
464 : bool *_result)
465 : {
466 4 : return sss_config_is_in_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_SERVICES,
467 : service, _result);
468 : }
469 :
470 : errno_t
471 3 : sss_config_service_enable(struct sss_config_ctx *ctx,
472 : const char *service)
473 : {
474 3 : return sss_config_add_to_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_SERVICES,
475 : service);
476 : }
477 :
478 : errno_t
479 4 : sss_config_service_disable(struct sss_config_ctx *ctx,
480 : const char *service)
481 : {
482 4 : return sss_config_del_from_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_SERVICES,
483 : service);
484 : }
485 :
486 : errno_t
487 4 : sss_config_domain_is_enabled(struct sss_config_ctx *ctx,
488 : const char *domain,
489 : bool *_result)
490 : {
491 4 : return sss_config_is_in_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_DOMAINS,
492 : domain, _result);
493 : }
494 :
495 : errno_t
496 3 : sss_config_domain_enable(struct sss_config_ctx *ctx,
497 : const char *domain)
498 : {
499 3 : return sss_config_add_to_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_DOMAINS,
500 : domain);
501 : }
502 :
503 : errno_t
504 4 : sss_config_domain_disable(struct sss_config_ctx *ctx,
505 : const char *domain)
506 : {
507 4 : return sss_config_del_from_list(ctx, "sssd", CONFDB_MONITOR_ACTIVE_DOMAINS,
508 : domain);
509 : }
|