scaffold.c revision 1.7 1 1.7 itojun /* $NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun Exp $ */
2 1.2 christos
3 1.1 cjs /*
4 1.1 cjs * Routines for testing only. Not really industrial strength.
5 1.1 cjs *
6 1.1 cjs * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
7 1.1 cjs */
8 1.1 cjs
9 1.2 christos #include <sys/cdefs.h>
10 1.1 cjs #ifndef lint
11 1.2 christos #if 0
12 1.6 itojun static char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24";
13 1.2 christos #else
14 1.7 itojun __RCSID("$NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun Exp $");
15 1.2 christos #endif
16 1.1 cjs #endif
17 1.1 cjs
18 1.1 cjs /* System libraries. */
19 1.1 cjs
20 1.1 cjs #include <sys/types.h>
21 1.1 cjs #include <sys/stat.h>
22 1.1 cjs #include <sys/socket.h>
23 1.1 cjs #include <netinet/in.h>
24 1.1 cjs #include <arpa/inet.h>
25 1.1 cjs #include <netdb.h>
26 1.1 cjs #include <stdio.h>
27 1.1 cjs #include <syslog.h>
28 1.1 cjs #include <setjmp.h>
29 1.1 cjs #include <string.h>
30 1.2 christos #include <stdlib.h>
31 1.1 cjs
32 1.1 cjs #ifndef INADDR_NONE
33 1.1 cjs #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
34 1.1 cjs #endif
35 1.1 cjs
36 1.1 cjs /* Application-specific. */
37 1.1 cjs
38 1.1 cjs #include "tcpd.h"
39 1.1 cjs #include "scaffold.h"
40 1.1 cjs
41 1.2 christos static struct hostent *dup_hostent __P((struct hostent *));
42 1.2 christos
43 1.1 cjs /*
44 1.1 cjs * These are referenced by the options module and by rfc931.c.
45 1.1 cjs */
46 1.1 cjs int allow_severity = SEVERITY;
47 1.1 cjs int deny_severity = LOG_WARNING;
48 1.3 christos extern int rfc931_timeout; /* = RFC931_TIMEOUT; */
49 1.1 cjs
50 1.1 cjs /* dup_hostent - create hostent in one memory block */
51 1.1 cjs
52 1.1 cjs static struct hostent *dup_hostent(hp)
53 1.1 cjs struct hostent *hp;
54 1.1 cjs {
55 1.1 cjs struct hostent_block {
56 1.1 cjs struct hostent host;
57 1.1 cjs char *addr_list[1];
58 1.1 cjs };
59 1.1 cjs struct hostent_block *hb;
60 1.1 cjs int count;
61 1.1 cjs char *data;
62 1.1 cjs char *addr;
63 1.1 cjs
64 1.1 cjs for (count = 0; hp->h_addr_list[count] != 0; count++)
65 1.1 cjs /* void */ ;
66 1.1 cjs
67 1.1 cjs if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
68 1.1 cjs + (hp->h_length + sizeof(char *)) * count)) == 0) {
69 1.1 cjs fprintf(stderr, "Sorry, out of memory\n");
70 1.1 cjs exit(1);
71 1.1 cjs }
72 1.1 cjs memset((char *) &hb->host, 0, sizeof(hb->host));
73 1.7 itojun hb->host.h_addrtype = hp->h_addrtype;
74 1.1 cjs hb->host.h_length = hp->h_length;
75 1.1 cjs hb->host.h_addr_list = hb->addr_list;
76 1.1 cjs hb->host.h_addr_list[count] = 0;
77 1.1 cjs data = (char *) (hb->host.h_addr_list + count + 1);
78 1.1 cjs
79 1.1 cjs for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
80 1.1 cjs hb->host.h_addr_list[count] = data + hp->h_length * count;
81 1.1 cjs memcpy(hb->host.h_addr_list[count], addr, hp->h_length);
82 1.1 cjs }
83 1.1 cjs return (&hb->host);
84 1.1 cjs }
85 1.1 cjs
86 1.1 cjs /* find_inet_addr - find all addresses for this host, result to free() */
87 1.1 cjs
88 1.1 cjs struct hostent *find_inet_addr(host)
89 1.1 cjs char *host;
90 1.1 cjs {
91 1.1 cjs struct in_addr addr;
92 1.5 thorpej unsigned long addr_num;
93 1.1 cjs struct hostent *hp;
94 1.1 cjs static struct hostent h;
95 1.1 cjs static char *addr_list[2];
96 1.7 itojun #ifdef INET6
97 1.7 itojun static struct in6_addr in6;
98 1.7 itojun #endif
99 1.1 cjs
100 1.1 cjs /*
101 1.1 cjs * Host address: translate it to internal form.
102 1.1 cjs */
103 1.5 thorpej if (dot_quad_addr(host, &addr_num) == 0) {
104 1.5 thorpej addr.s_addr = (addr_num & 0xffffffff);
105 1.1 cjs h.h_addr_list = addr_list;
106 1.1 cjs h.h_addr_list[0] = (char *) &addr;
107 1.1 cjs h.h_length = sizeof(addr);
108 1.7 itojun h.h_addrtype = AF_INET;
109 1.1 cjs return (dup_hostent(&h));
110 1.1 cjs }
111 1.7 itojun #ifdef INET6
112 1.7 itojun if (inet_pton(AF_INET6, host, &in6) == 1) {
113 1.7 itojun h.h_addr_list = addr_list;
114 1.7 itojun h.h_addr_list[0] = (char *) &in6;
115 1.7 itojun h.h_length = sizeof(in6);
116 1.7 itojun h.h_addrtype = AF_INET6;
117 1.7 itojun return (dup_hostent(&h));
118 1.7 itojun }
119 1.7 itojun #endif
120 1.1 cjs
121 1.1 cjs /*
122 1.1 cjs * Map host name to a series of addresses. Watch out for non-internet
123 1.1 cjs * forms or aliases. The NOT_INADDR() is here in case gethostbyname() has
124 1.1 cjs * been "enhanced" to accept numeric addresses. Make a copy of the
125 1.1 cjs * address list so that later gethostbyXXX() calls will not clobber it.
126 1.1 cjs */
127 1.7 itojun #ifdef INET6
128 1.7 itojun if (NOT_INADDR(host) == 0 && inet_pton(AF_INET6, host, &in6) == 1)
129 1.7 itojun #else
130 1.7 itojun if (NOT_INADDR(host) == 0)
131 1.7 itojun #endif
132 1.7 itojun {
133 1.1 cjs tcpd_warn("%s: not an internet address", host);
134 1.1 cjs return (0);
135 1.1 cjs }
136 1.7 itojun #ifdef INET6
137 1.7 itojun /*
138 1.7 itojun * XXX this behavior may, or may not be desirable.
139 1.7 itojun * - we may better use getipnodebyname() to addresses of get both AFs,
140 1.7 itojun * however, getipnodebyname() is not widely implemented.
141 1.7 itojun * - it may be better to have a way to specify the AF to use.
142 1.7 itojun */
143 1.7 itojun if ((hp = gethostbyname2(host, AF_INET)) == 0
144 1.7 itojun && (hp = gethostbyname2(host, AF_INET6)) == 0) {
145 1.7 itojun tcpd_warn("%s: host not found", host);
146 1.7 itojun return (0);
147 1.7 itojun }
148 1.7 itojun #else
149 1.1 cjs if ((hp = gethostbyname(host)) == 0) {
150 1.1 cjs tcpd_warn("%s: host not found", host);
151 1.1 cjs return (0);
152 1.1 cjs }
153 1.1 cjs if (hp->h_addrtype != AF_INET) {
154 1.1 cjs tcpd_warn("%d: not an internet host", hp->h_addrtype);
155 1.1 cjs return (0);
156 1.1 cjs }
157 1.7 itojun #endif
158 1.1 cjs if (STR_NE(host, hp->h_name)) {
159 1.1 cjs tcpd_warn("%s: hostname alias", host);
160 1.6 itojun tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name);
161 1.1 cjs }
162 1.1 cjs return (dup_hostent(hp));
163 1.1 cjs }
164 1.1 cjs
165 1.1 cjs /* check_dns - give each address thorough workout, return address count */
166 1.1 cjs
167 1.1 cjs int check_dns(host)
168 1.1 cjs char *host;
169 1.1 cjs {
170 1.1 cjs struct request_info request;
171 1.7 itojun struct sockaddr_storage sin;
172 1.1 cjs struct hostent *hp;
173 1.1 cjs int count;
174 1.1 cjs char *addr;
175 1.7 itojun char *ap;
176 1.7 itojun int alen;
177 1.1 cjs
178 1.1 cjs if ((hp = find_inet_addr(host)) == 0)
179 1.1 cjs return (0);
180 1.1 cjs request_init(&request, RQ_CLIENT_SIN, &sin, 0);
181 1.1 cjs sock_methods(&request);
182 1.1 cjs memset((char *) &sin, 0, sizeof(sin));
183 1.7 itojun sin.ss_family = hp->h_addrtype;
184 1.7 itojun switch (hp->h_addrtype) {
185 1.7 itojun case AF_INET:
186 1.7 itojun ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
187 1.7 itojun alen = sizeof(struct in6_addr);
188 1.7 itojun break;
189 1.7 itojun #ifdef INET6
190 1.7 itojun case AF_INET6:
191 1.7 itojun ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
192 1.7 itojun alen = sizeof(struct in6_addr);
193 1.7 itojun break;
194 1.7 itojun #endif
195 1.7 itojun default:
196 1.7 itojun return (0);
197 1.7 itojun }
198 1.1 cjs
199 1.1 cjs for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
200 1.7 itojun memcpy(ap, addr, alen);
201 1.1 cjs
202 1.1 cjs /*
203 1.1 cjs * Force host name and address conversions. Use the request structure
204 1.1 cjs * as a cache. Detect hostname lookup problems. Any name/name or
205 1.1 cjs * name/address conflicts will be reported while eval_hostname() does
206 1.1 cjs * its job.
207 1.1 cjs */
208 1.1 cjs request_set(&request, RQ_CLIENT_ADDR, "", RQ_CLIENT_NAME, "", 0);
209 1.1 cjs if (STR_EQ(eval_hostname(request.client), unknown))
210 1.1 cjs tcpd_warn("host address %s->name lookup failed",
211 1.1 cjs eval_hostaddr(request.client));
212 1.1 cjs }
213 1.1 cjs free((char *) hp);
214 1.1 cjs return (count);
215 1.1 cjs }
216 1.1 cjs
217 1.1 cjs /* dummy function to intercept the real shell_cmd() */
218 1.1 cjs
219 1.1 cjs /* ARGSUSED */
220 1.1 cjs
221 1.1 cjs void shell_cmd(command)
222 1.1 cjs char *command;
223 1.1 cjs {
224 1.1 cjs if (hosts_access_verbose)
225 1.1 cjs printf("command: %s", command);
226 1.1 cjs }
227 1.1 cjs
228 1.1 cjs /* dummy function to intercept the real clean_exit() */
229 1.1 cjs
230 1.1 cjs /* ARGSUSED */
231 1.1 cjs
232 1.1 cjs void clean_exit(request)
233 1.1 cjs struct request_info *request;
234 1.1 cjs {
235 1.1 cjs exit(0);
236 1.1 cjs }
237 1.1 cjs
238 1.2 christos #if 0
239 1.1 cjs /* dummy function to intercept the real rfc931() */
240 1.1 cjs
241 1.1 cjs /* ARGSUSED */
242 1.1 cjs
243 1.1 cjs void rfc931(request)
244 1.1 cjs struct request_info *request;
245 1.1 cjs {
246 1.1 cjs strcpy(request->user, unknown);
247 1.1 cjs }
248 1.2 christos #endif
249 1.1 cjs
250 1.1 cjs /* check_path - examine accessibility */
251 1.1 cjs
252 1.1 cjs int check_path(path, st)
253 1.1 cjs char *path;
254 1.1 cjs struct stat *st;
255 1.1 cjs {
256 1.1 cjs struct stat stbuf;
257 1.1 cjs char buf[BUFSIZ];
258 1.1 cjs
259 1.1 cjs if (stat(path, st) < 0)
260 1.1 cjs return (-1);
261 1.1 cjs #ifdef notdef
262 1.1 cjs if (st->st_uid != 0)
263 1.1 cjs tcpd_warn("%s: not owned by root", path);
264 1.1 cjs if (st->st_mode & 020)
265 1.1 cjs tcpd_warn("%s: group writable", path);
266 1.1 cjs #endif
267 1.1 cjs if (st->st_mode & 002)
268 1.1 cjs tcpd_warn("%s: world writable", path);
269 1.1 cjs if (path[0] == '/' && path[1] != 0) {
270 1.1 cjs strrchr(strcpy(buf, path), '/')[0] = 0;
271 1.1 cjs (void) check_path(buf[0] ? buf : "/", &stbuf);
272 1.1 cjs }
273 1.1 cjs return (0);
274 1.1 cjs }
275