aboutsummaryrefslogtreecommitdiff
path: root/inet/rcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'inet/rcmd.c')
-rw-r--r--inet/rcmd.c260
1 files changed, 192 insertions, 68 deletions
diff --git a/inet/rcmd.c b/inet/rcmd.c
index 51fa34eca8..483e7b389d 100644
--- a/inet/rcmd.c
+++ b/inet/rcmd.c
@@ -55,8 +55,10 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
#include <string.h>
-int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
-static int __icheckhost __P((u_int32_t, char *)) internal_function;
+int __ivaliduser __P ((FILE *, u_int32_t, const char *, const char *));
+static int __ivaliduser2 __P ((FILE *, u_int32_t, const char *, const char *,
+ const char *));
+
int
rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
@@ -283,7 +285,7 @@ ruserok(rhost, superuser, ruser, luser)
for (ap = hp->h_addr_list; *ap; ++ap) {
bcopy(*ap, &addr, sizeof(addr));
- if (iruserok(addr, superuser, ruser, luser) == 0)
+ if (iruserok(addr, superuser, ruser, luser, rhost) == 0)
return 0;
}
return -1;
@@ -341,11 +343,11 @@ iruserfopen (char *file, uid_t okuser)
*
* Returns 0 if ok, -1 if not ok.
*/
-int
-iruserok (raddr, superuser, ruser, luser)
+static int
+iruserok2 (raddr, superuser, ruser, luser, rhost)
u_int32_t raddr;
int superuser;
- const char *ruser, *luser;
+ const char *ruser, *luser, *rhost;
{
FILE *hostf = NULL;
int isbad;
@@ -355,7 +357,7 @@ iruserok (raddr, superuser, ruser, luser)
if (hostf)
{
- isbad = __ivaliduser (hostf, raddr, luser, ruser);
+ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
fclose (hostf);
if (!isbad)
@@ -388,7 +390,7 @@ iruserok (raddr, superuser, ruser, luser)
if (hostf != NULL)
{
- isbad = __ivaliduser (hostf, raddr, luser, ruser);
+ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
fclose (hostf);
}
@@ -398,10 +400,25 @@ iruserok (raddr, superuser, ruser, luser)
return -1;
}
+/* This is the exported version. */
+int
+iruserok (raddr, superuser, ruser, luser)
+ u_int32_t raddr;
+ int superuser;
+ const char *ruser, *luser;
+{
+ return iruserok2 (raddr, superuser, ruser, luser, "-");
+}
+
/*
* XXX
* Don't make static, used by lpd(8).
*
+ * This function is not used anymore. It is only present because lpd(8)
+ * calls it (!?!). We simply call __invaliduser2() with an illegal rhost
+ * argument. This means that netgroups won't work in .rhost/hosts.equiv
+ * files. If you want lpd to work with netgroups, fix lpd to use ruserok()
+ * or PAM.
* Returns 0 if ok, -1 if not ok.
*/
int
@@ -410,87 +427,194 @@ __ivaliduser(hostf, raddr, luser, ruser)
u_int32_t raddr;
const char *luser, *ruser;
{
- register char *user, *p;
- int ch;
- char *buf = NULL;
- char *cp;
- size_t bufsize = 0;
- ssize_t nread;
-
- while ((nread = __getline (&buf, &bufsize, hostf)) > 0) {
- buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */
- /* Because the file format does not know any form of quoting we
- can search forward for the next '#' character and if found
- make it terminating the line. */
- cp = strchr (buf, '#');
- if (cp != NULL)
- *cp = '\0';
- p = buf;
- while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
- *p = isupper(*p) ? tolower(*p) : *p;
- p++;
- }
- if (*p == ' ' || *p == '\t') {
- *p++ = '\0';
- while (*p == ' ' || *p == '\t')
- p++;
- user = p;
- while (*p != '\n' && *p != ' ' &&
- *p != '\t' && *p != '\0')
- p++;
- } else
- user = p;
- *p = '\0';
- if (__icheckhost(raddr, buf) &&
- strcmp(ruser, *user ? user : luser) == 0) {
- free (buf);
- return 0;
- }
- }
- if (buf != NULL)
- free (buf);
- return -1;
+ return __ivaliduser2(hostf, raddr, luser, ruser, "-");
}
-/*
- * Returns "true" if match, 0 if no match.
- */
+
+/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
static int
internal_function
-__icheckhost(raddr, lhost)
+__icheckhost (raddr, lhost, rhost)
u_int32_t raddr;
- register char *lhost;
+ char *lhost;
+ const char *rhost;
{
struct hostent hostbuf, *hp;
size_t buflen;
char *buffer;
- register u_int32_t laddr;
- register char **pp;
int herr;
+ int save_errno;
+ u_int32_t laddr;
+ int negate=1; /* Multiply return with this to get -1 instead of 1 */
+ char **pp, *user;
+
+ /* Check nis netgroup. */
+ if (strncmp ("+@", lhost, 2) == 0)
+ return innetgr (&lhost[2], rhost, NULL, NULL);
+
+ if (strncmp ("-@", lhost, 2) == 0)
+ return -innetgr (&lhost[2], rhost, NULL, NULL);
+
+ /* -host */
+ if (strncmp ("-", lhost,1) == 0) {
+ negate = -1;
+ lhost++;
+ } else if (strcmp ("+",lhost) == 0) {
+ return 1; /* asking for trouble, but ok.. */
+ }
/* Try for raw ip address first. */
- if (isdigit(*lhost) && (int32_t)(laddr = inet_addr(lhost)) != -1)
- return raddr == laddr;
+ if (isdigit (*lhost) && (long) (laddr = inet_addr (lhost)) != -1)
+ return negate * (! (raddr ^ laddr));
/* Better be a hostname. */
buflen = 1024;
buffer = __alloca (buflen);
+ save_errno = errno;
while (__gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr)
< 0)
- if (herr != NETDB_INTERNAL || errno != ERANGE)
- return 0;
- else
- {
- /* Enlarge the buffer. */
- buflen *= 2;
- buffer = __alloca (buflen);
- }
+ if (herr != NETDB_INTERNAL || errno != ERANGE)
+ return (0);
+ else {
+ /* Enlarge the buffer. */
+ buflen *= 2;
+ buffer = __alloca (buflen);
+ __set_errno (0);
+ }
+ __set_errno (save_errno);
+ if (hp == NULL)
+ return 0;
/* Spin through ip addresses. */
for (pp = hp->h_addr_list; *pp; ++pp)
- if (!memcmp(&raddr, *pp, sizeof(u_int32_t)))
- return 1;
+ if (!memcmp (&raddr, *pp, sizeof (u_int32_t)))
+ return negate;
/* No match. */
- return 0;
+ return (0);
+}
+
+/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
+static int
+internal_function
+__icheckuser (luser, ruser)
+ const char *luser, *ruser;
+{
+ /*
+ luser is user entry from .rhosts/hosts.equiv file
+ ruser is user id on remote host
+ */
+ char *user;
+
+ /* [-+]@netgroup */
+ if (strncmp ("+@", luser, 2) == 0)
+ return innetgr (&luser[2], NULL, ruser, NULL);
+
+ if (strncmp ("-@", luser,2) == 0)
+ return -innetgr (&luser[2], NULL, ruser, NULL);
+
+ /* -user */
+ if (strncmp ("-", luser, 1) == 0)
+ return -(strcmp (&luser[1], ruser) == 0);
+
+ /* + */
+ if (strcmp ("+", luser) == 0)
+ return 1;
+
+ /* simple string match */
+ return strcmp (ruser, luser) == 0;
+}
+
+/*
+ * Returns 1 for blank lines (or only comment lines) and 0 otherwise
+ */
+static int
+__isempty(p)
+ char *p;
+{
+ while (*p && isspace (*p)) {
+ ++p;
+ }
+
+ return (*p == '\0' || *p == '#') ? 1 : 0 ;
+}
+
+/*
+ * Returns 0 if positive match, -1 if _not_ ok.
+ */
+static int
+__ivaliduser2(hostf, raddr, luser, ruser, rhost)
+ FILE *hostf;
+ u_int32_t raddr;
+ const char *luser, *ruser, *rhost;
+{
+ register const char *user;
+ register char *p;
+ int hcheck, ucheck;
+ char *buf = NULL;
+ size_t bufsize = 0;
+
+ while (__getline (&buf, &bufsize, hostf) > 0) {
+ buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */
+ p = buf;
+
+ /* Skip empty or comment lines */
+ if (__isempty (p)) {
+ continue;
+ }
+
+ /* Skip lines that are too long. */
+ if (strchr (p, '\n') == NULL) {
+ int ch = getc (hostf);
+
+ while (ch != '\n' && ch != EOF)
+ ch = getc (hostf);
+ continue;
+ }
+
+ for (;*p && !isspace(*p); ++p) {
+ *p = tolower (*p);
+ }
+
+ /* Next we want to find the permitted name for the remote user. */
+ if (*p == ' ' || *p == '\t') {
+ /* <nul> terminate hostname and skip spaces */
+ for (*p++='\0'; *p && isspace (*p); ++p);
+
+ user = p; /* this is the user's name */
+ while (*p && !isspace (*p))
+ ++p; /* find end of user's name */
+ } else
+ user = p;
+
+ *p = '\0'; /* <nul> terminate username (+host?) */
+
+ /* buf -> host(?) ; user -> username(?) */
+
+ /* First check host part */
+ hcheck = __icheckhost (raddr, buf, rhost);
+
+ if (hcheck < 0)
+ return -1;
+
+ if (hcheck) {
+ /* Then check user part */
+ if (! (*user))
+ user = luser;
+
+ ucheck = __icheckuser (user, ruser);
+
+ /* Positive 'host user' match? */
+ if (ucheck > 0)
+ return 0;
+
+ /* Negative 'host -user' match? */
+ if (ucheck < 0)
+ return -1;
+
+ /* Neither, go on looking for match */
+ }
+ }
+
+ return -1;
}