summaryrefslogtreecommitdiffstats
path: root/lib/libskey/skeyaccess.c
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1994-10-19 00:03:45 +0000
committerpst <pst@FreeBSD.org>1994-10-19 00:03:45 +0000
commit3bbaa5903cdfa6d903256d9ad37d1d8c20c79437 (patch)
tree18581614639f8a987cdf2526bd645ecfdd38abd3 /lib/libskey/skeyaccess.c
parent1552617ffdcabd5ebae23058e72580c06f45e182 (diff)
downloadFreeBSD-src-3bbaa5903cdfa6d903256d9ad37d1d8c20c79437.zip
FreeBSD-src-3bbaa5903cdfa6d903256d9ad37d1d8c20c79437.tar.gz
Include most of the logdaemon v4.4 S/key changes
Diffstat (limited to 'lib/libskey/skeyaccess.c')
-rw-r--r--lib/libskey/skeyaccess.c200
1 files changed, 142 insertions, 58 deletions
diff --git a/lib/libskey/skeyaccess.c b/lib/libskey/skeyaccess.c
index 67ed549..3cd877f 100644
--- a/lib/libskey/skeyaccess.c
+++ b/lib/libskey/skeyaccess.c
@@ -2,9 +2,14 @@
* Figure out if UNIX passwords are permitted for any combination of user
* name, group member, terminal port, host_name or network:
*
- * Programmatic interface: skeyaccess(char *user, char *port, char *host)
+ * Programmatic interface: skeyaccess(user, port, host, addr)
*
- * Specify a null character pointer where information is not available.
+ * All arguments are null-terminated strings. Specify a null character pointer
+ * where information is not available.
+ *
+ * When no address information is given this code performs the host (internet)
+ * address lookup itself. It rejects addresses that appear to belong to
+ * someone else.
*
* When compiled with -DPERMIT_CONSOLE always permits UNIX passwords with
* console logins, no matter what the configuration file says.
@@ -12,7 +17,9 @@
* To build a stand-alone test version, compile with -DTEST and run it off an
* skey.access file in the current directory:
*
- * Command-line interface: ./skeyaccess user port [host]
+ * Command-line interface: ./skeyaccess user port [host_or_ip_addr]
+ *
+ * Errors are reported via syslogd.
*
* Author: Wietse Venema, Eindhoven University of Technology.
*/
@@ -54,6 +61,8 @@ static int match_internet_addr();
static int match_group();
static int match_token();
static int is_internet_addr();
+static struct in_addr *convert_internet_addr();
+static struct in_addr *lookup_internet_addr();
#define MAX_ADDR 32
#define PERMIT 1
@@ -68,40 +77,53 @@ struct login_info {
/* skeyaccess - find out if UNIX passwords are permitted */
-int skeyaccess(user, port, host)
+int skeyaccess(user, port, host, addr)
char *user;
char *port;
char *host;
+char *addr;
{
- struct hostent *hp;
+ FILE *fp;
struct login_info login_info;
- struct in_addr internet_addr[MAX_ADDR + 1];
- char hostname_buf[MAXHOSTNAMELEN + 1];
- int i;
+ int result;
+ /*
+ * Assume no restriction on the use of UNIX passwords when the s/key
+ * acces table does not exist.
+ */
+ if ((fp = fopen(_PATH_SKEYACCESS, "r")) == 0) {
+#ifdef TEST
+ fprintf(stderr, "No file %s, thus no access control\n", _PATH_SKEYACCESS);
+#endif
+ return (PERMIT);
+ }
+
+ /*
+ * Bundle up the arguments in a structure so we won't have to drag around
+ * boring long argument lists.
+ *
+ * Look up the host address when only the name is given. We try to reject
+ * addresses that belong to someone else.
+ */
login_info.user = user;
login_info.port = port;
- login_info.host_name = 0;
- login_info.internet_addr = 0;
-
- if (host) {
- if (is_internet_addr(host)) { /* not DECnet */
- internet_addr[0].s_addr = inet_addr(host);
- internet_addr[1].s_addr = 0;
- login_info.internet_addr = internet_addr;
+
+ if (host != 0 && !is_internet_addr(host)) {
+ login_info.host_name = host;
+ } else {
+ login_info.host_name = 0;
+ }
+
+ if (addr != 0 && is_internet_addr(addr)) {
+ login_info.internet_addr = convert_internet_addr(addr);
+ } else if (host != 0) {
+ if (is_internet_addr(host)) {
+ login_info.internet_addr = convert_internet_addr(host);
} else {
- if ((hp = gethostbyname(host)) != 0 && hp->h_addrtype == AF_INET) {
- for (i = 0; i < MAX_ADDR && hp->h_addr_list[i]; i++)
- memcpy((char *) &internet_addr[i],
- hp->h_addr_list[i], hp->h_length);
- internet_addr[i].s_addr = 0;
- login_info.internet_addr = internet_addr;
- host = hp->h_name;
- }
- strncpy(hostname_buf, host, MAXHOSTNAMELEN);
- hostname_buf[MAXHOSTNAMELEN] = 0;
- login_info.host_name = hostname_buf;
+ login_info.internet_addr = lookup_internet_addr(host);
}
+ } else {
+ login_info.internet_addr = 0;
}
/*
@@ -115,20 +137,25 @@ char *host;
if (login_info.internet_addr == 0) {
printf("none\n");
} else {
+ int i;
+
for (i = 0; login_info.internet_addr[i].s_addr; i++)
- printf("%s%s", inet_ntoa(login_info.internet_addr[i]),
+ printf("%s%s", login_info.internet_addr[i].s_addr == -1 ?
+ "(see error log)" : inet_ntoa(login_info.internet_addr[i]),
login_info.internet_addr[i + 1].s_addr ? " " : "\n");
}
#endif
- return (_skeyaccess(&login_info));
+ result = _skeyaccess(fp, &login_info);
+ fclose(fp);
+ return (result);
}
/* _skeyaccess - find out if UNIX passwords are permitted */
-int _skeyaccess(login_info)
+int _skeyaccess(fp, login_info)
+FILE *fp;
struct login_info *login_info;
{
- FILE *fp;
char buf[BUFSIZ];
char *tok;
int match;
@@ -140,13 +167,6 @@ struct login_info *login_info;
#endif
/*
- * Assume no restriction on the use of UNIX passwords when the s/key
- * acces table does not exist.
- */
- if ((fp = fopen(_PATH_SKEYACCESS, "r")) == 0)
- return (PERMIT);
-
- /*
* Scan the s/key access table until we find an entry that matches. If no
* match is found, assume that UNIX passwords are disallowed.
*/
@@ -187,7 +207,6 @@ struct login_info *login_info;
}
}
}
- fclose(fp);
return (match ? permission : DENY);
}
@@ -200,7 +219,6 @@ struct login_info *login_info;
long pattern;
long mask;
struct in_addr *addrp;
- struct hostent *hp;
if (login_info->internet_addr == 0)
return (0);
@@ -212,26 +230,13 @@ struct login_info *login_info;
mask = inet_addr(tok);
/*
- * 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.
+ * See if any of the addresses matches a pattern in the control file. We
+ * have already tried to drop addresses that belong to someone else.
*/
-#define NEQ(x,y) (strcasecmp((x),(y)) != 0)
-
- for (addrp = login_info->internet_addr; addrp->s_addr; addrp++) {
- if ((addrp->s_addr & mask) == pattern) {
- if (login_info->host_name != 0 &&
- ((hp = gethostbyaddr((char *) addrp, sizeof(*addrp), AF_INET)) == 0
- || (NEQ(login_info->host_name, hp->h_name)
- && NEQ(login_info->host_name, "localhost")))) {
- syslog(LOG_ERR, "address %s not registered for host %s",
- inet_ntoa(*addrp), login_info->host_name);
- continue;
- }
+ for (addrp = login_info->internet_addr; addrp->s_addr; addrp++)
+ if (addrp->s_addr != -1 && (addrp->s_addr & mask) == pattern)
return (1);
- }
- }
return (0);
}
@@ -365,18 +370,97 @@ char *str;
return (runs == 4);
}
+/* lookup_internet_addr - look up internet addresses with extreme prejudice */
+
+static struct in_addr *lookup_internet_addr(host)
+char *host;
+{
+ struct hostent *hp;
+ static struct in_addr list[MAX_ADDR + 1];
+ char buf[MAXHOSTNAMELEN + 1];
+ int length;
+ int i;
+
+ if ((hp = gethostbyname(host)) == 0 || hp->h_addrtype != AF_INET)
+ return (0);
+
+ /*
+ * Save a copy of the results before gethostbyaddr() clobbers them.
+ */
+
+ for (i = 0; i < MAX_ADDR && hp->h_addr_list[i]; i++)
+ memcpy((char *) &list[i],
+ hp->h_addr_list[i], hp->h_length);
+ list[i].s_addr = 0;
+
+ strncpy(buf, hp->h_name, MAXHOSTNAMELEN);
+ buf[MAXHOSTNAMELEN] = 0;
+ length = hp->h_length;
+
+ /*
+ * Wipe addresses that appear to belong to someone else. We will get
+ * false alarms when when the hostname comes from DNS, while its
+ * addresses are listed under different names in local databases.
+ */
+#define NEQ(x,y) (strcasecmp((x),(y)) != 0)
+#define NEQ3(x,y,n) (strncasecmp((x),(y), (n)) != 0)
+
+ while (--i >= 0) {
+ if ((hp = gethostbyaddr((char *) &list[i], length, AF_INET)) == 0) {
+ syslog(LOG_ERR, "address %s not registered for host %s",
+ inet_ntoa(list[i]), buf);
+ list[i].s_addr = -1;
+ }
+ if (NEQ(buf, hp->h_name) && NEQ3(buf, "localhost.", 10)) {
+ syslog(LOG_ERR, "address %s registered for host %s and %s",
+ inet_ntoa(list[i]), hp->h_name, buf);
+ list[i].s_addr = -1;
+ }
+ }
+ return (list);
+}
+
+/* convert_internet_addr - convert string to internet address */
+
+static struct in_addr *convert_internet_addr(string)
+char *string;
+{
+ static struct in_addr list[2];
+
+ list[0].s_addr = inet_addr(string);
+ list[1].s_addr = 0;
+ return (list);
+}
+
#ifdef TEST
main(argc, argv)
int argc;
char **argv;
{
+ struct hostent *hp;
+ char host[MAXHOSTNAMELEN + 1];
+ int verdict;
+ char *user;
+ char *port;
+
if (argc != 3 && argc != 4) {
fprintf(stderr, "usage: %s user port [host_or_ip_address]\n", argv[0]);
exit(0);
}
+ if (_PATH_SKEYACCESS[0] != '/')
+ printf("Warning: this program uses control file: %s\n", KEYACCESS);
openlog("login", LOG_PID, LOG_AUTH);
- printf("%s\n", skeyaccess(argv[1], argv[2], argv[3]) ? "YES" : "NO");
+
+ user = argv[1];
+ port = argv[2];
+ if (argv[3]) {
+ strncpy(host, (hp = gethostbyname(argv[3])) ?
+ hp->h_name : argv[3], MAXHOSTNAMELEN);
+ host[MAXHOSTNAMELEN] = 0;
+ }
+ verdict = skeyaccess(user, port, argv[3] ? host : (char *) 0, (char *) 0);
+ printf("UNIX passwords %spermitted\n", verdict ? "" : "NOT ");
return (0);
}
OpenPOWER on IntegriCloud