scaffold.c revision 272461
1139749Simp /* 240024Sgibbs * Routines for testing only. Not really industrial strength. 340024Sgibbs * 440024Sgibbs * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 540024Sgibbs * 640024Sgibbs * $FreeBSD: releng/10.1/contrib/tcp_wrappers/scaffold.c 63158 2000-07-14 17:15:34Z ume $ 756979Sgibbs */ 840024Sgibbs 956979Sgibbs#ifndef lint 1040024Sgibbsstatic char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24"; 1140024Sgibbs#endif 1240024Sgibbs 1340024Sgibbs/* System libraries. */ 1440024Sgibbs 1540024Sgibbs#include <sys/types.h> 1640024Sgibbs#include <sys/stat.h> 1756979Sgibbs#include <sys/socket.h> 1840024Sgibbs#include <netinet/in.h> 1940024Sgibbs#include <arpa/inet.h> 2040024Sgibbs#include <netdb.h> 2140024Sgibbs#include <stdio.h> 2240024Sgibbs#include <syslog.h> 2340024Sgibbs#include <setjmp.h> 2440024Sgibbs#include <string.h> 2540024Sgibbs 2640024Sgibbs#ifndef INADDR_NONE 2740024Sgibbs#define INADDR_NONE (-1) /* XXX should be 0xffffffff */ 2840024Sgibbs#endif 2940024Sgibbs 3040024Sgibbs#ifndef INET6 3140024Sgibbsextern char *malloc(); 3240024Sgibbs#endif 3340024Sgibbs 3440024Sgibbs/* Application-specific. */ 3540024Sgibbs 3640024Sgibbs#include "tcpd.h" 3740024Sgibbs#include "scaffold.h" 3840024Sgibbs 3940024Sgibbs /* 4040024Sgibbs * These are referenced by the options module and by rfc931.c. 4140024Sgibbs */ 4240024Sgibbsint allow_severity = SEVERITY; 4340024Sgibbsint deny_severity = LOG_WARNING; 4440024Sgibbsint rfc931_timeout = RFC931_TIMEOUT; 4540024Sgibbs 46119418Sobrien#ifndef INET6 47119418Sobrien/* dup_hostent - create hostent in one memory block */ 48119418Sobrien 4940024Sgibbsstatic struct hostent *dup_hostent(hp) 5040024Sgibbsstruct hostent *hp; 5140024Sgibbs{ 5240024Sgibbs struct hostent_block { 53117126Sscottl struct hostent host; 54117126Sscottl char *addr_list[1]; 5556979Sgibbs }; 5640024Sgibbs struct hostent_block *hb; 5740024Sgibbs int count; 5856979Sgibbs char *data; 5940024Sgibbs char *addr; 6056979Sgibbs 6156979Sgibbs for (count = 0; hp->h_addr_list[count] != 0; count++) 6240024Sgibbs /* void */ ; 6340024Sgibbs 6440024Sgibbs if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block) 6540024Sgibbs + (hp->h_length + sizeof(char *)) * count)) == 0) { 6640024Sgibbs fprintf(stderr, "Sorry, out of memory\n"); 6740024Sgibbs exit(1); 6840024Sgibbs } 6940024Sgibbs memset((char *) &hb->host, 0, sizeof(hb->host)); 7040024Sgibbs hb->host.h_length = hp->h_length; 7140024Sgibbs hb->host.h_addr_list = hb->addr_list; 7240024Sgibbs hb->host.h_addr_list[count] = 0; 7340024Sgibbs data = (char *) (hb->host.h_addr_list + count + 1); 7440024Sgibbs 7540024Sgibbs for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { 7640024Sgibbs hb->host.h_addr_list[count] = data + hp->h_length * count; 7740024Sgibbs memcpy(hb->host.h_addr_list[count], addr, hp->h_length); 7857679Sgibbs } 7940024Sgibbs return (&hb->host); 8040024Sgibbs} 8140024Sgibbs#endif 8240024Sgibbs 8340024Sgibbs/* find_inet_addr - find all addresses for this host, result to free() */ 8440024Sgibbs 8540024Sgibbs#ifdef INET6 8640024Sgibbsstruct addrinfo *find_inet_addr(host) 8740024Sgibbschar *host; 8840024Sgibbs{ 8940024Sgibbs struct addrinfo hints, *res; 9040024Sgibbs 9140024Sgibbs memset(&hints, 0, sizeof(hints)); 9240024Sgibbs hints.ai_family = PF_UNSPEC; 9340024Sgibbs hints.ai_socktype = SOCK_STREAM; 9440024Sgibbs hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 9540024Sgibbs if (getaddrinfo(host, NULL, &hints, &res) == 0) 9640024Sgibbs return (res); 9740024Sgibbs 9840024Sgibbs memset(&hints, 0, sizeof(hints)); 9940024Sgibbs hints.ai_family = PF_UNSPEC; 10040024Sgibbs hints.ai_socktype = SOCK_STREAM; 10140024Sgibbs hints.ai_flags = AI_PASSIVE | AI_CANONNAME; 10257679Sgibbs if (getaddrinfo(host, NULL, &hints, &res) != 0) { 10357679Sgibbs tcpd_warn("%s: host not found", host); 10457679Sgibbs return (0); 10557679Sgibbs } 10657679Sgibbs if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) { 10757679Sgibbs tcpd_warn("%d: not an internet host", res->ai_family); 10840024Sgibbs freeaddrinfo(res); 10940024Sgibbs return (0); 11040024Sgibbs } 11140024Sgibbs if (!res->ai_canonname) { 11240024Sgibbs tcpd_warn("%s: hostname alias", host); 11340024Sgibbs tcpd_warn("(cannot obtain official name)", res->ai_canonname); 11440024Sgibbs } else if (STR_NE(host, res->ai_canonname)) { 11540024Sgibbs tcpd_warn("%s: hostname alias", host); 11640024Sgibbs tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname); 11740024Sgibbs } 11840024Sgibbs return (res); 11940024Sgibbs} 12040024Sgibbs#else 12140024Sgibbsstruct hostent *find_inet_addr(host) 12240024Sgibbschar *host; 12340024Sgibbs{ 12440024Sgibbs struct in_addr addr; 12540024Sgibbs struct hostent *hp; 12640024Sgibbs static struct hostent h; 12740024Sgibbs static char *addr_list[2]; 12840024Sgibbs 12940024Sgibbs /* 13040024Sgibbs * Host address: translate it to internal form. 13140024Sgibbs */ 13240024Sgibbs if ((addr.s_addr = dot_quad_addr(host)) != INADDR_NONE) { 13340024Sgibbs h.h_addr_list = addr_list; 13440024Sgibbs h.h_addr_list[0] = (char *) &addr; 13540024Sgibbs h.h_length = sizeof(addr); 13640024Sgibbs return (dup_hostent(&h)); 13740024Sgibbs } 13840024Sgibbs 13940024Sgibbs /* 14040024Sgibbs * Map host name to a series of addresses. Watch out for non-internet 14140024Sgibbs * forms or aliases. The NOT_INADDR() is here in case gethostbyname() has 14240024Sgibbs * been "enhanced" to accept numeric addresses. Make a copy of the 14340024Sgibbs * address list so that later gethostbyXXX() calls will not clobber it. 14440024Sgibbs */ 14540024Sgibbs if (NOT_INADDR(host) == 0) { 14640024Sgibbs tcpd_warn("%s: not an internet address", host); 14740024Sgibbs return (0); 14840024Sgibbs } 14940024Sgibbs if ((hp = gethostbyname(host)) == 0) { 15040024Sgibbs tcpd_warn("%s: host not found", host); 15140024Sgibbs return (0); 15240024Sgibbs } 15340024Sgibbs if (hp->h_addrtype != AF_INET) { 15440024Sgibbs tcpd_warn("%d: not an internet host", hp->h_addrtype); 15540024Sgibbs return (0); 15640024Sgibbs } 15740024Sgibbs if (STR_NE(host, hp->h_name)) { 15840024Sgibbs tcpd_warn("%s: hostname alias", host); 15940024Sgibbs tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name); 16040024Sgibbs } 16140024Sgibbs return (dup_hostent(hp)); 16240024Sgibbs} 16340024Sgibbs#endif 16440024Sgibbs 16540024Sgibbs/* check_dns - give each address thorough workout, return address count */ 16640024Sgibbs 16740024Sgibbsint check_dns(host) 16840024Sgibbschar *host; 16940024Sgibbs{ 17040024Sgibbs struct request_info request; 17140024Sgibbs#ifdef INET6 17240024Sgibbs struct sockaddr_storage sin; 17340024Sgibbs struct addrinfo *hp, *res; 17440024Sgibbs#else 17540024Sgibbs struct sockaddr_in sin; 17640024Sgibbs struct hostent *hp; 17740024Sgibbs#endif 17840024Sgibbs int count; 17940024Sgibbs char *addr; 18040024Sgibbs 18140024Sgibbs if ((hp = find_inet_addr(host)) == 0) 18240024Sgibbs return (0); 18340024Sgibbs request_init(&request, RQ_CLIENT_SIN, &sin, 0); 18440024Sgibbs sock_methods(&request); 18540024Sgibbs#ifndef INET6 18640024Sgibbs memset((char *) &sin, 0, sizeof(sin)); 18740024Sgibbs sin.sin_family = AF_INET; 18840024Sgibbs#endif 18940024Sgibbs 19040024Sgibbs#ifdef INET6 19140024Sgibbs for (res = hp, count = 0; res; res = res->ai_next, count++) { 19240024Sgibbs memcpy(&sin, res->ai_addr, res->ai_addrlen); 19340024Sgibbs#else 19440024Sgibbs for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { 19540024Sgibbs memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr)); 19640024Sgibbs#endif 19740024Sgibbs 19840024Sgibbs /* 19940024Sgibbs * Force host name and address conversions. Use the request structure 20040024Sgibbs * as a cache. Detect hostname lookup problems. Any name/name or 20140024Sgibbs * name/address conflicts will be reported while eval_hostname() does 20240024Sgibbs * its job. 20340024Sgibbs */ 20440024Sgibbs request_set(&request, RQ_CLIENT_ADDR, "", RQ_CLIENT_NAME, "", 0); 20540024Sgibbs if (STR_EQ(eval_hostname(request.client), unknown)) 20640024Sgibbs tcpd_warn("host address %s->name lookup failed", 20740024Sgibbs eval_hostaddr(request.client)); 20840024Sgibbs } 20940024Sgibbs#ifdef INET6 21040024Sgibbs freeaddrinfo(hp); 21140024Sgibbs#else 21240024Sgibbs free((char *) hp); 21340024Sgibbs#endif 21440024Sgibbs return (count); 21540024Sgibbs} 21640024Sgibbs 21756979Sgibbs/* dummy function to intercept the real shell_cmd() */ 21856979Sgibbs 21956979Sgibbs/* ARGSUSED */ 22056979Sgibbs 22140024Sgibbsvoid shell_cmd(command) 22240024Sgibbschar *command; 22340024Sgibbs{ 22440024Sgibbs if (hosts_access_verbose) 22540024Sgibbs printf("command: %s", command); 22640024Sgibbs} 22740024Sgibbs 22840024Sgibbs/* dummy function to intercept the real clean_exit() */ 22940024Sgibbs 23040024Sgibbs/* ARGSUSED */ 23140024Sgibbs 23240024Sgibbsvoid clean_exit(request) 23340024Sgibbsstruct request_info *request; 23440024Sgibbs{ 23540024Sgibbs exit(0); 23640024Sgibbs} 23740024Sgibbs 23840024Sgibbs/* dummy function to intercept the real rfc931() */ 23940420Sgibbs 24040024Sgibbs/* ARGSUSED */ 24140024Sgibbs 24240024Sgibbsvoid rfc931(request) 24340024Sgibbsstruct request_info *request; 24440024Sgibbs{ 24540024Sgibbs strcpy(request->user, unknown); 24640024Sgibbs} 24740024Sgibbs 24840024Sgibbs/* check_path - examine accessibility */ 24940024Sgibbs 25040024Sgibbsint check_path(path, st) 25140024Sgibbschar *path; 25240024Sgibbsstruct stat *st; 25340024Sgibbs{ 25440024Sgibbs struct stat stbuf; 25540024Sgibbs char buf[BUFSIZ]; 25640024Sgibbs 25740024Sgibbs if (stat(path, st) < 0) 25840024Sgibbs return (-1); 259115343Sscottl#ifdef notdef 26040024Sgibbs if (st->st_uid != 0) 26140024Sgibbs tcpd_warn("%s: not owned by root", path); 26240024Sgibbs if (st->st_mode & 020) 26340024Sgibbs tcpd_warn("%s: group writable", path); 26440024Sgibbs#endif 26540024Sgibbs if (st->st_mode & 002) 26640024Sgibbs tcpd_warn("%s: world writable", path); 26740024Sgibbs if (path[0] == '/' && path[1] != 0) { 26840024Sgibbs strrchr(strcpy(buf, path), '/')[0] = 0; 26940024Sgibbs (void) check_path(buf[0] ? buf : "/", &stbuf); 27040024Sgibbs } 27140024Sgibbs return (0); 27240024Sgibbs} 27340024Sgibbs