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

more complete pam_rhosts_auth



Enclosed is two unified diffs for pam_rhosts_auth that includes support
for +@netgroup, -@netgroup (both in user and host field), as well as
-user, -host and + in the user field. The latter is conditional on the
'promiscuous' option as with + in the host field.  The syntax is
now documented in the README file.

I did not add any 'nis' option, I think the default mode of operation
should be to accept the full non-dangerous part of the traditional
.rhosts syntax.  A 'no_nis' option might be an idea.

The patch is relative to 0.57 preview C that i found at
http://sysadm.sorosis.ro/devel/pam/.  The enclosed patches, and my full
source is also in http://www.math.uio.no/~janl/pam/
I am _not_ subscribed to the linux-pam mailinglist, please mail me
with any comments, wishes for rewrites, etc.

--- pam_rhosts_auth.c.orig	Mon Mar 17 16:57:27 1997
+++ pam_rhosts_auth.c	Mon Mar 17 16:35:23 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,126 @@
 }
 
 /*
- * 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;
+    int negate=1;  /* Multiply return with this to get -1 instead of 1 */
     char **pp;
 
-    if (strcmp("+",lhost) == 0) {
+    _pam_log(LOG_WARNING,"checkhost: %s/%s",rhost,lhost);
+
+    /* Check nis netgroup.  We assume that pam has done all needed
+       paranoia checking before we are handed the rhost */
+    _pam_log(LOG_WARNING,"checkhost: Positive NIS entry?");
+
+    if (strncmp("+@",lhost,2) == 0)
+      return(innetgr(&lhost[2],rhost,NULL,NULL));
+
+    _pam_log(LOG_WARNING,"checkhost: Negative NIS entry?");
+
+    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) {
+        _pam_log(LOG_WARNING, "user %s has a `+' host entry", user);
 	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 */
 	}
     }
 
     /* Try for raw ip address first. */
+    _pam_log(LOG_WARNING,"checkhost: Trying as ipaddr");
     if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
-	return (!! (raddr ^ laddr));
+	return (negate*(! (raddr ^ laddr)));
 
+    _pam_log(LOG_WARNING,"checkhost: Resolving host");
     /* Better be a hostname. */
     hp = gethostbyname(lhost);
     if (hp == NULL)
-	return (1);
+	return (0);
     
+    _pam_log(LOG_WARNING,"checkhost: Checking addresses");
     /* Spin through ip addresses. */
     for (pp = hp->h_addr_list; *pp; ++pp)
 	if (!memcmp (&raddr, *pp, sizeof (unsigned long)))
-	    return (0);
+	    return (negate);
+
+    _pam_log(LOG_WARNING,"checkhost: No match");
 
     /* 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
+  */
+
+  /* [-+]@netgroup */
+  _pam_log(LOG_WARNING,"checkuser: %s/%s",ruser,luser);
+  _pam_log(LOG_WARNING,"checkuser: +@?");
+  if (strncmp("+@",luser,2) == 0)
+    return (innetgr(&luser[2],NULL,ruser,NULL));
+  _pam_log(LOG_WARNING,"checkuser: -@?");
+  if (strncmp("-@",luser,2) == 0)
+    return (-innetgr(&luser[2],NULL,ruser,NULL));
+
+  /* -user */
+  _pam_log(LOG_WARNING,"checkuser: -user?");
+  if (strncmp("-",luser,1) == 0)
+    return(-(strcmp(&luser[1],ruser) == 0));
+
+  /* + */
+  _pam_log(LOG_WARNING,"checkuser: +?");
+  if (strcmp("+",luser) == 0) {
+    _pam_log(LOG_WARNING, "user %s has a `+' user entry", ruser);
+    if (opts->opt_promiscuous)
+      return(1);
+    /* If not promiscuous we handle it as a negative match */
+    return(-1);
+  }
+
+  _pam_log(LOG_WARNING,"checkuser: simple match?");
+  /* 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 +389,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 +430,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 +445,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 +518,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 +542,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;
 	    }


--- README.orig	Mon Mar 17 16:57:40 1997
+++ README	Mon Mar 17 16:37:40 1997
@@ -4,3 +4,53 @@
 "no_rhosts"
 "debug"
 "nowarn"
+"promiscuous"
+
+.rhosts/hosts.equiv format:
+
+There are positive entries, when one is matched authentication
+succeeds and terminates.  There are negative entries, when one is
+matched authentication fails and terminates.  Thus order is
+significant.
+
+Entry		hosts.equiv			.rhosts
+<host>		All users on <host> are ok	Same username from <host> is ok
+<host> <user>	<user> from <host> is ok	ditto
+-<host>		No users from <host> are ok	ditto
+<host> -<user>	<user> from <host> is not ok	ditto
+
+<host> can be ip (IPv4) numbers.
+
+Netgroups may be used in either host or user fields, and then applies
+to all hosts, or users, in the netgroup.  The syntax is
+
+  +@<ng>
+
+The entries
+
+  <host> +@<ng>
+  +@<ng> +@<ng>
+  +@<ng> <user>
+
+means exactly what you think it does.  Negative entries are of the
+form
+
+  -@<ng>
+
+When the "promiscuous" option is given the special character + may be
+used as a wildcard in any field.
+
+  +			Allow anyone from any host to connect. DANGEROUS.
+  + +			Ditto.
+  + <user>		Allow the user to connect from anywhere. DANGEROUS.
+  <host> +		Allow any user from the host. Dangerous.
+  
+These, perhaps more usefull, forms of the + form is also disallowed
+unless "promiscuous" is specified:
+
+  + -<user>		Disallow the user from any host
+  + -@<ng>		Disallow all members of the netgroup from any host
+
+When "promiscuous" is not specified a '+' is handled as a negative
+match.
+




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