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