scaffold.c revision 63158
11541Srgrimes /* 21541Srgrimes * Routines for testing only. Not really industrial strength. 31541Srgrimes * 41541Srgrimes * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 51541Srgrimes * 61541Srgrimes * $FreeBSD: head/contrib/tcp_wrappers/scaffold.c 63158 2000-07-14 17:15:34Z ume $ 71541Srgrimes */ 81541Srgrimes 91541Srgrimes#ifndef lint 101541Srgrimesstatic char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24"; 111541Srgrimes#endif 121541Srgrimes 131541Srgrimes/* System libraries. */ 141541Srgrimes 151541Srgrimes#include <sys/types.h> 161541Srgrimes#include <sys/stat.h> 171541Srgrimes#include <sys/socket.h> 181541Srgrimes#include <netinet/in.h> 191541Srgrimes#include <arpa/inet.h> 201541Srgrimes#include <netdb.h> 211541Srgrimes#include <stdio.h> 221541Srgrimes#include <syslog.h> 231541Srgrimes#include <setjmp.h> 241541Srgrimes#include <string.h> 251541Srgrimes 261541Srgrimes#ifndef INADDR_NONE 271541Srgrimes#define INADDR_NONE (-1) /* XXX should be 0xffffffff */ 281541Srgrimes#endif 291541Srgrimes 301541Srgrimes#ifndef INET6 311541Srgrimesextern char *malloc(); 321541Srgrimes#endif 331541Srgrimes 341541Srgrimes/* Application-specific. */ 351541Srgrimes 361541Srgrimes#include "tcpd.h" 3728270Swollman#include "scaffold.h" 381541Srgrimes 391541Srgrimes /* 401541Srgrimes * These are referenced by the options module and by rfc931.c. 411541Srgrimes */ 421541Srgrimesint allow_severity = SEVERITY; 431541Srgrimesint deny_severity = LOG_WARNING; 441541Srgrimesint rfc931_timeout = RFC931_TIMEOUT; 451541Srgrimes 461541Srgrimes#ifndef INET6 471541Srgrimes/* dup_hostent - create hostent in one memory block */ 481541Srgrimes 491541Srgrimesstatic struct hostent *dup_hostent(hp) 501541Srgrimesstruct hostent *hp; 511541Srgrimes{ 521541Srgrimes struct hostent_block { 531541Srgrimes struct hostent host; 541541Srgrimes char *addr_list[1]; 559336Sdfr }; 5627446Sdfr struct hostent_block *hb; 572997Swollman int count; 582997Swollman char *data; 592997Swollman char *addr; 602997Swollman 611541Srgrimes for (count = 0; hp->h_addr_list[count] != 0; count++) 623305Sphk /* void */ ; 6312662Sdg 6412662Sdg if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block) 6512662Sdg + (hp->h_length + sizeof(char *)) * count)) == 0) { 669507Sdg fprintf(stderr, "Sorry, out of memory\n"); 673305Sphk exit(1); 681541Srgrimes } 699336Sdfr memset((char *) &hb->host, 0, sizeof(hb->host)); 701541Srgrimes hb->host.h_length = hp->h_length; 711541Srgrimes hb->host.h_addr_list = hb->addr_list; 721541Srgrimes hb->host.h_addr_list[count] = 0; 731541Srgrimes data = (char *) (hb->host.h_addr_list + count + 1); 741541Srgrimes 751541Srgrimes for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { 761541Srgrimes hb->host.h_addr_list[count] = data + hp->h_length * count; 771541Srgrimes memcpy(hb->host.h_addr_list[count], addr, hp->h_length); 781541Srgrimes } 791541Srgrimes return (&hb->host); 801541Srgrimes} 811541Srgrimes#endif 821541Srgrimes 831541Srgrimes/* find_inet_addr - find all addresses for this host, result to free() */ 841541Srgrimes 851541Srgrimes#ifdef INET6 861541Srgrimesstruct addrinfo *find_inet_addr(host) 871541Srgrimeschar *host; 881541Srgrimes{ 891541Srgrimes struct addrinfo hints, *res; 901541Srgrimes 919336Sdfr memset(&hints, 0, sizeof(hints)); 921541Srgrimes hints.ai_family = PF_UNSPEC; 939336Sdfr hints.ai_socktype = SOCK_STREAM; 941541Srgrimes hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 951541Srgrimes if (getaddrinfo(host, NULL, &hints, &res) == 0) 961541Srgrimes return (res); 9712911Sphk 9812911Sphk memset(&hints, 0, sizeof(hints)); 9912911Sphk hints.ai_family = PF_UNSPEC; 10012911Sphk hints.ai_socktype = SOCK_STREAM; 10112911Sphk hints.ai_flags = AI_PASSIVE | AI_CANONNAME; 10212911Sphk if (getaddrinfo(host, NULL, &hints, &res) != 0) { 10312911Sphk tcpd_warn("%s: host not found", host); 10422521Sdyson return (0); 1059336Sdfr } 1069336Sdfr if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) { 1079759Sbde tcpd_warn("%d: not an internet host", res->ai_family); 1089759Sbde freeaddrinfo(res); 1099759Sbde return (0); 1109759Sbde } 1119759Sbde if (!res->ai_canonname) { 1129759Sbde tcpd_warn("%s: hostname alias", host); 1139759Sbde tcpd_warn("(cannot obtain official name)", res->ai_canonname); 1149759Sbde } else if (STR_NE(host, res->ai_canonname)) { 1159759Sbde tcpd_warn("%s: hostname alias", host); 1169759Sbde tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname); 11713416Sphk } 1189336Sdfr return (res); 1199336Sdfr} 1209336Sdfr#else 1219336Sdfrstruct hostent *find_inet_addr(host) 1229336Sdfrchar *host; 1239336Sdfr{ 1249336Sdfr struct in_addr addr; 1259336Sdfr struct hostent *hp; 1269336Sdfr static struct hostent h; 1279336Sdfr static char *addr_list[2]; 1289336Sdfr 1299336Sdfr /* 1309336Sdfr * Host address: translate it to internal form. 1319336Sdfr */ 1329336Sdfr if ((addr.s_addr = dot_quad_addr(host)) != INADDR_NONE) { 1339336Sdfr h.h_addr_list = addr_list; 1349336Sdfr h.h_addr_list[0] = (char *) &addr; 1359336Sdfr h.h_length = sizeof(addr); 1369336Sdfr return (dup_hostent(&h)); 1379336Sdfr } 1389336Sdfr 1399336Sdfr /* 1409336Sdfr * Map host name to a series of addresses. Watch out for non-internet 1419336Sdfr * forms or aliases. The NOT_INADDR() is here in case gethostbyname() has 1429336Sdfr * been "enhanced" to accept numeric addresses. Make a copy of the 1439336Sdfr * address list so that later gethostbyXXX() calls will not clobber it. 1449336Sdfr */ 1459336Sdfr if (NOT_INADDR(host) == 0) { 1469336Sdfr tcpd_warn("%s: not an internet address", host); 1479336Sdfr return (0); 1489336Sdfr } 1499336Sdfr if ((hp = gethostbyname(host)) == 0) { 15013416Sphk tcpd_warn("%s: host not found", host); 1519336Sdfr return (0); 1529336Sdfr } 1539336Sdfr if (hp->h_addrtype != AF_INET) { 1549336Sdfr tcpd_warn("%d: not an internet host", hp->h_addrtype); 1559336Sdfr return (0); 1569336Sdfr } 1579336Sdfr if (STR_NE(host, hp->h_name)) { 1589336Sdfr tcpd_warn("%s: hostname alias", host); 1599336Sdfr tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name); 1609336Sdfr } 1619336Sdfr return (dup_hostent(hp)); 1629336Sdfr} 1639336Sdfr#endif 1649336Sdfr 1659336Sdfr/* check_dns - give each address thorough workout, return address count */ 1669336Sdfr 1679336Sdfrint check_dns(host) 1689336Sdfrchar *host; 1699336Sdfr{ 1709336Sdfr struct request_info request; 1719336Sdfr#ifdef INET6 1729336Sdfr struct sockaddr_storage sin; 1739336Sdfr struct addrinfo *hp, *res; 1749336Sdfr#else 1759336Sdfr struct sockaddr_in sin; 1769336Sdfr struct hostent *hp; 1779336Sdfr#endif 1789336Sdfr int count; 1799336Sdfr char *addr; 1809336Sdfr 1819336Sdfr if ((hp = find_inet_addr(host)) == 0) 1829336Sdfr return (0); 18313416Sphk request_init(&request, RQ_CLIENT_SIN, &sin, 0); 1849336Sdfr sock_methods(&request); 1859336Sdfr#ifndef INET6 1869336Sdfr memset((char *) &sin, 0, sizeof(sin)); 1879336Sdfr sin.sin_family = AF_INET; 1889336Sdfr#endif 1899336Sdfr 1909336Sdfr#ifdef INET6 1919336Sdfr for (res = hp, count = 0; res; res = res->ai_next, count++) { 1929336Sdfr memcpy(&sin, res->ai_addr, res->ai_addrlen); 1939336Sdfr#else 1949336Sdfr for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { 1959336Sdfr memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr)); 1969336Sdfr#endif 1979336Sdfr 1989336Sdfr /* 1999336Sdfr * Force host name and address conversions. Use the request structure 2009336Sdfr * as a cache. Detect hostname lookup problems. Any name/name or 2019336Sdfr * name/address conflicts will be reported while eval_hostname() does 2029336Sdfr * its job. 2039336Sdfr */ 2049336Sdfr request_set(&request, RQ_CLIENT_ADDR, "", RQ_CLIENT_NAME, "", 0); 2059336Sdfr if (STR_EQ(eval_hostname(request.client), unknown)) 2069336Sdfr tcpd_warn("host address %s->name lookup failed", 2079336Sdfr eval_hostaddr(request.client)); 2089336Sdfr } 2099336Sdfr#ifdef INET6 2109336Sdfr freeaddrinfo(hp); 2119336Sdfr#else 2129336Sdfr free((char *) hp); 2139336Sdfr#endif 2149336Sdfr return (count); 2159336Sdfr} 2169336Sdfr 2179336Sdfr/* dummy function to intercept the real shell_cmd() */ 2189336Sdfr 2199336Sdfr/* ARGSUSED */ 2209336Sdfr 2219336Sdfrvoid shell_cmd(command) 2229336Sdfrchar *command; 2239336Sdfr{ 2249336Sdfr if (hosts_access_verbose) 2259336Sdfr printf("command: %s", command); 2269336Sdfr} 2279336Sdfr 2289336Sdfr/* dummy function to intercept the real clean_exit() */ 2299336Sdfr 2309336Sdfr/* ARGSUSED */ 2319336Sdfr 2329336Sdfrvoid clean_exit(request) 2339336Sdfrstruct request_info *request; 2349336Sdfr{ 2359336Sdfr exit(0); 2369336Sdfr} 2379336Sdfr 2389336Sdfr/* dummy function to intercept the real rfc931() */ 2399336Sdfr 2409336Sdfr/* ARGSUSED */ 2419336Sdfr 2429336Sdfrvoid rfc931(request) 2439336Sdfrstruct request_info *request; 2449336Sdfr{ 2459336Sdfr strcpy(request->user, unknown); 2469336Sdfr} 2479336Sdfr 2489336Sdfr/* check_path - examine accessibility */ 2499336Sdfr 2509336Sdfrint check_path(path, st) 2519336Sdfrchar *path; 2529336Sdfrstruct stat *st; 2539336Sdfr{ 2549336Sdfr struct stat stbuf; 2559336Sdfr char buf[BUFSIZ]; 2569336Sdfr 2579336Sdfr if (stat(path, st) < 0) 2589336Sdfr return (-1); 2599336Sdfr#ifdef notdef 2609336Sdfr if (st->st_uid != 0) 2619336Sdfr tcpd_warn("%s: not owned by root", path); 2629336Sdfr if (st->st_mode & 020) 2639336Sdfr tcpd_warn("%s: group writable", path); 2649336Sdfr#endif 2659336Sdfr if (st->st_mode & 002) 2669336Sdfr tcpd_warn("%s: world writable", path); 2679336Sdfr if (path[0] == '/' && path[1] != 0) { 2689336Sdfr strrchr(strcpy(buf, path), '/')[0] = 0; 2699336Sdfr (void) check_path(buf[0] ? buf : "/", &stbuf); 2709336Sdfr } 2719336Sdfr return (0); 2729336Sdfr} 2739336Sdfr