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