1 /*	$OpenBSD: alias.c,v 1.5 2002/09/06 22:56:21 deraadt Exp $	*/
2 /*
3  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Niels Provos.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/stat.h>
35 #include <sys/tree.h>
36 #include <limits.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <grp.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <ctype.h>
44 #include <err.h>
45 
46 #include "intercept.h"
47 #include "systrace.h"
48 
49 static SPLAY_HEAD(alitr, systrace_alias) aliasroot;
50 static SPLAY_HEAD(revtr, systrace_revalias) revroot;
51 
52 static int aliascompare(struct systrace_alias *, struct systrace_alias *);
53 static int revcompare(struct systrace_revalias *, struct systrace_revalias *);
54 
55 static int
aliascompare(struct systrace_alias * a,struct systrace_alias * b)56 aliascompare(struct systrace_alias *a, struct systrace_alias *b)
57 {
58 	int diff;
59 
60 	diff = strcmp(a->emulation, b->emulation);
61 	if (diff)
62 		return (diff);
63 	return (strcmp(a->name, b->name));
64 }
65 
66 static int
revcompare(struct systrace_revalias * a,struct systrace_revalias * b)67 revcompare(struct systrace_revalias *a, struct systrace_revalias *b)
68 {
69 	int diff;
70 
71 	diff = strcmp(a->emulation, b->emulation);
72 	if (diff)
73 		return (diff);
74 	return (strcmp(a->name, b->name));
75 }
76 
SPLAY_PROTOTYPE(alitr,systrace_alias,node,aliascompare)77 SPLAY_PROTOTYPE(alitr, systrace_alias, node, aliascompare)
78 SPLAY_GENERATE(alitr, systrace_alias, node, aliascompare)
79 
80 SPLAY_PROTOTYPE(revtr, systrace_revalias, node, revcompare)
81 SPLAY_GENERATE(revtr, systrace_revalias, node, revcompare)
82 
83 int
84 systrace_initalias(void)
85 {
86 	SPLAY_INIT(&aliasroot);
87 	SPLAY_INIT(&revroot);
88 
89 	return (0);
90 }
91 
92 struct systrace_alias *
systrace_find_alias(const char * emulation,const char * name)93 systrace_find_alias(const char *emulation, const char *name)
94 {
95 	struct systrace_alias tmp;
96 
97 	strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation));
98 	strlcpy(tmp.name, name, sizeof(tmp.name));
99 
100 	return (SPLAY_FIND(alitr, &aliasroot, &tmp));
101 }
102 
103 struct systrace_revalias *
systrace_find_reverse(const char * emulation,const char * name)104 systrace_find_reverse(const char *emulation, const char *name)
105 {
106 	struct systrace_revalias tmp;
107 
108 	strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation));
109 	strlcpy(tmp.name, name, sizeof(tmp.name));
110 
111 	return (SPLAY_FIND(revtr, &revroot, &tmp));
112 }
113 
114 struct systrace_revalias *
systrace_reverse(const char * emulation,const char * name)115 systrace_reverse(const char *emulation, const char *name)
116 {
117 	struct systrace_revalias tmp, *reverse;
118 
119 	strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation));
120 	strlcpy(tmp.name, name, sizeof(tmp.name));
121 
122 	reverse = SPLAY_FIND(revtr, &revroot, &tmp);
123 	if (reverse != NULL)
124 		return (reverse);
125 
126 	reverse = calloc(1, sizeof(struct systrace_alias));
127 	if (reverse == NULL)
128 		err(1, "%s: %s-%s: malloc", __func__, emulation, name);
129 
130 	strlcpy(reverse->emulation, emulation, sizeof(reverse->emulation));
131 	strlcpy(reverse->name, name, sizeof(reverse->name));
132 
133 	TAILQ_INIT(&reverse->revl);
134 
135 	if (SPLAY_INSERT(revtr, &revroot, reverse) != NULL)
136 		errx(1, "%s: %s-%s: double revalias",
137 		    __func__, emulation, name);
138 
139 	return (reverse);
140 }
141 
142 struct systrace_alias *
systrace_new_alias(const char * emulation,const char * name,char * aemul,char * aname)143 systrace_new_alias(const char *emulation, const char *name,
144     char *aemul, char *aname)
145 {
146 	struct systrace_alias *alias;
147 	struct systrace_revalias *reverse;
148 
149 	alias = malloc(sizeof(struct systrace_alias));
150 	if (alias == NULL)
151 		err(1, "%s: %s-%s: malloc", __func__, emulation, name);
152 
153 	strlcpy(alias->emulation, emulation, sizeof(alias->emulation));
154 	strlcpy(alias->name, name, sizeof(alias->name));
155 	strlcpy(alias->aemul, aemul, sizeof(alias->aemul));
156 	strlcpy(alias->aname, aname, sizeof(alias->aname));
157 	alias->nargs = 0;
158 
159 	if (SPLAY_INSERT(alitr, &aliasroot, alias) != NULL)
160 		errx(1, "%s: %s-%s: double alias", __func__, emulation, name);
161 
162 	reverse = systrace_reverse(aemul, aname);
163 	alias->reverse = reverse;
164 	TAILQ_INSERT_TAIL(&reverse->revl, alias, next);
165 
166 	return (alias);
167 }
168 
169 void
systrace_switch_alias(const char * emulation,const char * name,char * aemul,char * aname)170 systrace_switch_alias(const char *emulation, const char *name,
171     char *aemul, char *aname)
172 {
173 	struct systrace_alias *alias;
174 	struct systrace_revalias *reverse;
175 
176 	if ((alias = systrace_find_alias(emulation, name)) == NULL)
177 		errx(1, "%s: unknown alias %s-%s", __func__, emulation, name);
178 
179 	/* Switch to a different alias */
180 	reverse = alias->reverse;
181 	TAILQ_REMOVE(&reverse->revl, alias, next);
182 
183 	strlcpy(alias->aemul, aemul, sizeof(alias->aemul));
184 	strlcpy(alias->aname, aname, sizeof(alias->aname));
185 
186 	reverse = systrace_reverse(aemul, aname);
187 	alias->reverse = reverse;
188 	TAILQ_INSERT_TAIL(&reverse->revl, alias, next);
189 }
190 
191 /* Add an already translated argument to this alias */
192 
193 void
systrace_alias_add_trans(struct systrace_alias * alias,struct intercept_translate * tl)194 systrace_alias_add_trans(struct systrace_alias *alias,
195     struct intercept_translate *tl)
196 {
197 	if (alias->nargs >= SYSTRACE_MAXALIAS)
198 		errx(1, "%s: too many arguments", __func__);
199 
200 	alias->arguments[alias->nargs++] = tl;
201 }
202