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