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