Line data Source code
1 : /*
2 : SSSD
3 :
4 : sss_ini.c
5 :
6 : Authors:
7 : Ondrej Kos <okos@redhat.com>
8 :
9 : Copyright (C) 2013 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include <stdio.h>
26 : #include <errno.h>
27 : #include <talloc.h>
28 :
29 : #include "config.h"
30 : #include "util/util.h"
31 : #include "util/sss_ini.h"
32 : #include "confdb/confdb_setup.h"
33 : #include "confdb/confdb_private.h"
34 :
35 : #ifdef HAVE_LIBINI_CONFIG_V1
36 : #include "ini_configobj.h"
37 : #else
38 : #include "collection.h"
39 : #include "collection_tools.h"
40 : #endif
41 :
42 : #include "ini_config.h"
43 :
44 :
45 : #ifdef HAVE_LIBINI_CONFIG_V1
46 :
47 : struct sss_ini_initdata {
48 : char **error_list;
49 : struct ini_cfgobj *sssd_config;
50 : struct value_obj *obj;
51 : const struct stat *cstat;
52 : struct ini_cfgfile *file;
53 : };
54 :
55 : #define sss_ini_get_sec_list ini_get_section_list
56 : #define sss_ini_get_attr_list ini_get_attribute_list
57 : #define sss_ini_get_const_string_config_value ini_get_const_string_config_value
58 : #define sss_ini_get_config_obj ini_get_config_valueobj
59 :
60 :
61 :
62 : #else
63 :
64 : struct sss_ini_initdata {
65 : struct collection_item *error_list;
66 : struct collection_item *sssd_config;
67 : struct collection_item *obj;
68 : struct stat cstat;
69 : int file;
70 : };
71 :
72 : #define sss_ini_get_sec_list get_section_list
73 : #define sss_ini_get_attr_list get_attribute_list
74 : #define sss_ini_get_const_string_config_value get_const_string_config_value
75 : #define sss_ini_get_config_obj(secs,attrs,cfg,flag,attr) \
76 : get_config_item(secs,attrs,cfg,attr)
77 :
78 : #endif
79 :
80 :
81 : /* Initialize data structure */
82 :
83 0 : struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *mem_ctx)
84 : {
85 0 : return talloc_zero(mem_ctx, struct sss_ini_initdata);
86 : }
87 :
88 :
89 :
90 : /* Close file descriptor */
91 :
92 0 : void sss_ini_close_file(struct sss_ini_initdata *init_data)
93 : {
94 0 : if (init_data == NULL) return;
95 : #ifdef HAVE_LIBINI_CONFIG_V1
96 0 : if (init_data->file != NULL) {
97 0 : ini_config_file_destroy(init_data->file);
98 0 : init_data->file = NULL;
99 : }
100 : #else
101 : if (init_data->file != -1) {
102 : close(init_data->file);
103 : init_data->file = -1;
104 : }
105 : #endif
106 : }
107 :
108 :
109 :
110 : /* Open configuration file */
111 :
112 0 : int sss_ini_config_file_open(struct sss_ini_initdata *init_data,
113 : const char *config_file)
114 : {
115 : #ifdef HAVE_LIBINI_CONFIG_V1
116 0 : return ini_config_file_open(config_file,
117 : INI_META_STATS,
118 : &init_data->file);
119 : #else
120 : return check_and_open_readonly(config_file, &init_data->file, 0, 0,
121 : S_IFREG|S_IRUSR, /* f r**------ */
122 : S_IFMT|(ALLPERMS & ~(S_IWUSR|S_IXUSR)));
123 : #endif
124 : }
125 :
126 :
127 :
128 : /* Check configuration file permissions */
129 :
130 0 : int sss_ini_config_access_check(struct sss_ini_initdata *init_data)
131 : {
132 : #ifdef HAVE_LIBINI_CONFIG_V1
133 0 : return ini_config_access_check(init_data->file,
134 : INI_ACCESS_CHECK_MODE |
135 : INI_ACCESS_CHECK_UID |
136 : INI_ACCESS_CHECK_GID,
137 : 0, /* owned by root */
138 : 0, /* owned by root */
139 : S_IRUSR, /* r**------ */
140 : ALLPERMS & ~(S_IWUSR|S_IXUSR));
141 : #else
142 : return EOK;
143 : #endif
144 : }
145 :
146 :
147 :
148 : /* Get cstat */
149 :
150 0 : int sss_ini_get_stat(struct sss_ini_initdata *init_data)
151 : {
152 : #ifdef HAVE_LIBINI_CONFIG_V1
153 0 : init_data->cstat = ini_config_get_stat(init_data->file);
154 :
155 0 : if (!init_data->cstat) return EIO;
156 :
157 0 : return EOK;
158 : #else
159 :
160 : return fstat(init_data->file, &init_data->cstat);
161 : #endif
162 : }
163 :
164 :
165 :
166 : /* Get mtime */
167 :
168 0 : int sss_ini_get_mtime(struct sss_ini_initdata *init_data,
169 : size_t timestr_len,
170 : char *timestr)
171 : {
172 : #ifdef HAVE_LIBINI_CONFIG_V1
173 0 : return snprintf(timestr, timestr_len, "%llu",
174 0 : (long long unsigned)init_data->cstat->st_mtime);
175 : #else
176 : return snprintf(timestr, timestr_len, "%llu",
177 : (long long unsigned)init_data->cstat.st_mtime);
178 : #endif
179 : }
180 :
181 :
182 :
183 : /* Print ini_config errors */
184 :
185 0 : void sss_ini_config_print_errors(char **error_list)
186 : {
187 : #ifdef HAVE_LIBINI_CONFIG_V1
188 0 : unsigned count = 0;
189 :
190 0 : if (!error_list) {
191 0 : return;
192 : }
193 :
194 0 : while (error_list[count]) {
195 0 : DEBUG(SSSDBG_CRIT_FAILURE, "%s\n", error_list[count]);
196 0 : count++;
197 : }
198 : #endif
199 :
200 0 : return;
201 : }
202 :
203 :
204 :
205 : /* Load configuration */
206 :
207 0 : int sss_ini_get_config(struct sss_ini_initdata *init_data,
208 : const char *config_file)
209 : {
210 : int ret;
211 : #ifdef HAVE_LIBINI_CONFIG_V1
212 :
213 : /* Create config object */
214 0 : ret = ini_config_create(&(init_data->sssd_config));
215 0 : if (ret != EOK) {
216 0 : DEBUG(SSSDBG_FATAL_FAILURE,
217 : "Failed to create config object. Error %d.\n", ret);
218 0 : return ret;
219 : }
220 :
221 : /* Parse file */
222 0 : ret = ini_config_parse(init_data->file,
223 : INI_STOP_ON_ANY,
224 : INI_MV1S_OVERWRITE,
225 : INI_PARSE_NOWRAP,
226 : init_data->sssd_config);
227 :
228 0 : if (ret != EOK) {
229 0 : DEBUG(SSSDBG_FATAL_FAILURE,
230 : "Failed to parse configuration. Error %d.\n", ret);
231 :
232 0 : if (ini_config_error_count(init_data->sssd_config)) {
233 0 : DEBUG(SSSDBG_FATAL_FAILURE,
234 : "Errors detected while parsing: %s\n",
235 : ini_config_get_filename(init_data->file));
236 :
237 0 : ini_config_get_errors(init_data->sssd_config,
238 : &init_data->error_list);
239 0 : sss_ini_config_print_errors(init_data->error_list);
240 0 : ini_config_free_errors(init_data->error_list);
241 : }
242 0 : ini_config_destroy(init_data->sssd_config);
243 0 : init_data->sssd_config = NULL;
244 0 : return ret;
245 : }
246 :
247 0 : return ret;
248 :
249 : #else
250 :
251 : /* Read the configuration into a collection */
252 : ret = config_from_fd("sssd",
253 : init_data->file,
254 : config_file,
255 : &init_data->sssd_config,
256 : INI_STOP_ON_ANY,
257 : &init_data->error_list);
258 :
259 : if (ret != EOK) {
260 : DEBUG(SSSDBG_FATAL_FAILURE,
261 : "Parse error reading configuration file [%s]\n",
262 : config_file);
263 :
264 : print_file_parsing_errors(stderr, init_data->error_list);
265 :
266 : free_ini_config_errors(init_data->error_list);
267 : free_ini_config(init_data->sssd_config);
268 :
269 : return ret;
270 : }
271 :
272 : return EOK;
273 :
274 : #endif
275 : }
276 :
277 :
278 :
279 : /* Get configuration object */
280 :
281 0 : int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data,
282 : const char *section, const char *name)
283 : {
284 0 : return sss_ini_get_config_obj(section,name, init_data->sssd_config,
285 : INI_GET_FIRST_VALUE, &init_data->obj);
286 : }
287 :
288 :
289 :
290 : /* Check configuration object */
291 :
292 0 : int sss_ini_check_config_obj(struct sss_ini_initdata *init_data)
293 : {
294 0 : if (init_data->obj == NULL) {
295 0 : return ENOENT;
296 : }
297 :
298 0 : return EOK;
299 : }
300 :
301 :
302 :
303 : /* Get integer value */
304 :
305 0 : int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data,
306 : int strict, int def, int *error)
307 : {
308 : #ifdef HAVE_LIBINI_CONFIG_V1
309 0 : return ini_get_int_config_value(init_data->obj, strict, def, error);
310 : #else
311 : return get_int_config_value(init_data->obj, strict, def, error);
312 : #endif
313 : }
314 :
315 :
316 :
317 : /* Destroy ini config (v1) */
318 :
319 0 : void sss_ini_config_destroy(struct sss_ini_initdata *init_data)
320 : {
321 0 : if (init_data == NULL) return;
322 : #ifdef HAVE_LIBINI_CONFIG_V1
323 0 : if (init_data->sssd_config != NULL) {
324 0 : ini_config_destroy(init_data->sssd_config);
325 0 : init_data->sssd_config = NULL;
326 : }
327 : #else
328 : free_ini_config(init_data->sssd_config);
329 : #endif
330 : }
331 :
332 :
333 :
334 : /* Create LDIF */
335 :
336 0 : int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx,
337 : struct sss_ini_initdata *init_data,
338 : const char **config_ldif)
339 : {
340 : int ret, i, j;
341 : char *ldif;
342 : char *tmp_ldif;
343 : char **sections;
344 : int section_count;
345 : char *dn;
346 : char *tmp_dn;
347 : char *sec_dn;
348 : char **attrs;
349 : int attr_count;
350 : char *ldif_attr;
351 : TALLOC_CTX *tmp_ctx;
352 : size_t dn_size;
353 : size_t ldif_len;
354 : size_t attr_len;
355 : #ifdef HAVE_LIBINI_CONFIG_V1
356 0 : struct value_obj *obj = NULL;
357 : #else
358 : struct collection_item *obj = NULL;
359 : #endif
360 :
361 0 : ldif_len = strlen(CONFDB_INTERNAL_LDIF);
362 0 : ldif = talloc_array(mem_ctx, char, ldif_len+1);
363 0 : if (!ldif) return ENOMEM;
364 :
365 0 : tmp_ctx = talloc_new(ldif);
366 0 : if (!tmp_ctx) {
367 0 : ret = ENOMEM;
368 0 : goto error;
369 : }
370 :
371 0 : memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len);
372 :
373 : /* Read in the collection and convert it to an LDIF */
374 : /* Get the list of sections */
375 0 : sections = sss_ini_get_sec_list(init_data->sssd_config,
376 : §ion_count, &ret);
377 0 : if (ret != EOK) {
378 0 : goto error;
379 : }
380 :
381 0 : for (i = 0; i < section_count; i++) {
382 0 : const char *rdn = NULL;
383 0 : DEBUG(SSSDBG_TRACE_FUNC,
384 : "Processing config section [%s]\n", sections[i]);
385 0 : ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn);
386 0 : if (ret != EOK) {
387 0 : goto error;
388 : }
389 :
390 0 : dn = talloc_asprintf(tmp_ctx,
391 : "dn: %s,cn=config\n"
392 : "cn: %s\n",
393 : sec_dn, rdn);
394 0 : if (!dn) {
395 0 : ret = ENOMEM;
396 0 : free_section_list(sections);
397 0 : goto error;
398 : }
399 0 : dn_size = strlen(dn);
400 :
401 : /* Get all of the attributes and their values as LDIF */
402 0 : attrs = sss_ini_get_attr_list(init_data->sssd_config, sections[i],
403 : &attr_count, &ret);
404 0 : if (ret != EOK) {
405 0 : free_section_list(sections);
406 0 : goto error;
407 : }
408 :
409 0 : for (j = 0; j < attr_count; j++) {
410 0 : DEBUG(SSSDBG_TRACE_FUNC,
411 : "Processing attribute [%s]\n", attrs[j]);
412 0 : ret = sss_ini_get_config_obj(sections[i], attrs[j],
413 : init_data->sssd_config,
414 : INI_GET_FIRST_VALUE, &obj);
415 0 : if (ret != EOK) goto error;
416 :
417 0 : const char *value = sss_ini_get_const_string_config_value(obj, &ret);
418 0 : if (ret != EOK) goto error;
419 0 : if (value && value[0] == '\0') {
420 0 : DEBUG(SSSDBG_CRIT_FAILURE,
421 : "Attribute '%s' has empty value, ignoring\n",
422 : attrs[j]);
423 0 : continue;
424 : }
425 :
426 0 : ldif_attr = talloc_asprintf(tmp_ctx,
427 0 : "%s: %s\n", attrs[j], value);
428 0 : DEBUG(SSSDBG_TRACE_ALL, "%s\n", ldif_attr);
429 :
430 0 : attr_len = strlen(ldif_attr);
431 :
432 0 : tmp_dn = talloc_realloc(tmp_ctx, dn, char,
433 : dn_size+attr_len+1);
434 0 : if (!tmp_dn) {
435 0 : ret = ENOMEM;
436 0 : free_attribute_list(attrs);
437 0 : free_section_list(sections);
438 0 : goto error;
439 : }
440 0 : dn = tmp_dn;
441 0 : memcpy(dn+dn_size, ldif_attr, attr_len+1);
442 0 : dn_size += attr_len;
443 : }
444 :
445 0 : dn_size ++;
446 0 : tmp_dn = talloc_realloc(tmp_ctx, dn, char,
447 : dn_size+1);
448 0 : if (!tmp_dn) {
449 0 : ret = ENOMEM;
450 0 : free_attribute_list(attrs);
451 0 : free_section_list(sections);
452 0 : goto error;
453 : }
454 0 : dn = tmp_dn;
455 0 : dn[dn_size-1] = '\n';
456 0 : dn[dn_size] = '\0';
457 :
458 0 : DEBUG(SSSDBG_TRACE_ALL, "Section dn\n%s\n", dn);
459 :
460 0 : tmp_ldif = talloc_realloc(mem_ctx, ldif, char,
461 : ldif_len+dn_size+1);
462 0 : if (!tmp_ldif) {
463 0 : ret = ENOMEM;
464 0 : free_attribute_list(attrs);
465 0 : free_section_list(sections);
466 0 : goto error;
467 : }
468 0 : ldif = tmp_ldif;
469 0 : memcpy(ldif+ldif_len, dn, dn_size);
470 0 : ldif_len += dn_size;
471 :
472 0 : free_attribute_list(attrs);
473 0 : talloc_free(dn);
474 : }
475 :
476 0 : ldif[ldif_len] = '\0';
477 :
478 0 : free_section_list(sections);
479 :
480 0 : *config_ldif = (const char *)ldif;
481 0 : talloc_free(tmp_ctx);
482 0 : return EOK;
483 :
484 : error:
485 0 : talloc_free(ldif);
486 0 : return ret;
487 : }
|