# 2.11BSD#431 - /usr/src/libexec/tcpd/tcpdmatch.c

##### Functions

    main              X

##### Macros

    INADDR_NONE       X

       1:  /*
       2:   * tcpdmatch - explain what tcpd would do in a specific case
       3:   *
       4:   * usage: tcpdmatch [-d] [-i inet_conf] daemon[@host] [user@]host
       5:   *
       6:   * -d: use the access control tables in the current directory.
       7:   *
       8:   * -i: location of inetd.conf file.
       9:   *
      10:   * All errors are reported to the standard error stream, including the errors
      11:   * that would normally be reported via the syslog daemon.
      12:   *
      13:   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
      14:   */
      15:
      16: #ifndef lint
      17: static char sccsid[] = "@(#) tcpdmatch.c 1.4 95/01/01 13:34:07";
      18: #endif
      19:
      20: /* System libraries. */
      21:
      22: #include <sys/types.h>
      23: #include <sys/stat.h>
      24: #include <sys/socket.h>
      25: #include <netinet/in.h>
      26: #include <arpa/inet.h>
      27: #include <netdb.h>
      28: #include <stdio.h>
      29: #include <syslog.h>
      30: #include <setjmp.h>
      31: #include <string.h>
      32:
      33: extern void exit();
      34: extern int optind;
      35: extern char *optarg;
      36:
      37: #ifndef INADDR_NONE
      38: #define INADDR_NONE (-1)        /* XXX should be 0xffffffff */
      39: #endif
      40:
      41: /* Application-specific. */
      42:
      43: #include "tcpd.h"
      44: #include "inetcf.h"
      45: #include "scaffold.h"
      46:
      47: static void usage();
      48: static void tcpdmatch();
      49:
      50: /* The main program */
      51:
      52: int     main(argc, argv)
      53: int     argc;
      54: char  **argv;
      55: {
      56:     struct hostent *hp;
      57:     char   *myname = argv[0];
      58:     char   *client;
      59:     char   *server;
      60:     char   *addr;
      61:     char   *user;
      62:     char   *daemon;
      63:     struct request_info request;
      64:     int     ch;
      65:     char   *inetcf = 0;
      66:     int     count;
      67:     struct sockaddr_in server_sin;
      68:     struct sockaddr_in client_sin;
      69:     struct stat st;
      70:
      71:     /*
      72:      * Show what rule actually matched.
      73:      */
      74:     hosts_access_verbose = 2;
      75:
      76:     /*
      77:      * Parse the JCL.
      78:      */
      79:     while ((ch = getopt(argc, argv, "di:")) != EOF) {
      80:     switch (ch) {
      81:     case 'd':
      82:         hosts_allow_table = "hosts.allow";
      83:         hosts_deny_table = "hosts.deny";
      84:         break;
      85:     case 'i':
      86:         inetcf = optarg;
      87:         break;
      88:     default:
      89:         usage(myname);
      90:         /* NOTREACHED */
      91:     }
      92:     }
      93:     if (argc != optind + 2)
      94:     usage(myname);
      95:
      96:     /*
      97:      * Default is to specify a daemon process name. When daemon@host is
      98:      * specified, separate the two parts.
      99:      */
     100:     if ((server = split_at(argv[optind], '@')) == 0)
     101:     server = unknown;
     102:     if (argv[optind][0] == '/') {
     103:     daemon = strrchr(argv[optind], '/') + 1;
     104:     tcpd_warn("%s: daemon name normalized to: %s", argv[optind], daemon);
     105:     } else {
     106:     daemon = argv[optind];
     107:     }
     108:
     109:     /*
     110:      * Default is to specify a client hostname or address. When user@host is
     111:      * specified, separate the two parts.
     112:      */
     113:     if ((client = split_at(argv[optind + 1], '@')) != 0) {
     114:     user = argv[optind + 1];
     115:     } else {
     116:     client = argv[optind + 1];
     117:     user = unknown;
     118:     }
     119:
     120:     /*
     121:      * Analyze the inetd (or tlid) configuration file, so that we can warn
     122:      * the user about services that may not be wrapped, services that are not
     123:      * configured, or services that are wrapped in an incorrect manner. Allow
     124:      * for services that are not run from inetd, or that have tcpd access
     125:      * control built into them.
     126:      */
     127:     inetcf = inet_cfg(inetcf);
     128:     inet_set("portmap", WR_NOT);
     129:     inet_set("rpcbind", WR_NOT);
     130:     switch (inet_get(daemon)) {
     131:     case WR_UNKNOWN:
     132:     tcpd_warn("%s: no such process name in %s", daemon, inetcf);
     133:     break;
     134:     case WR_NOT:
     135:     tcpd_warn("%s: service possibly not wrapped", daemon);
     136:     break;
     137:     }
     138:
     139:     /*
     140:      * Check accessibility of access control files.
     141:      */
     142:     (void) check_path(hosts_allow_table, &st);
     143:     (void) check_path(hosts_deny_table, &st);
     144:
     145:     /*
     146:      * Fill in what we have figured out sofar. Use socket and DNS routines
     147:      * for address and name conversions. We attach stdout to the request so
     148:      * that banner messages will become visible.
     149:      */
     150:     request_init(&request, RQ_DAEMON, daemon, RQ_USER, user, RQ_FILE, 1, 0);
     151:     sock_methods(&request);
     152:
     153:     /*
     154:      * If a server hostname is specified, insist that the name maps to at
     155:      * most one address. eval_hostname() warns the user about name server
     156:      * problems, while using the request.server structure as a cache for host
     157:      * address and name conversion results.
     158:      */
     159:     if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
     160:     if ((hp = find_inet_addr(server)) == 0)
     161:         exit(1);
     162:     memset((char *) &server_sin, 0, sizeof(server_sin));
     163:     server_sin.sin_family = AF_INET;
     164:     request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
     165:
     166:     for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
     167:         memcpy((char *) &server_sin.sin_addr, addr,
     168:            sizeof(server_sin.sin_addr));
     169:
     170:         /*
     171: 	     * Force evaluation of server host name and address. Host name
     172: 	     * conflicts will be reported while eval_hostname() does its job.
     173: 	     */
     174:         request_set(&request, RQ_SERVER_NAME, "", RQ_SERVER_ADDR, "", 0);
     175:         if (STR_EQ(eval_hostname(request.server), unknown))
     176:         tcpd_warn("host address %s->name lookup failed",
     177:               eval_hostaddr(request.server));
     178:     }
     179:     if (count > 1) {
     180:         fprintf(stderr, "Error: %s has more than one address\n", server);
     181:         fprintf(stderr, "Please specify an address instead\n");
     182:         exit(1);
     183:     }
     184:     free((char *) hp);
     185:     } else {
     186:     request_set(&request, RQ_SERVER_NAME, server, 0);
     187:     }
     188:
     189:     /*
     190:      * If a client address is specified, we simulate the effect of client
     191:      * hostname lookup failure.
     192:      */
     193:     if (dot_quad_addr(client) != INADDR_NONE) {
     194:     request_set(&request, RQ_CLIENT_ADDR, client, 0);
     195:     tcpdmatch(&request);
     196:     exit(0);
     197:     }
     198:
     199:     /*
     200:      * Perhaps they are testing special client hostname patterns that aren't
     201:      * really host names at all.
     202:      */
     203:     if (NOT_INADDR(client) && HOSTNAME_KNOWN(client) == 0) {
     204:     request_set(&request, RQ_CLIENT_NAME, client, 0);
     205:     tcpdmatch(&request);
     206:     exit(0);
     207:     }
     208:
     209:     /*
     210:      * Otherwise, assume that a client hostname is specified, and insist that
     211:      * the address can be looked up. The reason for this requirement is that
     212:      * in real life the client address is available (at least with IP). Let
     213:      * eval_hostname() figure out if this host is properly registered, while
     214:      * using the request.client structure as a cache for host name and
     215:      * address conversion results.
     216:      */
     217:     if ((hp = find_inet_addr(client)) == 0)
     218:     exit(1);
     219:     memset((char *) &client_sin, 0, sizeof(client_sin));
     220:     client_sin.sin_family = AF_INET;
     221:     request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
     222:
     223:     for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
     224:     memcpy((char *) &client_sin.sin_addr, addr,
     225:            sizeof(client_sin.sin_addr));
     226:
     227:     /*
     228: 	 * Force evaluation of client host name and address. Host name
     229: 	 * conflicts will be reported while eval_hostname() does its job.
     230: 	 */
     231:     request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
     232:     if (STR_EQ(eval_hostname(request.client), unknown))
     233:         tcpd_warn("host address %s->name lookup failed",
     234:               eval_hostaddr(request.client));
     235:     tcpdmatch(&request);
     236:     if (hp->h_addr_list[count + 1])
     237:         printf("\n");
     238:     }
     239:     free((char *) hp);
     240:     exit(0);
     241: }
     242:
     243: /* Explain how to use this program */
     244:
     245: static void usage(myname)
     246: char   *myname;
     247: {
     248:     fprintf(stderr, "usage: %s [-d] [-i inet_conf] daemon[@host] [user@]host\n",
     249:         myname);
     250:     fprintf(stderr, "	-d: use allow/deny files in current directory\n");
     251:     fprintf(stderr, "	-i: location of inetd.conf file\n");
     252:     exit(1);
     253: }
     254:
     255: /* Print interesting expansions */
     256:
     257: static void expand(text, pattern, request)
     258: char   *text;
     259: char   *pattern;
     260: struct request_info *request;
     261: {
     262:     char    buf[BUFSIZ];
     263:
     264:     if (STR_NE(percent_x(buf, sizeof(buf), pattern, request), unknown))
     265:     printf("%s %s\n", text, buf);
     266: }
     267:
     268: /* Try out a (server,client) pair */
     269:
     270: static void tcpdmatch(request)
     271: struct request_info *request;
     272: {
     273:     int     verdict;
     274:
     275:     /*
     276:      * Show what we really know. Suppress uninteresting noise.
     277:      */
     278:     expand("client:   hostname", "%n", request);
     279:     expand("client:   address ", "%a", request);
     280:     expand("client:   username", "%u", request);
     281:     expand("server:   hostname", "%N", request);
     282:     expand("server:   address ", "%A", request);
     283:     expand("server:   process ", "%d", request);
     284:
     285:     /*
     286:      * Reset stuff that might be changed by options handlers. In dry-run
     287:      * mode, extension language routines that would not return should inform
     288:      * us of their plan, by clearing the dry_run flag. This is a bit clumsy
     289:      * but we must be able to verify hosts with more than one network
     290:      * address.
     291:      */
     292:     rfc931_timeout = RFC931_TIMEOUT;
     293:     allow_severity = SEVERITY;
     294:     deny_severity = LOG_WARNING;
     295:     dry_run = 1;
     296:
     297:     /*
     298:      * When paranoid mode is enabled, access is rejected no matter what the
     299:      * access control rules say.
     300:      */
     301: #ifdef PARANOID
     302:     if (STR_EQ(eval_hostname(request->client), paranoid)) {
     303:     printf("access:   denied (PARANOID mode)\n\n");
     304:     return;
     305:     }
     306: #endif
     307:
     308:     /*
     309:      * Report the access control verdict.
     310:      */
     311:     verdict = hosts_access(request);
     312:     printf("access:   %s\n",
     313:        dry_run == 0 ? "delegated" :
     314:        verdict ? "granted" : "denied");
     315: }

#### Defined functions

expand defined in line 257; used 6 times

- in line 278-283(6)

main defined in line 52; never used
tcpdmatch defined in line 270; used 4 times

- in line 48, 195, 205, 235

usage defined in line 245; used 3 times

- in line 47, 89-94(2)

#### Defined variables

sccsid defined in line 17; never used

#### Defined macros

INADDR_NONE defined in line 38; used 2 times

- in line 37, 193

Last modified: 1995-01-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 931 |