LCOV - code coverage report
Current view: top level - util - sss_ini.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 139 0.0 %
Date: 2016-06-29 Functions: 0 14 0.0 %

          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 ref_array *ra_success_list;
      50             :     struct ref_array *ra_error_list;
      51             :     struct ini_cfgobj *sssd_config;
      52             :     struct value_obj *obj;
      53             :     const struct stat *cstat;
      54             :     struct ini_cfgfile *file;
      55             : };
      56             : 
      57             : #define sss_ini_get_sec_list                   ini_get_section_list
      58             : #define sss_ini_get_attr_list                  ini_get_attribute_list
      59             : #define sss_ini_get_const_string_config_value  ini_get_const_string_config_value
      60             : #define sss_ini_get_config_obj                 ini_get_config_valueobj
      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             :                        const char *config_dir)
     210             : {
     211             :     int ret;
     212             : #ifdef HAVE_LIBINI_CONFIG_V1
     213             : #ifdef HAVE_LIBINI_CONFIG_V1_3
     214             :     const char *patterns[] = { "^[^\\.].*\\.conf", NULL };
     215             :     const char *sections[] = { ".*", NULL };
     216             :     uint32_t i = 0;
     217             :     char *msg = NULL;
     218             :     struct access_check snip_check;
     219             :     struct ini_cfgobj *modified_sssd_config = NULL;
     220             : #endif /* HAVE_LIBINI_CONFIG_V1_3 */
     221             : 
     222             :     /* Create config object */
     223           0 :     ret = ini_config_create(&(init_data->sssd_config));
     224           0 :     if (ret != EOK) {
     225           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     226             :                 "Failed to create config object. Error %d.\n", ret);
     227           0 :         return ret;
     228             :     }
     229             : 
     230             :     /* Parse file */
     231           0 :     ret = ini_config_parse(init_data->file,
     232             :                            INI_STOP_ON_ANY,
     233             :                            INI_MV1S_OVERWRITE,
     234             :                            INI_PARSE_NOWRAP,
     235             :                            init_data->sssd_config);
     236             : 
     237           0 :     if (ret != EOK) {
     238           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     239             :                 "Failed to parse configuration. Error %d.\n", ret);
     240             : 
     241           0 :         if (ini_config_error_count(init_data->sssd_config)) {
     242           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     243             :                     "Errors detected while parsing: %s\n",
     244             :                      ini_config_get_filename(init_data->file));
     245             : 
     246           0 :             ini_config_get_errors(init_data->sssd_config,
     247             :                                   &init_data->error_list);
     248           0 :             sss_ini_config_print_errors(init_data->error_list);
     249           0 :             ini_config_free_errors(init_data->error_list);
     250             :         }
     251           0 :         ini_config_destroy(init_data->sssd_config);
     252           0 :         init_data->sssd_config = NULL;
     253           0 :         return ret;
     254             :     }
     255             : 
     256             : #ifdef HAVE_LIBINI_CONFIG_V1_3
     257             :     snip_check.flags = INI_ACCESS_CHECK_MODE | INI_ACCESS_CHECK_UID
     258             :                        | INI_ACCESS_CHECK_GID;
     259             :     snip_check.uid = 0; /* owned by root */
     260             :     snip_check.gid = 0; /* owned by root */
     261             :     snip_check.mode = S_IRUSR; /* r**------ */
     262             :     snip_check.mask = ALLPERMS & ~(S_IWUSR | S_IXUSR);
     263             : 
     264             :     ret = ini_config_augment(init_data->sssd_config,
     265             :                              config_dir,
     266             :                              patterns,
     267             :                              sections,
     268             :                              &snip_check,
     269             :                              INI_STOP_ON_ANY,
     270             :                              INI_MV1S_OVERWRITE,
     271             :                              INI_PARSE_NOWRAP,
     272             :                              INI_MV2S_OVERWRITE,
     273             :                              &modified_sssd_config,
     274             :                              &init_data->ra_error_list,
     275             :                              &init_data->ra_success_list);
     276             :     if (ret != EOK) {
     277             :         DEBUG(SSSDBG_CRIT_FAILURE,
     278             :               "Failed to augment configuration [%d]: %s",
     279             :               ret, sss_strerror(ret));
     280             :     }
     281             : 
     282             :     while (ref_array_get(init_data->ra_success_list, i, &msg) != NULL) {
     283             :         DEBUG(SSSDBG_TRACE_FUNC,
     284             :               "Config merge success: %s\n", msg);
     285             :         i++;
     286             :     }
     287             : 
     288             :     i = 0;
     289             :     while (ref_array_get(init_data->ra_error_list, i, &msg) != NULL) {
     290             :         DEBUG(SSSDBG_CRIT_FAILURE,
     291             :               "Config merge error: %s\n", msg);
     292             :         i++;
     293             :     }
     294             : 
     295             :     /* switch config objects if there are no errors */
     296             :     if (modified_sssd_config != NULL) {
     297             :         ini_config_destroy(init_data->sssd_config);
     298             :         init_data->sssd_config = modified_sssd_config;
     299             :     } else {
     300             :         DEBUG(SSSDBG_TRACE_FUNC,
     301             :               "Using only main configuration file due to errors in merging\n");
     302             :     }
     303             : #endif
     304             : 
     305           0 :     return ret;
     306             : 
     307             : #else
     308             : 
     309             :     /* Read the configuration into a collection */
     310             :     ret = config_from_fd("sssd",
     311             :                          init_data->file,
     312             :                          config_file,
     313             :                          &init_data->sssd_config,
     314             :                          INI_STOP_ON_ANY,
     315             :                          &init_data->error_list);
     316             : 
     317             :     if (ret != EOK) {
     318             :         DEBUG(SSSDBG_FATAL_FAILURE,
     319             :                 "Parse error reading configuration file [%s]\n",
     320             :                  config_file);
     321             : 
     322             :         print_file_parsing_errors(stderr, init_data->error_list);
     323             : 
     324             :         free_ini_config_errors(init_data->error_list);
     325             :         free_ini_config(init_data->sssd_config);
     326             : 
     327             :         return ret;
     328             :     }
     329             : 
     330             :     return EOK;
     331             : 
     332             : #endif
     333             : }
     334             : 
     335             : 
     336             : 
     337             : /* Get configuration object */
     338             : 
     339           0 : int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data,
     340             :                        const char *section, const char *name)
     341             : {
     342           0 :     return sss_ini_get_config_obj(section,name, init_data->sssd_config,
     343             :                                   INI_GET_FIRST_VALUE, &init_data->obj);
     344             : }
     345             : 
     346             : 
     347             : 
     348             : /* Check configuration object */
     349             : 
     350           0 : int sss_ini_check_config_obj(struct sss_ini_initdata *init_data)
     351             : {
     352           0 :     if (init_data->obj == NULL) {
     353           0 :         return ENOENT;
     354             :     }
     355             : 
     356           0 :     return EOK;
     357             : }
     358             : 
     359             : 
     360             : 
     361             : /* Get integer value */
     362             : 
     363           0 : int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data,
     364             :                                  int strict, int def, int *error)
     365             : {
     366             : #ifdef HAVE_LIBINI_CONFIG_V1
     367           0 :     return ini_get_int_config_value(init_data->obj, strict, def, error);
     368             : #else
     369             :     return get_int_config_value(init_data->obj, strict, def, error);
     370             : #endif
     371             : }
     372             : 
     373             : 
     374             : 
     375             : /* Destroy ini config (v1) */
     376             : 
     377           0 : void sss_ini_config_destroy(struct sss_ini_initdata *init_data)
     378             : {
     379           0 :     if (init_data == NULL) return;
     380             : #ifdef HAVE_LIBINI_CONFIG_V1
     381           0 :     if (init_data->sssd_config != NULL) {
     382           0 :         ini_config_destroy(init_data->sssd_config);
     383           0 :         init_data->sssd_config = NULL;
     384             :     }
     385             : #else
     386             :     free_ini_config(init_data->sssd_config);
     387             : #endif
     388             : }
     389             : 
     390             : 
     391             : 
     392             : /* Create LDIF */
     393             : 
     394           0 : int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx,
     395             :                            struct sss_ini_initdata *init_data,
     396             :                            const char **config_ldif)
     397             : {
     398             :     int ret, i, j;
     399             :     char *ldif;
     400             :     char *tmp_ldif;
     401             :     char **sections;
     402             :     int section_count;
     403             :     char *dn;
     404             :     char *tmp_dn;
     405             :     char *sec_dn;
     406             :     char **attrs;
     407             :     int attr_count;
     408             :     char *ldif_attr;
     409             :     TALLOC_CTX *tmp_ctx;
     410             :     size_t dn_size;
     411             :     size_t ldif_len;
     412             :     size_t attr_len;
     413             : #ifdef HAVE_LIBINI_CONFIG_V1
     414           0 :     struct value_obj *obj = NULL;
     415             : #else
     416             :     struct collection_item *obj = NULL;
     417             : #endif
     418             : 
     419           0 :     ldif_len = strlen(CONFDB_INTERNAL_LDIF);
     420           0 :     ldif = talloc_array(mem_ctx, char, ldif_len+1);
     421           0 :     if (!ldif) return ENOMEM;
     422             : 
     423           0 :     tmp_ctx = talloc_new(ldif);
     424           0 :     if (!tmp_ctx) {
     425           0 :         ret = ENOMEM;
     426           0 :         goto error;
     427             :     }
     428             : 
     429           0 :     memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len);
     430             : 
     431             :     /* Read in the collection and convert it to an LDIF */
     432             :     /* Get the list of sections */
     433           0 :     sections = sss_ini_get_sec_list(init_data->sssd_config,
     434             :                                     &section_count, &ret);
     435           0 :     if (ret != EOK) {
     436           0 :         goto error;
     437             :     }
     438             : 
     439           0 :     for (i = 0; i < section_count; i++) {
     440           0 :         const char *rdn = NULL;
     441           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     442             :                 "Processing config section [%s]\n", sections[i]);
     443           0 :         ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn);
     444           0 :         if (ret != EOK) {
     445           0 :             goto error;
     446             :         }
     447             : 
     448           0 :         dn = talloc_asprintf(tmp_ctx,
     449             :                              "dn: %s,cn=config\n"
     450             :                              "cn: %s\n",
     451             :                              sec_dn, rdn);
     452           0 :         if (!dn) {
     453           0 :             ret = ENOMEM;
     454           0 :             free_section_list(sections);
     455           0 :             goto error;
     456             :         }
     457           0 :         dn_size = strlen(dn);
     458             : 
     459             :         /* Get all of the attributes and their values as LDIF */
     460           0 :         attrs = sss_ini_get_attr_list(init_data->sssd_config, sections[i],
     461             :                                    &attr_count, &ret);
     462           0 :         if (ret != EOK) {
     463           0 :             free_section_list(sections);
     464           0 :             goto error;
     465             :         }
     466             : 
     467           0 :         for (j = 0; j < attr_count; j++) {
     468           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     469             :                     "Processing attribute [%s]\n", attrs[j]);
     470           0 :             ret = sss_ini_get_config_obj(sections[i], attrs[j],
     471             :                                          init_data->sssd_config,
     472             :                                          INI_GET_FIRST_VALUE, &obj);
     473           0 :             if (ret != EOK) goto error;
     474             : 
     475           0 :             const char *value = sss_ini_get_const_string_config_value(obj, &ret);
     476           0 :             if (ret != EOK) goto error;
     477           0 :             if (value && value[0] == '\0') {
     478           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     479             :                         "Attribute '%s' has empty value, ignoring\n",
     480             :                          attrs[j]);
     481           0 :                 continue;
     482             :             }
     483             : 
     484           0 :             ldif_attr = talloc_asprintf(tmp_ctx,
     485           0 :                                         "%s: %s\n", attrs[j], value);
     486           0 :             DEBUG(SSSDBG_TRACE_ALL, "%s\n", ldif_attr);
     487             : 
     488           0 :             attr_len = strlen(ldif_attr);
     489             : 
     490           0 :             tmp_dn = talloc_realloc(tmp_ctx, dn, char,
     491             :                                     dn_size+attr_len+1);
     492           0 :             if (!tmp_dn) {
     493           0 :                 ret = ENOMEM;
     494           0 :                 free_attribute_list(attrs);
     495           0 :                 free_section_list(sections);
     496           0 :                 goto error;
     497             :             }
     498           0 :             dn = tmp_dn;
     499           0 :             memcpy(dn+dn_size, ldif_attr, attr_len+1);
     500           0 :             dn_size += attr_len;
     501             :         }
     502             : 
     503           0 :         dn_size ++;
     504           0 :         tmp_dn = talloc_realloc(tmp_ctx, dn, char,
     505             :                                 dn_size+1);
     506           0 :         if (!tmp_dn) {
     507           0 :             ret = ENOMEM;
     508           0 :             free_attribute_list(attrs);
     509           0 :             free_section_list(sections);
     510           0 :             goto error;
     511             :         }
     512           0 :         dn = tmp_dn;
     513           0 :         dn[dn_size-1] = '\n';
     514           0 :         dn[dn_size] = '\0';
     515             : 
     516           0 :         DEBUG(SSSDBG_TRACE_ALL, "Section dn\n%s\n", dn);
     517             : 
     518           0 :         tmp_ldif = talloc_realloc(mem_ctx, ldif, char,
     519             :                                   ldif_len+dn_size+1);
     520           0 :         if (!tmp_ldif) {
     521           0 :             ret = ENOMEM;
     522           0 :             free_attribute_list(attrs);
     523           0 :             free_section_list(sections);
     524           0 :             goto error;
     525             :         }
     526           0 :         ldif = tmp_ldif;
     527           0 :         memcpy(ldif+ldif_len, dn, dn_size);
     528           0 :         ldif_len += dn_size;
     529             : 
     530           0 :         free_attribute_list(attrs);
     531           0 :         talloc_free(dn);
     532             :     }
     533             : 
     534           0 :     ldif[ldif_len] = '\0';
     535             : 
     536           0 :     free_section_list(sections);
     537             : 
     538           0 :     *config_ldif = (const char *)ldif;
     539           0 :     talloc_free(tmp_ctx);
     540           0 :     return EOK;
     541             : 
     542             : error:
     543           0 :     talloc_free(ldif);
     544           0 :     return ret;
     545             : }
     546             : 
     547           0 : int sss_ini_call_validators(struct sss_ini_initdata *data,
     548             :                             const char *rules_path)
     549             : {
     550             : #ifdef HAVE_LIBINI_CONFIG_V1_3
     551             :     int ret;
     552             :     struct ini_cfgobj *rules_cfgobj = NULL;
     553             :     struct ini_errobj *errobj = NULL;
     554             : 
     555             :     ret = ini_errobj_create(&errobj);
     556             :     if (ret != EOK) {
     557             :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create error list\n");
     558             :         goto done;
     559             :     }
     560             : 
     561             :     ret = ini_rules_read_from_file(rules_path, &rules_cfgobj);
     562             :     if (ret != EOK) {
     563             :         DEBUG(SSSDBG_FATAL_FAILURE,
     564             :               "Failed to read sssd.conf schema %d [%s]\n", ret, strerror(ret));
     565             :         goto done;
     566             :     }
     567             : 
     568             :     ret = ini_rules_check(rules_cfgobj, data->sssd_config, NULL, errobj);
     569             :     if (ret != EOK) {
     570             :         DEBUG(SSSDBG_FATAL_FAILURE,
     571             :               "ini_rules_check failed %d [%s]\n", ret, strerror(ret));
     572             :         goto done;
     573             :     }
     574             : 
     575             :     /* Do not error out when validators find some issue */
     576             :     while (!ini_errobj_no_more_msgs(errobj)) {
     577             :         DEBUG(SSSDBG_CRIT_FAILURE,
     578             :               "%s\n", ini_errobj_get_msg(errobj));
     579             :         ini_errobj_next(errobj);
     580             :     }
     581             : 
     582             : done:
     583             :     if (rules_cfgobj) ini_config_destroy(rules_cfgobj);
     584             :     ini_errobj_destroy(&errobj);
     585             : 
     586             :     return ret;
     587             : #else
     588           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     589             :           "libini_config does not support configuration file validataion\n");
     590           0 :     return EOK;
     591             : #endif /* HAVE_LIBINI_CONFIG_V1_3 */
     592             : }

Generated by: LCOV version 1.10