xref: /illumos-gate/usr/src/cmd/lp/lib/access/bang.c (revision 08cab4be4299a328b9f434f66247c070e06b5845)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2016 by Delphix. All rights reserved.
26  */
27 
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2	*/
33 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
34 
35 #include "string.h"
36 #include "unistd.h"
37 #include "stdlib.h"
38 #include "sys/utsname.h"
39 
40 #include "lp.h"
41 
42 /*
43  * The rules:
44  *
45  *	Key:	A - some system
46  *		X - some user
47  *
48  *	X	a user named X on the local system
49  *	A!X	the user named X from the system A
50  *	all!X	all users named X from any system
51  *	all	all users from local system
52  *	A!all	all users from the system A
53  *	all!all	all users from any system
54  */
55 
56 
57 /**
58  ** bangequ() - LIKE STREQU, BUT HANDLES system!name CASES
59  **/
60 
61 int
62 bangequ (char *user1p, char *user2p)
63 {
64 	int	sysname1_all	= 0,
65 		username1_all	= 0;
66 	int	sysname2_all	= 0,
67 		username2_all	= 0;
68 	char	sysname1[BUFSIZ],
69 		sysname2[BUFSIZ];
70 	char	username1[BUFSIZ],
71 		username2[BUFSIZ],
72 		*sp;
73 
74 	static	char *Nodenamep = (char *) 0;
75 
76 	if (! user1p || ! user2p)
77 		return	1;
78 
79 	if (! Nodenamep) {
80 		struct utsname	utsbuf;
81 
82 		(void)	uname (&utsbuf);
83 		Nodenamep = Strdup (utsbuf.nodename);
84 	}
85 
86 	/* pattern=all */
87 	if (STREQU (NAME_ALL, user2p) || STREQU(NAME_ALL, user1p))
88 		return	1;
89 
90 	if ((sp = strrchr(user1p, '@')) != NULL) {	 /* user@host */
91 		*sp++ = '\0';
92 		(void) snprintf(sysname1, sizeof (sysname1), "%s", sp);
93 		(void) snprintf(username1, sizeof (username1), "%s", user1p);
94 		*--sp = '@';
95 	} else if ((sp = strchr(user1p, '!')) != NULL) { /* host!user */
96 		*sp++ = '\0';
97 		(void) snprintf(sysname1, sizeof (sysname1), "%s", user1p);
98 		(void) snprintf(username1, sizeof (username1), "%s", sp);
99 		*--sp = '!';
100 	} else {					 /* user */
101 		(void) snprintf(sysname1, sizeof (sysname1), "%s", Nodenamep);
102 		(void) snprintf(username1, sizeof (username1), "%s", user1p);
103 	}
104 
105 	sysname1_all = STREQU (NAME_ALL, sysname1);
106 	username1_all = STREQU (NAME_ALL, username1);
107 
108 	/* user2p is simple user name */
109 	if (strpbrk (user2p, "!@") == NULL)
110 		return	(username1_all && sysname1_all) ||
111 			 STREQU (username1, user2p);
112 
113 	if ((sp = strrchr(user2p, '@')) != NULL) {	 /* user@host */
114 		*sp++ = '\0';
115 		(void) snprintf(sysname2, sizeof (sysname2), "%s", sp);
116 		(void) snprintf(username2, sizeof (username2), "%s", user2p);
117 		*--sp = '@';
118 	} else if ((sp = strchr(user2p, '!')) != NULL) { /* host!user */
119 		*sp++ = '\0';
120 		(void) snprintf(sysname2, sizeof (sysname2), "%s", user2p);
121 		(void) snprintf(username2, sizeof (username2), "%s", sp);
122 		*--sp = '!';
123 	} else {					 /* user */
124 		(void) snprintf(sysname2, sizeof (sysname2), "%s", Nodenamep);
125 		(void) snprintf(username2, sizeof (username2), "%s", user1p);
126 	}
127 
128 	sysname2_all = STREQU (NAME_ALL, sysname2);
129 	username2_all = STREQU (NAME_ALL, username2);
130 
131 	if ((sysname1_all && username1_all) ||
132 	    (sysname2_all && username2_all) ||
133 	    (sysname1_all && username2_all) ||
134 	    (sysname2_all && username1_all))
135 		return 1;
136 
137 	if (sysname1_all || sysname2_all)
138 		return	STREQU (username1, username2);
139 
140 	if (username1_all || username2_all)
141 		return STREQU (sysname1, sysname2);
142 
143 	if (STREQU (sysname1, sysname2) && STREQU (username1, username2))
144 		return 1;
145 
146 	return 0;
147 }
148 
149 /**
150  ** bang_searchlist() - SEARCH (char **) LIST FOR "system!user" ITEM
151  **/
152 int
153 bang_searchlist(char *item, char **list)
154 {
155 	if (!list || !*list)
156 		return (0);
157 
158 	/*
159 	 * This is a linear search--we believe that the lists
160 	 * will be short.
161 	 */
162 	while (*list) {
163 		if (bangequ(item, *list))
164 			return (1);
165 		list++;
166 	}
167 	return (0);
168 }
169 
170 /**
171  ** bang_dellist() - REMOVE "system!name" ITEM FROM (char **) LIST
172  **/
173 
174 int
175 bang_dellist(char ***plist, char *item)
176 {
177 	register char **	pl;
178 	register char **	ql;
179 
180 	register int		n;
181 
182 				/*
183 				 * "hole" is a pointer guaranteed not
184 				 * to point to anyplace malloc'd.
185 				 */
186 	char *			hole	= "";
187 
188 
189 	/*
190 	 * There are two ways this routine is different from the
191 	 * regular "dellist()" routine: First, the items are of the form
192 	 * ``system!name'', which means there is a two part matching
193 	 * for ``all'' cases (all systems and/or all names). Second,
194 	 * ALL matching items in the list are deleted.
195 	 *
196 	 * Now suppose the list contains just the word ``all'', and
197 	 * the item to be deleted is the name ``foo''. What will
198 	 * happen? The word ``all'' will be deleted, leaving the list
199 	 * empty (null)! This may sound odd at first, but keep in mind
200 	 * that this routine is paired with the regular "addlist()"
201 	 * routine; the item (``foo'') is ADDED to an opposite list
202 	 * (we are either deleting from a deny list and adding to an allow
203 	 * list or vice versa). So, to continue the example, if previously
204 	 * ``all'' were allowed, removing ``foo'' from the allow list
205 	 * does indeed empty that list, but then putting it in the deny
206 	 * list means only ``foo'' is denied, which is the effect we
207 	 * want.
208 	 */
209 
210 	if (*plist) {
211 
212 		for (pl = *plist; *pl; pl++)
213 			if (bangequ(item, *pl)) {
214 				Free (*pl);
215 				*pl = hole;
216 			}
217 
218 		for (n = 0, ql = pl = *plist; *pl; pl++)
219 			if (*pl != hole) {
220 				*ql++ = *pl;
221 				n++;
222 			}
223 
224 		if (n == 0) {
225 			Free ((char *)*plist);
226 			*plist = 0;
227 		} else {
228 			*plist = (char **)Realloc(
229 				(char *)*plist,
230 				(n + 1) * sizeof(char *)
231 			);
232 			if (!*plist)
233 				return (-1);
234 			(*plist)[n] = 0;
235 		}
236 	}
237 
238 	return (0);
239 }
240