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