1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl /* 22*18bdb8a7Smichen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27cb5caa98Sdjl 28cb5caa98Sdjl /* 29cb5caa98Sdjl * routine to read configuration file 30cb5caa98Sdjl * 31cb5caa98Sdjl */ 32cb5caa98Sdjl #include "nscd_config.h" 33cb5caa98Sdjl #include "nscd_log.h" 34cb5caa98Sdjl #include <locale.h> 35cb5caa98Sdjl #include <ctype.h> 36cb5caa98Sdjl #include <string.h> 37cb5caa98Sdjl #include <errno.h> 38cb5caa98Sdjl 39cb5caa98Sdjl static int 40cb5caa98Sdjl strbreak(char *field[], int array_size, char *s, char *sep) 41cb5caa98Sdjl { 42cb5caa98Sdjl int i; 43cb5caa98Sdjl char *lasts, *qp; 44cb5caa98Sdjl int inquote; 45cb5caa98Sdjl 46cb5caa98Sdjl qp = strchr(s, '"'); 47*18bdb8a7Smichen for (i = 0; i < array_size && (field[i] = strtok_r((i?(char *)NULL:s), 48*18bdb8a7Smichen sep, &lasts)); i++) { 49*18bdb8a7Smichen /* empty */ 50*18bdb8a7Smichen } 51cb5caa98Sdjl 52cb5caa98Sdjl if (qp == NULL) 53cb5caa98Sdjl return (i); 54cb5caa98Sdjl 55cb5caa98Sdjl inquote = 1; 56cb5caa98Sdjl while (++qp < lasts) { 57cb5caa98Sdjl 58cb5caa98Sdjl switch (*qp) { 59cb5caa98Sdjl 60cb5caa98Sdjl case '"': 61cb5caa98Sdjl inquote = (inquote == 0); 62cb5caa98Sdjl break; 63cb5caa98Sdjl 64cb5caa98Sdjl case '\\': 65cb5caa98Sdjl /* escape " */ 66cb5caa98Sdjl if (inquote == 1 && *(qp + 1) == '"') 67cb5caa98Sdjl qp++; 68cb5caa98Sdjl break; 69cb5caa98Sdjl 70cb5caa98Sdjl case '\0': 71cb5caa98Sdjl if (inquote == 1) { 72cb5caa98Sdjl *qp = ' '; 73cb5caa98Sdjl i--; 74cb5caa98Sdjl } 75cb5caa98Sdjl 76cb5caa98Sdjl break; 77cb5caa98Sdjl } 78cb5caa98Sdjl } 79cb5caa98Sdjl 80cb5caa98Sdjl return (i); 81cb5caa98Sdjl } 82cb5caa98Sdjl 83cb5caa98Sdjl 84cb5caa98Sdjl nscd_rc_t 85cb5caa98Sdjl _nscd_cfg_read_file( 86cb5caa98Sdjl char *filename, 87cb5caa98Sdjl nscd_cfg_error_t **errorp) 88cb5caa98Sdjl { 89cb5caa98Sdjl char *me = "_nscd_cfg_read_file"; 90cb5caa98Sdjl FILE *in; 91cb5caa98Sdjl char buffer[255]; 92cb5caa98Sdjl char *fields [128]; 93cb5caa98Sdjl int linecnt; 94cb5caa98Sdjl int fieldcnt; 95cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 96cb5caa98Sdjl nscd_cfg_handle_t *h = NULL; 97cb5caa98Sdjl nscd_cfg_param_desc_t *pdesc; 98cb5caa98Sdjl char *dbname, *str; 99cb5caa98Sdjl void *data_p; 100cb5caa98Sdjl int i; 101cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 102cb5caa98Sdjl 103cb5caa98Sdjl union { 104cb5caa98Sdjl int i; 105cb5caa98Sdjl char data[256]; 106cb5caa98Sdjl } u; 107cb5caa98Sdjl 108cb5caa98Sdjl if ((in = fopen(filename, "r")) == NULL) { 109cb5caa98Sdjl 110cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 111cb5caa98Sdjl gettext("open of configuration file \"%s\" failed: %s"), 112cb5caa98Sdjl filename, strerror(errno)); 113cb5caa98Sdjl if (errorp != NULL) 114cb5caa98Sdjl *errorp = _nscd_cfg_make_error( 115cb5caa98Sdjl NSCD_CFG_FILE_OPEN_ERROR, msg); 116cb5caa98Sdjl 117cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 118cb5caa98Sdjl (me, "%s\n", msg); 119cb5caa98Sdjl 120cb5caa98Sdjl return (NSCD_CFG_FILE_OPEN_ERROR); 121cb5caa98Sdjl } 122cb5caa98Sdjl 123cb5caa98Sdjl linecnt = 0; 124cb5caa98Sdjl msg[0] = '\0'; 125cb5caa98Sdjl while (fgets(buffer, sizeof (buffer), in) != NULL) { 126cb5caa98Sdjl 127cb5caa98Sdjl linecnt++; 128cb5caa98Sdjl if ((fieldcnt = strbreak(fields, 128, buffer, " \t\n")) == 129cb5caa98Sdjl 0 || *fields[0] == '#') { 130cb5caa98Sdjl /* skip blank or comment lines */ 131cb5caa98Sdjl continue; 132cb5caa98Sdjl } 133cb5caa98Sdjl 134cb5caa98Sdjl switch (fieldcnt) { 135cb5caa98Sdjl 136cb5caa98Sdjl case 2: 137cb5caa98Sdjl dbname = NULL; 138cb5caa98Sdjl str = fields[1]; 139cb5caa98Sdjl break; 140cb5caa98Sdjl 141cb5caa98Sdjl case 3: 142cb5caa98Sdjl dbname = fields[1]; 143cb5caa98Sdjl str = fields[2]; 144cb5caa98Sdjl break; 145cb5caa98Sdjl 146cb5caa98Sdjl default: 147cb5caa98Sdjl 148cb5caa98Sdjl (void) strlcpy(u.data, fields[0], sizeof (u.data)); 149cb5caa98Sdjl for (i = 1; i < fieldcnt; i++) { 150cb5caa98Sdjl (void) strlcat(u.data, " ", 151cb5caa98Sdjl sizeof (u.data)); 152cb5caa98Sdjl (void) strlcat(u.data, fields[i], 153cb5caa98Sdjl sizeof (u.data)); 154cb5caa98Sdjl } 155cb5caa98Sdjl 156cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 157cb5caa98Sdjl gettext("Syntax error: line %d of configuration " 158cb5caa98Sdjl "file: %s : \"%s\""), linecnt, filename, u.data); 159cb5caa98Sdjl if (errorp != NULL) 160cb5caa98Sdjl *errorp = _nscd_cfg_make_error( 161cb5caa98Sdjl NSCD_CFG_SYNTAX_ERROR, msg); 162cb5caa98Sdjl 163cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 164cb5caa98Sdjl (me, "%s\n", msg); 165cb5caa98Sdjl 166cb5caa98Sdjl rc = NSCD_CFG_SYNTAX_ERROR; 167cb5caa98Sdjl break; 168cb5caa98Sdjl } 169cb5caa98Sdjl 170cb5caa98Sdjl if (rc != NSCD_SUCCESS) 171cb5caa98Sdjl break; 172cb5caa98Sdjl 173cb5caa98Sdjl rc = _nscd_cfg_get_handle(fields[0], dbname, &h, errorp); 174cb5caa98Sdjl if (rc != NSCD_SUCCESS) 175cb5caa98Sdjl break; 176cb5caa98Sdjl 177cb5caa98Sdjl pdesc = _nscd_cfg_get_desc(h); 178cb5caa98Sdjl 179cb5caa98Sdjl /* convert string to data */ 180cb5caa98Sdjl rc = _nscd_cfg_str_to_data(pdesc, str, &u.data, 181cb5caa98Sdjl &data_p, errorp); 182cb5caa98Sdjl if (rc != NSCD_SUCCESS) 183cb5caa98Sdjl break; 184cb5caa98Sdjl 185cb5caa98Sdjl /* do preliminary check based on data type */ 186cb5caa98Sdjl rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp); 187cb5caa98Sdjl if (rc != NSCD_SUCCESS) 188cb5caa98Sdjl break; 189cb5caa98Sdjl 190cb5caa98Sdjl rc = _nscd_cfg_set_linked(h, data_p, errorp); 191cb5caa98Sdjl _nscd_cfg_free_handle(h); 192cb5caa98Sdjl h = NULL; 193cb5caa98Sdjl if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS) 194cb5caa98Sdjl break; 195cb5caa98Sdjl else { 196cb5caa98Sdjl _nscd_cfg_free_error(*errorp); 197cb5caa98Sdjl *errorp = NULL; 198cb5caa98Sdjl } 199cb5caa98Sdjl } 200cb5caa98Sdjl /* NSCD_CFG_READ_ONLY is not fatal */ 201cb5caa98Sdjl if (rc == NSCD_CFG_READ_ONLY) 202cb5caa98Sdjl rc = NSCD_SUCCESS; 203cb5caa98Sdjl 204cb5caa98Sdjl if (h != NULL) 205cb5caa98Sdjl _nscd_cfg_free_handle(h); 206cb5caa98Sdjl 207cb5caa98Sdjl (void) fclose(in); 208cb5caa98Sdjl 209cb5caa98Sdjl if (msg[0] == '\0' && rc != NSCD_SUCCESS) { 210cb5caa98Sdjl if (errorp != NULL) 211cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 212cb5caa98Sdjl (me, "%s\n", NSCD_ERR2MSG(*errorp)); 213cb5caa98Sdjl } 214cb5caa98Sdjl 215cb5caa98Sdjl return (rc); 216cb5caa98Sdjl } 217cb5caa98Sdjl 218cb5caa98Sdjl nscd_rc_t 219cb5caa98Sdjl _nscd_cfg_read_nsswitch_file( 220cb5caa98Sdjl char *filename, 221cb5caa98Sdjl nscd_cfg_error_t **errorp) 222cb5caa98Sdjl { 223cb5caa98Sdjl char *me = "_nscd_cfg_read_nsswitch_file"; 224cb5caa98Sdjl char *pname = "nsw-config-string"; 225cb5caa98Sdjl FILE *in; 226cb5caa98Sdjl char buffer[255]; 227cb5caa98Sdjl char *cc, *ce, *ce1, *c1, *c2; 228cb5caa98Sdjl char *db, *dbe; 229cb5caa98Sdjl char *nsscfg; 230cb5caa98Sdjl int syntax_err; 231cb5caa98Sdjl int linecnt; 232cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 233cb5caa98Sdjl nscd_cfg_handle_t *h = NULL; 234cb5caa98Sdjl nscd_cfg_param_desc_t *pdesc; 235cb5caa98Sdjl void *data_p; 236cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 237cb5caa98Sdjl 238cb5caa98Sdjl union { 239cb5caa98Sdjl int i; 240cb5caa98Sdjl char data[256]; 241cb5caa98Sdjl } u; 242cb5caa98Sdjl 243cb5caa98Sdjl if ((in = fopen(filename, "r")) == NULL) { 244cb5caa98Sdjl 245cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 246cb5caa98Sdjl gettext("open of configuration file \"%s\" failed: %s"), 247cb5caa98Sdjl filename, strerror(errno)); 248cb5caa98Sdjl if (errorp != NULL) 249cb5caa98Sdjl *errorp = _nscd_cfg_make_error( 250cb5caa98Sdjl NSCD_CFG_FILE_OPEN_ERROR, msg); 251cb5caa98Sdjl 252cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 253cb5caa98Sdjl (me, "%s\n", msg); 254cb5caa98Sdjl 255cb5caa98Sdjl return (NSCD_CFG_FILE_OPEN_ERROR); 256cb5caa98Sdjl } 257cb5caa98Sdjl 258cb5caa98Sdjl linecnt = 0; 259cb5caa98Sdjl msg[0] = '\0'; 260cb5caa98Sdjl while (fgets(buffer, sizeof (buffer), in) != NULL) { 261cb5caa98Sdjl 262cb5caa98Sdjl linecnt++; 263cb5caa98Sdjl syntax_err = 0; 264cb5caa98Sdjl /* skip blank or comment lines */ 265cb5caa98Sdjl if (buffer[0] == '#' || buffer[0] == '\n') 266cb5caa98Sdjl continue; 267cb5caa98Sdjl /* skip end of line comment */ 268cb5caa98Sdjl if ((ce = strchr(buffer, '\n')) != NULL) 269cb5caa98Sdjl *ce = '\0'; 270cb5caa98Sdjl else 271cb5caa98Sdjl ce = &buffer[255]; 272cb5caa98Sdjl if ((ce1 = strchr(buffer, '#')) != NULL) { 273cb5caa98Sdjl ce = ce1; 274cb5caa98Sdjl *ce = '\0'; 275cb5caa98Sdjl } 276cb5caa98Sdjl if ((cc = strchr(buffer, ':')) == NULL) { 277cb5caa98Sdjl c1 = buffer; 278cb5caa98Sdjl while (isalpha(*c1) && c1 < ce) 279cb5caa98Sdjl c1++; 280cb5caa98Sdjl if (c1 > ce) 281cb5caa98Sdjl syntax_err = 1; 282cb5caa98Sdjl else /* blank line */ 283cb5caa98Sdjl continue; 284cb5caa98Sdjl } else { 285cb5caa98Sdjl /* 286cb5caa98Sdjl * data name goes before ':', 287cb5caa98Sdjl * skip spaces on both ends 288cb5caa98Sdjl */ 289cb5caa98Sdjl c2 = cc - 1; 290cb5caa98Sdjl while (buffer <= c2 && isspace(*c2)) 291cb5caa98Sdjl c2--; 292cb5caa98Sdjl c1 = buffer; 293cb5caa98Sdjl while (c1 <= cc && isspace(*c1)) 294cb5caa98Sdjl c1++; 295cb5caa98Sdjl if (c1 > c2) 296cb5caa98Sdjl syntax_err = 1; 297cb5caa98Sdjl else { 298cb5caa98Sdjl db = c1; 299cb5caa98Sdjl dbe = c2 + 1; 300cb5caa98Sdjl 301cb5caa98Sdjl /* 302cb5caa98Sdjl * nss config goes after ':', 303cb5caa98Sdjl * skip spaces on both ends 304cb5caa98Sdjl */ 305cb5caa98Sdjl c1 = cc + 1; 306cb5caa98Sdjl while (c1 <= ce && isspace(*c1)) 307cb5caa98Sdjl c1++; 308cb5caa98Sdjl c2 = ce - 1; 309cb5caa98Sdjl while (cc <= c2 && isspace(*c2)) 310cb5caa98Sdjl c2--; 311*18bdb8a7Smichen if (c1 > c2) { 312*18bdb8a7Smichen /* no source specified, it's OK */ 313*18bdb8a7Smichen continue; 314*18bdb8a7Smichen } else { 315cb5caa98Sdjl *dbe = '\0'; 316cb5caa98Sdjl nsscfg = c1; 317cb5caa98Sdjl *(c2 + 1) = '\0'; 318cb5caa98Sdjl } 319cb5caa98Sdjl } 320cb5caa98Sdjl } 321cb5caa98Sdjl 322cb5caa98Sdjl if (syntax_err == 1) { 323cb5caa98Sdjl 324cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 325cb5caa98Sdjl gettext("Syntax error: line %d of configuration " 326cb5caa98Sdjl "file: %s : \"%s\""), linecnt, filename, buffer); 327cb5caa98Sdjl if (errorp != NULL) 328cb5caa98Sdjl *errorp = _nscd_cfg_make_error( 329cb5caa98Sdjl NSCD_CFG_SYNTAX_ERROR, msg); 330cb5caa98Sdjl 331cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 332cb5caa98Sdjl (me, "%s\n", msg); 333cb5caa98Sdjl 334cb5caa98Sdjl rc = NSCD_CFG_SYNTAX_ERROR; 335cb5caa98Sdjl return (rc); 336cb5caa98Sdjl } 337cb5caa98Sdjl 338cb5caa98Sdjl rc = _nscd_cfg_get_handle(pname, db, &h, errorp); 339cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 340cb5caa98Sdjl /* ignore unsupported switch database */ 341cb5caa98Sdjl if (rc == NSCD_CFG_UNSUPPORTED_SWITCH_DB) { 342cb5caa98Sdjl _nscd_cfg_free_error(*errorp); 343cb5caa98Sdjl *errorp = NULL; 344cb5caa98Sdjl rc = NSCD_SUCCESS; 345cb5caa98Sdjl continue; 346cb5caa98Sdjl } 347cb5caa98Sdjl break; 348cb5caa98Sdjl } 349cb5caa98Sdjl 350cb5caa98Sdjl pdesc = _nscd_cfg_get_desc(h); 351cb5caa98Sdjl 352cb5caa98Sdjl /* convert string to data */ 353cb5caa98Sdjl rc = _nscd_cfg_str_to_data(pdesc, nsscfg, &u.data, 354cb5caa98Sdjl &data_p, errorp); 355cb5caa98Sdjl if (rc != NSCD_SUCCESS) 356cb5caa98Sdjl break; 357cb5caa98Sdjl 358cb5caa98Sdjl /* do preliminary check based on data type */ 359cb5caa98Sdjl rc = _nscd_cfg_prelim_check(pdesc, data_p, errorp); 360cb5caa98Sdjl if (rc != NSCD_SUCCESS) 361cb5caa98Sdjl break; 362cb5caa98Sdjl 363cb5caa98Sdjl rc = _nscd_cfg_set_linked(h, data_p, errorp); 364cb5caa98Sdjl _nscd_cfg_free_handle(h); 365cb5caa98Sdjl h = NULL; 366cb5caa98Sdjl if (rc != NSCD_CFG_READ_ONLY && rc != NSCD_SUCCESS) 367cb5caa98Sdjl break; 368cb5caa98Sdjl else { 369cb5caa98Sdjl _nscd_cfg_free_error(*errorp); 370cb5caa98Sdjl *errorp = NULL; 371cb5caa98Sdjl } 372cb5caa98Sdjl } 373cb5caa98Sdjl /* NSCD_CFG_READ_ONLY is not fatal */ 374cb5caa98Sdjl if (rc == NSCD_CFG_READ_ONLY) 375cb5caa98Sdjl rc = NSCD_SUCCESS; 376cb5caa98Sdjl 377cb5caa98Sdjl if (h != NULL) 378cb5caa98Sdjl _nscd_cfg_free_handle(h); 379cb5caa98Sdjl 380cb5caa98Sdjl (void) fclose(in); 381cb5caa98Sdjl 382cb5caa98Sdjl if (msg[0] == '\0' && rc != NSCD_SUCCESS) { 383cb5caa98Sdjl if (errorp != NULL) 384cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 385cb5caa98Sdjl (me, "%s\n", NSCD_ERR2MSG(*errorp)); 386cb5caa98Sdjl } 387cb5caa98Sdjl 388cb5caa98Sdjl return (rc); 389cb5caa98Sdjl } 390