[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: more complete pam_rhosts_auth



Nicolai Langfeldt <janl@math.uio.no>:
...

Ooops, the patch I sent yesterday, does not even compile, and it has
a stupid feature or two.   Got a bit confusing at the end of the day.
Here is a new patch, that compiles, and has less debugging output
and correct messages about + entries.  I also put the new complete
source and patch at http://www.math.uio.no/~janl/pam/

Nicolai

--- pam_rhosts_auth.c.orig	Mon Mar 17 16:57:27 1997
+++ pam_rhosts_auth.c	Tue Mar 18 10:43:56 1997
@@ -79,6 +79,31 @@
 
 #define PAM_SM_AUTH  /* only defines this management group */
 
+/*
+
+  This is the solaris manpage entry for innetgr.  It's declared in
+  <netdb.h> on solaris2 machines.
+
+SYNOPSIS
+     int innetgr(const char *netgroup, const char *machine,
+          const char *user, const char *domain);
+
+DESCRIPTION
+     The function innetgr() returns 1 if there is a netgroup net-
+     group that contains the specified machine, user, domain tri-
+     ple as a member; otherwise it returns 0.  Any  of  the  sup-
+     plied pointers machine, user, and domain may be NULL, signi-
+     fying a "wild card" that matches all values in that position
+     of the triple.
+
+     The innetgr() function is safe for  use  in  single-threaded
+     and multi-threaded applications. 
+
+*/
+
+int innetgr(const char *, const char *, const char *,const char *);
+
+
 #include <security/pam_modules.h>
 
 /*
@@ -200,60 +225,109 @@
 }
 
 /*
- * Returns 0 if match, 1 if no match.
+ * Returns 1 if positive match, 0 if no match, -1 if negative match.
  */
 
 static int
-__icheckhost (pam_handle_t *pamh, struct _options *opts, u_long raddr
-	      , register char *lhost)
+__icheckhost (pam_handle_t *pamh, struct _options *opts, u_long raddr,
+	      register char *lhost, const char *rhost)
 {
     struct hostent *hp;
     u_long laddr;
-    char **pp;
+    int negate=1;  /* Multiply return with this to get -1 instead of 1 */
+    char **pp, *user;
 
-    if (strcmp("+",lhost) == 0) {
-	if (opts->opt_promiscuous) {
-	    return (0);                     /* asking for trouble, but ok.. */
-	} else {
-	    if (opts->opt_debug) {
-		const char *user;
-		(void) pam_get_item(pamh, PAM_USER, (const void **)&user);
-		_pam_log(LOG_WARNING, "user %s has a `+' entry", user);
-	    }
-	    return (1);                     /* tough luck */
-	}
+    /* Check nis netgroup.  We assume that pam has done all needed
+       paranoia checking before we are handed the rhost */
+    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) {
+        (void) pam_get_item(pamh, PAM_USER, (const void **)&user);
+        _pam_log(LOG_WARNING, "user %s has a `+' host entry", user);
+	if (opts->opt_promiscuous)
+	    return (1);                     /* asking for trouble, but ok.. */
+	/* If not promiscuous: handle as negative */
+	return (-1);                     
     }
 
     /* Try for raw ip address first. */
     if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
-	return (!! (raddr ^ laddr));
+	return (negate*(! (raddr ^ laddr)));
 
     /* Better be a hostname. */
     hp = gethostbyname(lhost);
     if (hp == NULL)
-	return (1);
+	return (0);
     
     /* Spin through ip addresses. */
     for (pp = hp->h_addr_list; *pp; ++pp)
 	if (!memcmp (&raddr, *pp, sizeof (unsigned long)))
-	    return (0);
+	    return (negate);
 
     /* No match. */
-    return (1);
+    return (0);
+}
+
+/* Returns 1 on positive match, 0 on no match, -1 on negative match */
+
+static int
+__icheckuser(pam_handle_t *pamh, struct _options *opts, 
+	     const char *luser, const char *ruser, const char *rhost)
+
+
+{
+  /*
+    luser is user entry from .rhosts/hosts.equiv file
+    ruser is user id on remote host
+    rhost is the remote host name
+  */
+  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) {
+    (void) pam_get_item(pamh, PAM_USER, (const void **)&user);
+    _pam_log(LOG_WARNING, "user %s has a `+' user entry", user);
+    if (opts->opt_promiscuous)
+      return(1);
+    /* If not promiscuous we handle it as a negative match */
+    return(-1);
+  }
+
+  /* simple string match */
+  return (strcmp(ruser, luser) == 0);
 }
 
 /*
- * Returns 0 if match, 1 if not ok.
+ * Returns 0 if positive match, 1 if _not_ ok.
  */
 
 static int
 __ivaliduser (pam_handle_t *pamh, struct _options *opts,
 	      FILE *hostf, u_long raddr,
-	      const char *luser, const char *ruser)
+	      const char *luser, const char *ruser, const char *rhost)
 {
     register const char *user;
     register char *p;
-    int ch;
+    int ch,hcheck,ucheck;
     char buf[MAXHOSTNAMELEN + 128];                       /* host + login */
 
     buf[sizeof (buf)-1] = '\0';                 	/* terminate line */
@@ -298,11 +372,28 @@
 
 	/* buf -> host(?) ; user -> username(?) */
 
-	if (__icheckhost(pamh, opts, raddr, buf) == 0) {
-	    if (! (*user))
-	        user = luser;
-	    if (strcmp(ruser, user) == 0)
-	        return (0);
+	/* First check host part */
+	hcheck=__icheckhost(pamh, opts, raddr, buf, rhost);
+
+	if (hcheck<0)
+	  return(1);
+
+	if (hcheck) {
+	  /* Then check user part */
+	  if (! (*user))
+	    user = luser;
+	  
+	  ucheck=__icheckuser(pamh, opts, user, ruser, rhost);
+
+	  /* Positive 'host user' match? */
+	  if (ucheck>0)
+	    return(0);
+
+	  /* Negative 'host -user' match? */
+	  if (ucheck<0)
+	    return(1);
+
+	  /* Neither, go on looking for match */
 	}
     }
 
@@ -322,7 +413,7 @@
 static int
 iruserok(pam_handle_t *pamh,
 	 struct _options *opts, u_long raddr, int superuser,
-	 const char *ruser, const char *luser)
+	 const char *ruser, const char *luser, const char *rhost)
 {
     const char *cp;
     struct stat sbuf;
@@ -337,7 +428,7 @@
 	/* try to open system hosts.equiv file */
 	hostf = fopen (_PATH_HEQUIV, "r");
 	if (hostf) {
-	    answer = __ivaliduser(pamh, opts, hostf, raddr, luser, ruser);
+	    answer = __ivaliduser(pamh, opts, hostf, raddr, luser, ruser, rhost);
 	    (void) fclose(hostf);
 	    if (answer == 0)
 		return 0;      /* remote host is equivalent to localhost */
@@ -410,7 +501,7 @@
 	return 1;
     }
 
-    answer = __ivaliduser (pamh, opts, hostf, raddr, luser, ruser);
+    answer = __ivaliduser (pamh, opts, hostf, raddr, luser, ruser, rhost);
     (void) fclose(hostf);
     return answer;
 }
@@ -434,7 +525,7 @@
 	    memcpy (&addr, *ap, sizeof(addr));
 
 	    /* check user on remote host */
-	    if (iruserok(pamh, opts, addr, superuser, ruser, luser) == 0) {
+	    if (iruserok(pamh, opts, addr, superuser, ruser, luser, rhost) == 0) {
 		answer = 0;                                /* success */
 		break;
 	    }




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []