home *** CD-ROM | disk | FTP | other *** search
- /*
- * fromhost() returns the name of the host at the other end of standard
- * input, the host address if name lookup fails, "stdin" if it is connected
- * to a terminal, or a null pointer in all other cases.
- *
- * Protection against spoofing of naive rsh and rlogind implementations:
- *
- * Initially, all we have is the remote host address. If the host address->name
- * mapping is available, fromhost() verifies that the host name->address
- * mapping yields the original host address. The idea is that it is much
- * easier to compromise some random address->name map (because there is one
- * for almost every network), than to compromise the name->address map that
- * is unique for your internet domain.
- *
- * Anyway, if the test fails, fromhost() either drops the connection (when
- * compiled with -DPARANOID) or just returns the remote host address instead
- * of the bad remote host name (not compiled with -DPARANOID).
- *
- * Diagnostics are reported through syslog(3).
- *
- * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#) fromhost.c 1.2 91/05/20 13:28:01";
- #endif
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/socket.h>
- #include <syslog.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN BUFSIZ
- #endif
-
- /* The following are to be used in assignment context, not in comparisons */
-
- #define GOOD 1
- #define BAD 0
-
- /* fromhost - find out what is at the other end of standard input */
-
- char *fromhost()
- {
- struct sockaddr sa;
- struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
- struct hostent *hp;
- int sockt = fileno(stdin);
- int length = sizeof(sa);
- static char remotehost[MAXHOSTNAMELEN + 1];
- char *inet_ntoa();
- char *strncpy();
-
- /* Try to be smart if standard input is not connected to a socket. */
-
- if (getpeername(sockt, &sa, &length) < 0) {
- if (isatty(sockt)) {
- return ("stdin");
- } else {
- syslog(LOG_ERR, "getpeername: %m");
- return (0);
- }
- }
- if (sa.sa_family != AF_INET) {
- syslog(LOG_ERR, "unknown address family %ld", (long) sa.sa_family);
- return (0);
- }
- /* Look up the remote host name. Use its address if name lookup fails. */
-
- if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
- sizeof(sin->sin_addr.s_addr),
- AF_INET)) == 0) {
- return (inet_ntoa(sin->sin_addr));
- }
- /* Save the host name before the gethostbyxxx() routines clobber it. */
-
- (void) strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
- remotehost[sizeof(remotehost) - 1] = 0;
-
- /*
- * Decide what to do if the host name does not match the address or if we
- * are unable to verify that the host name matches the address.
- */
-
- if (matchname(remotehost, sin)) {
- return (remotehost);
- } else {
- #ifdef PARANOID
- exit(0);
- #else
- return (inet_ntoa(sin->sin_addr));
- #endif
- }
- }
-
- /* matchname - determine if host name matches address */
-
- static int matchname(remotehost, sin)
- char *remotehost;
- struct sockaddr_in *sin;
- {
- struct hostent *hp;
- int i;
-
- if ((hp = gethostbyname(remotehost)) == 0) {
-
- /*
- * Unable to verify that the host name matches the address. This may be
- * a transient problem or a botched name server setup.
- */
-
- syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
- return (BAD);
- } else {
-
- /* Look up the host address in the address list we just got. */
-
- for (i = 0; hp->h_addr_list[i]; i++) {
- if (memcmp(hp->h_addr_list[i], (caddr_t) & sin->sin_addr,
- sizeof(sin->sin_addr)) == 0)
- return (GOOD);
- }
-
- /*
- * The host name does not map to the host address. Perhaps someone
- * has compromised a name server. More likely someone botched it, but
- * that could be dangerous, too.
- */
-
- syslog(LOG_ERR, "host name/address mismatch: %s != %s",
- inet_ntoa(sin->sin_addr), hp->h_name);
- return (BAD);
- }
- }
-