Home | History | Annotate | Line # | Download | only in tcpdchk
scaffold.c revision 1.7
      1 /*	$NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun 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.6 97/03/21 19:27:24";
     13 #else
     14 __RCSID("$NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun 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_addrtype = hp->h_addrtype;
     74     hb->host.h_length = hp->h_length;
     75     hb->host.h_addr_list = hb->addr_list;
     76     hb->host.h_addr_list[count] = 0;
     77     data = (char *) (hb->host.h_addr_list + count + 1);
     78 
     79     for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
     80 	hb->host.h_addr_list[count] = data + hp->h_length * count;
     81 	memcpy(hb->host.h_addr_list[count], addr, hp->h_length);
     82     }
     83     return (&hb->host);
     84 }
     85 
     86 /* find_inet_addr - find all addresses for this host, result to free() */
     87 
     88 struct hostent *find_inet_addr(host)
     89 char   *host;
     90 {
     91     struct in_addr addr;
     92     unsigned long addr_num;
     93     struct hostent *hp;
     94     static struct hostent h;
     95     static char *addr_list[2];
     96 #ifdef INET6
     97     static struct in6_addr in6;
     98 #endif
     99 
    100     /*
    101      * Host address: translate it to internal form.
    102      */
    103     if (dot_quad_addr(host, &addr_num) == 0) {
    104 	addr.s_addr = (addr_num & 0xffffffff);
    105 	h.h_addr_list = addr_list;
    106 	h.h_addr_list[0] = (char *) &addr;
    107 	h.h_length = sizeof(addr);
    108 	h.h_addrtype = AF_INET;
    109 	return (dup_hostent(&h));
    110     }
    111 #ifdef INET6
    112     if (inet_pton(AF_INET6, host, &in6) == 1) {
    113 	h.h_addr_list = addr_list;
    114 	h.h_addr_list[0] = (char *) &in6;
    115 	h.h_length = sizeof(in6);
    116 	h.h_addrtype = AF_INET6;
    117 	return (dup_hostent(&h));
    118     }
    119 #endif
    120 
    121     /*
    122      * Map host name to a series of addresses. Watch out for non-internet
    123      * forms or aliases. The NOT_INADDR() is here in case gethostbyname() has
    124      * been "enhanced" to accept numeric addresses. Make a copy of the
    125      * address list so that later gethostbyXXX() calls will not clobber it.
    126      */
    127 #ifdef INET6
    128     if (NOT_INADDR(host) == 0 && inet_pton(AF_INET6, host, &in6) == 1)
    129 #else
    130     if (NOT_INADDR(host) == 0)
    131 #endif
    132     {
    133 	tcpd_warn("%s: not an internet address", host);
    134 	return (0);
    135     }
    136 #ifdef INET6
    137     /*
    138      * XXX this behavior may, or may not be desirable.
    139      * - we may better use getipnodebyname() to addresses of get both AFs,
    140      *   however, getipnodebyname() is not widely implemented.
    141      * - it may be better to have a way to specify the AF to use.
    142      */
    143     if ((hp = gethostbyname2(host, AF_INET)) == 0
    144      && (hp = gethostbyname2(host, AF_INET6)) == 0) {
    145 	tcpd_warn("%s: host not found", host);
    146 	return (0);
    147     }
    148 #else
    149     if ((hp = gethostbyname(host)) == 0) {
    150 	tcpd_warn("%s: host not found", host);
    151 	return (0);
    152     }
    153     if (hp->h_addrtype != AF_INET) {
    154 	tcpd_warn("%d: not an internet host", hp->h_addrtype);
    155 	return (0);
    156     }
    157 #endif
    158     if (STR_NE(host, hp->h_name)) {
    159 	tcpd_warn("%s: hostname alias", host);
    160 	tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name);
    161     }
    162     return (dup_hostent(hp));
    163 }
    164 
    165 /* check_dns - give each address thorough workout, return address count */
    166 
    167 int     check_dns(host)
    168 char   *host;
    169 {
    170     struct request_info request;
    171     struct sockaddr_storage sin;
    172     struct hostent *hp;
    173     int     count;
    174     char   *addr;
    175     char *ap;
    176     int alen;
    177 
    178     if ((hp = find_inet_addr(host)) == 0)
    179 	return (0);
    180     request_init(&request, RQ_CLIENT_SIN, &sin, 0);
    181     sock_methods(&request);
    182     memset((char *) &sin, 0, sizeof(sin));
    183     sin.ss_family = hp->h_addrtype;
    184     switch (hp->h_addrtype) {
    185     case AF_INET:
    186 	ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
    187 	alen = sizeof(struct in6_addr);
    188 	break;
    189 #ifdef INET6
    190     case AF_INET6:
    191 	ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
    192 	alen = sizeof(struct in6_addr);
    193 	break;
    194 #endif
    195     default:
    196 	return (0);
    197     }
    198 
    199     for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
    200 	memcpy(ap, addr, alen);
    201 
    202 	/*
    203 	 * Force host name and address conversions. Use the request structure
    204 	 * as a cache. Detect hostname lookup problems. Any name/name or
    205 	 * name/address conflicts will be reported while eval_hostname() does
    206 	 * its job.
    207 	 */
    208 	request_set(&request, RQ_CLIENT_ADDR, "", RQ_CLIENT_NAME, "", 0);
    209 	if (STR_EQ(eval_hostname(request.client), unknown))
    210 	    tcpd_warn("host address %s->name lookup failed",
    211 		      eval_hostaddr(request.client));
    212     }
    213     free((char *) hp);
    214     return (count);
    215 }
    216 
    217 /* dummy function to intercept the real shell_cmd() */
    218 
    219 /* ARGSUSED */
    220 
    221 void    shell_cmd(command)
    222 char   *command;
    223 {
    224     if (hosts_access_verbose)
    225 	printf("command: %s", command);
    226 }
    227 
    228 /* dummy function  to intercept the real clean_exit() */
    229 
    230 /* ARGSUSED */
    231 
    232 void    clean_exit(request)
    233 struct request_info *request;
    234 {
    235     exit(0);
    236 }
    237 
    238 #if 0
    239 /* dummy function  to intercept the real rfc931() */
    240 
    241 /* ARGSUSED */
    242 
    243 void    rfc931(request)
    244 struct request_info *request;
    245 {
    246     strcpy(request->user, unknown);
    247 }
    248 #endif
    249 
    250 /* check_path - examine accessibility */
    251 
    252 int     check_path(path, st)
    253 char   *path;
    254 struct stat *st;
    255 {
    256     struct stat stbuf;
    257     char    buf[BUFSIZ];
    258 
    259     if (stat(path, st) < 0)
    260 	return (-1);
    261 #ifdef notdef
    262     if (st->st_uid != 0)
    263 	tcpd_warn("%s: not owned by root", path);
    264     if (st->st_mode & 020)
    265 	tcpd_warn("%s: group writable", path);
    266 #endif
    267     if (st->st_mode & 002)
    268 	tcpd_warn("%s: world writable", path);
    269     if (path[0] == '/' && path[1] != 0) {
    270 	strrchr(strcpy(buf, path), '/')[0] = 0;
    271 	(void) check_path(buf[0] ? buf : "/", &stbuf);
    272     }
    273     return (0);
    274 }
    275