diff options
Diffstat (limited to 'lib/libskey/authfile.c')
-rw-r--r-- | lib/libskey/authfile.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/lib/libskey/authfile.c b/lib/libskey/authfile.c new file mode 100644 index 0000000..32b920a --- /dev/null +++ b/lib/libskey/authfile.c @@ -0,0 +1,170 @@ + /* Portions taken from the skey distribution on Oct 21 1993 */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <pwd.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> + +#if (MAXHOSTNAMELEN < 64) /* AIX weirdness */ +#undef MAXHOSTNAMELEN +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 255 +#endif + +#include "skey.h" + +static int isaddr(); +static int rdnets(); + +#define MAXADDR 16 /* how many addresses can a machine + * have? */ + + /* + * Turn host into an IP address and then look it up in the authorization + * database to determine if ordinary password logins are OK + */ +int authfile(host) +char *host; +{ + char *addr[MAXADDR]; + char **ap; + long n; + struct hostent *hp; + char **lp; + struct hostent *xp; + int addr_length; + + if (strlen(host) == 0) { + /* Local login, okay */ + return 1; + } + if (isaddr(host)) { + return rdnets(inet_addr(host)); + } else { + + /* + * Stash away a copy of the host address list because it will be + * clobbered by other gethostbyXXX() calls. + */ + + hp = gethostbyname(host); + if (hp == NULL) { + syslog(LOG_ERR, "unknown host: %s", host); + return 0; + } + if (hp->h_addrtype != AF_INET) { + syslog(LOG_ERR, "unknown network family: %d", hp->h_addrtype); + return 0; + } + for (lp = hp->h_addr_list, ap = addr; ap < addr + MAXADDR; lp++, ap++) { + if (*lp == NULL) { + *ap = 0; + break; + } else { + if ((*ap = malloc(hp->h_length)) == 0) { + syslog(LOG_ERR, "out of memory"); + return 0; + } + memcpy(*ap, *lp, hp->h_length); + } + } + addr_length = hp->h_length; + + /* + * See if any of the addresses matches a pattern in the control file. + * Report and skip the address if it does not belong to the remote + * host. Assume localhost == localhost.domain. + */ + +#define NEQ(x,y) (strcasecmp((x),(y)) != 0) + + while (ap-- > addr) { + memcpy((char *) &n, *ap, addr_length); + if (rdnets(n)) { + if ((hp = gethostbyaddr(*ap, addr_length, AF_INET)) == 0 + || (NEQ(host, hp->h_name) && NEQ(host, "localhost"))) { + syslog(LOG_ERR, "IP address %s not registered for host %s", + inet_ntoa(*(struct in_addr *) * ap), host); + continue; + } + return 1; + } + } + return 0; + } +} +static int rdnets(host) +unsigned long host; +{ + FILE *fp; + char buf[128], + *cp; + long pattern, + mask; + char *strtok(); + int permit_it = 0; + + fp = fopen("/etc/skey.access", "r"); + if (fp == NULL) + return 1; /* XXX */ + while (fgets(buf, sizeof(buf), fp), !feof(fp)) { + if (buf[0] == '#') + continue; /* Comment */ + cp = strtok(buf, " \t"); + if (cp == NULL) + continue; + /* two choices permit or deny */ + if (strncasecmp(cp, "permit", 4) == 0) { + permit_it = 1; + } else { + if (strncasecmp(cp, "deny", 4) == 0) { + permit_it = 0; + } else { + continue; /* ignore this it is not + * permit/deny */ + } + } + cp = strtok(NULL, " \t"); + if (cp == NULL) + continue; /* Invalid line */ + pattern = inet_addr(cp); + cp = strtok(NULL, " \t"); + if (cp == NULL) + continue; /* Invalid line */ + mask = inet_addr(cp); + if ((host & mask) == pattern) { + fclose(fp); + return permit_it; + } + } + fclose(fp); + return 0; +} + + /* + * Return TRUE if string appears to be an IP address in dotted decimal; + * return FALSE otherwise (i.e., if string is a domain name) + */ +static int isaddr(s) +register char *s; +{ + char c; + + if (s == NULL) + return 1; /* Can't happen */ + + while ((c = *s++) != '\0') { + if (c != '[' && c != ']' && !isdigit(c) && c != '.') + return 0; + } + return 1; +} |