1 /*	$OpenBSD: stringlist.c,v 1.4 2023/01/04 13:00:11 jsg Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Christos Zoulas
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <netgroup.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include "stringlist.h"
36 
37 static const char _ngstar[] = "*";
38 
39 static int		getstring(char **, int, char **);
40 static struct netgroup	*getnetgroup(char **);
41 
42 /*
43  * _ng_sl_init(): Initialize a string list
44  */
45 struct stringlist *
_ng_sl_init(void)46 _ng_sl_init(void)
47 {
48 	struct stringlist *sl = malloc(sizeof(struct stringlist));
49 	if (sl == NULL)
50 		return NULL;
51 
52 	sl->sl_cur = 0;
53 	sl->sl_max = 20;
54 	sl->sl_str = calloc(sl->sl_max, sizeof(char *));
55 	if (sl->sl_str == NULL) {
56 		free(sl);
57 		return NULL;
58 	}
59 	return sl;
60 }
61 
62 
63 /*
64  * _ng_sl_add(): Add an item to the string list
65  */
66 int
_ng_sl_add(struct stringlist * sl,char * name)67 _ng_sl_add(struct stringlist *sl, char *name)
68 {
69 	if (sl->sl_cur == sl->sl_max - 1) {
70 		char **slstr;
71 
72 		sl->sl_max += 20;
73 		slstr = reallocarray(sl->sl_str, sl->sl_max, sizeof(char *));
74 		if (slstr == NULL) {
75 			free(sl->sl_str);
76 			sl->sl_str = NULL;
77 			return -1;
78 		}
79 		sl->sl_str = slstr;
80 	}
81 	sl->sl_str[sl->sl_cur++] = name;
82 	return 0;
83 }
84 
85 
86 /*
87  * _ng_sl_free(): Free a stringlist
88  */
89 void
_ng_sl_free(struct stringlist * sl,int all)90 _ng_sl_free(struct stringlist *sl, int all)
91 {
92 	size_t	i;
93 
94 	if (all)
95 		for (i = 0; i < sl->sl_cur; i++)
96 			free(sl->sl_str[i]);
97 	free(sl->sl_str);
98 	free(sl);
99 }
100 
101 
102 /*
103  * sl_find(): Find a name in the string list
104  */
105 char *
_ng_sl_find(struct stringlist * sl,char * name)106 _ng_sl_find(struct stringlist *sl, char *name)
107 {
108 	size_t	i;
109 
110 	for (i = 0; i < sl->sl_cur; i++)
111 		if (strcmp(sl->sl_str[i], name) == 0)
112 			return sl->sl_str[i];
113 
114 	return NULL;
115 }
116 
117 /*
118  * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
119  * line was empty or a comment _NG_GROUP: line had a netgroup definition,
120  * returned in ng _NG_NAME:  line had a netgroup name, returned in name
121  *
122  * Public since used by netgroup_mkdb
123  */
124 int
_ng_parse(char ** p,char ** name,struct netgroup ** ng)125 _ng_parse(char **p, char **name, struct netgroup **ng)
126 {
127 	while (**p) {
128 		if (**p == '#')
129 			/* comment */
130 			return _NG_NONE;
131 
132 		while (**p && _NG_ISSPACE(**p))
133 			/* skipblank */
134 			(*p)++;
135 
136 		if (**p == '(') {
137 			if ((*ng = getnetgroup(p)) == NULL)
138 				return _NG_ERROR;
139 			return _NG_GROUP;
140 		} else {
141 			char	*np;
142 			int	i;
143 
144 			for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
145 				continue;
146 			if (np != *p) {
147 				i = (*p - np) + 1;
148 				*name = malloc(i);
149 				if (*name == NULL)
150 					return _NG_ERROR;
151 				memcpy(*name, np, i);
152 				(*name)[i - 1] = '\0';
153 				return _NG_NAME;
154 			}
155 		}
156 	}
157 	return _NG_NONE;
158 }
159 
160 /*
161  * _ng_makekey(): Make a key from the two names given. The key is of the form
162  * <name1>.<name2> Names strings are replaced with * if they are empty;
163  */
164 char *
_ng_makekey(const char * s1,const char * s2,size_t len)165 _ng_makekey(const char *s1, const char *s2, size_t len)
166 {
167 	char *buf = malloc(len);
168 	int ret;
169 
170 	if (buf == NULL)
171 		return NULL;
172 	ret = snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
173 	if (ret < 0 || ret >= len) {
174 		free(buf);
175 		return NULL;
176 	}
177 
178 	return buf;
179 }
180 
181 void
_ng_print(char * buf,size_t len,const struct netgroup * ng)182 _ng_print(char *buf, size_t len, const struct netgroup *ng)
183 {
184 	(void) snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host),
185 	    _NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain));
186 }
187 
188 /*
189  * getnetgroup(): Parse a netgroup, and advance the pointer
190  */
191 static struct netgroup *
getnetgroup(char ** pp)192 getnetgroup(char **pp)
193 {
194 	struct netgroup *ng = malloc(sizeof(struct netgroup));
195 
196 	if (ng == NULL)
197 		return NULL;
198 
199 	(*pp)++;	/* skip '(' */
200 	if (!getstring(pp, ',', &ng->ng_host))
201 		goto badhost;
202 
203 	if (!getstring(pp, ',', &ng->ng_user))
204 		goto baduser;
205 
206 	if (!getstring(pp, ')', &ng->ng_domain))
207 		goto baddomain;
208 
209 #ifdef DEBUG_NG
210 	{
211 		char buf[1024];
212 		_ng_print(buf, sizeof(buf), ng);
213 		fprintf(stderr, "netgroup %s\n", buf);
214 	}
215 #endif
216 	return ng;
217 
218 baddomain:
219 	free(ng->ng_user);
220 baduser:
221 	free(ng->ng_host);
222 badhost:
223 	free(ng);
224 	return NULL;
225 }
226 
227 /*
228  * getstring(): Get a string delimited by the character, skipping leading and
229  * trailing blanks and advancing the pointer
230  */
231 static int
getstring(char ** pp,int del,char ** str)232 getstring(char **pp, int del, char **str)
233 {
234 	char *sp, *ep, *dp;
235 
236 	/* skip leading blanks */
237 	for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
238 		continue;
239 
240 	/* accumulate till delimiter or space */
241 	for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
242 		continue;
243 
244 	/* hunt for the delimiter */
245 	for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
246 		continue;
247 
248 	if (*dp != del) {
249 		*str = NULL;
250 		return 0;
251 	}
252 
253 	*pp = ++dp;
254 
255 	del = (ep - sp) + 1;
256 	if (del > 1) {
257 		dp = malloc(del);
258 		if (dp == NULL)
259 			return 0;
260 		memcpy(dp, sp, del);
261 		dp[del - 1] = '\0';
262 	} else
263 		dp = NULL;
264 
265 	*str = dp;
266 	return 1;
267 }
268