]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
(iruserok): Remain setuid to the local user
authorUlrich Drepper <drepper@redhat.com>
Thu, 9 Apr 1998 17:39:54 +0000 (17:39 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 9 Apr 1998 17:39:54 +0000 (17:39 +0000)
while .rhosts is actually read, to make .rhosts-over-NFS work
(PR libc/524).  Use iruserfopen() for security checks on both
hosts.equiv and .rhosts.  General cleanup.
(iruserfopen): New function, performs careful checking on
hosts.equiv/.rhosts files.  Disallows all the old forbidden
stuff plus hard links to files.

inet/rcmd.c

index 121cd19302f24245a15989d4ceab435b85c3cd7a..dea06035bbe18876fc6dd9061bfc1c5a649c8b20 100644 (file)
@@ -297,6 +297,51 @@ ruserok(rhost, superuser, ruser, luser)
        return -1;
 }
 
+/* Extremely paranoid file open function. */
+static FILE *
+iruserfopen(char *file, uid_t okuser)
+{
+    struct stat st;
+    char *cp = NULL;
+    FILE *res = NULL;
+
+    /*
+     * If not a regular file, if owned by someone other than
+     * user or root, if writeable by anyone but the owner, or if
+     * hardlinked anywhere, quit.
+     */
+    cp = NULL;
+    if (lstat(file, &st))
+       cp = _("lstat failed");
+    else if (!S_ISREG(st.st_mode))
+       cp = _("not regular file");
+    else
+    {
+       res = fopen(file, "r");
+       if (!res)
+           cp = _("cannot open");
+       else if (fstat(fileno(res), &st) < 0)
+           cp = _("fstat failed");
+       else if (st.st_uid && st.st_uid != okuser)
+           cp = _("bad owner");
+       else if (st.st_mode & (S_IWGRP|S_IWOTH))
+           cp = _("writeable by other than owner");
+       else if (st.st_nlink > 1)
+           cp = _("hard linked somewhere");
+    }
+
+    /* If there were any problems, quit. */
+    if (cp)
+    {
+       __rcmd_errstr = cp;
+       if(res)
+           fclose(res);
+       return NULL;
+    }
+
+    return res;
+}
+
 /*
  * New .rhosts strategy: We are passed an ip address. We spin through
  * hosts.equiv and .rhosts looking for a match. When the .rhosts only
@@ -306,84 +351,64 @@ ruserok(rhost, superuser, ruser, luser)
  *
  * Returns 0 if ok, -1 if not ok.
  */
+
 int
 iruserok(raddr, superuser, ruser, luser)
        u_int32_t raddr;
        int superuser;
        const char *ruser, *luser;
 {
-       register char *cp;
-       struct stat sbuf;
+    FILE *hostf;
+    int isbad;
+
+    if(!superuser)
+       hostf = iruserfopen(_PATH_HEQUIV, 0);
+
+    if (hostf)
+    {
+       isbad = __ivaliduser(hostf, raddr, luser, ruser);
+       fclose(hostf);
+
+       if (!isbad)
+           return 0;
+    }
+
+    if (__check_rhosts_file || superuser)
+    {
+       char *pbuf;
        struct passwd pwdbuf, *pwd;
-       FILE *hostf;
-       int first;
-
-       first = 1;
-       hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
-again:
-       if (hostf) {
-               if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
-                       (void)fclose(hostf);
-                       return 0;
-               }
-               (void)fclose(hostf);
-       }
-       if (first == 1 && (__check_rhosts_file || superuser)) {
-               char *pbuf;
-               size_t dirlen;
-               size_t buflen = __sysconf (_SC_GETPW_R_SIZE_MAX);
-               char *buffer = __alloca (buflen);
-
-               first = 0;
-               if (__getpwnam_r (luser, &pwdbuf, buffer, buflen, &pwd) < 0)
-                       return -1;
+       size_t dirlen;
+       size_t buflen = __sysconf (_SC_GETPW_R_SIZE_MAX);
+               char *buffer = __alloca (buflen);
+       uid_t uid;
 
-               dirlen = strlen (pwd->pw_dir);
-               pbuf = alloca (dirlen + sizeof "/.rhosts");
-               memcpy (pbuf, pwd->pw_dir, dirlen);
-               memcpy (pbuf + dirlen, "/.rhosts", sizeof "/.rhosts");
-
-               /*
-                * Change effective uid while opening .rhosts.  If root and
-                * reading an NFS mounted file system, can't read files that
-                * are protected read/write owner only.
-                */
-               if (__access (pbuf, R_OK) != 0)
-                 hostf = NULL;
-               else
-                 {
-                   uid_t uid = geteuid ();
-                   seteuid (pwd->pw_uid);
-                   hostf = fopen (pbuf, "r");
-                   seteuid (uid);
-                 }
-
-               if (hostf == NULL)
-                       return -1;
-               /*
-                * If not a regular file, or is owned by someone other than
-                * user or root or if writeable by anyone but the owner, quit.
-                */
-               cp = NULL;
-               if (lstat(pbuf, &sbuf) < 0)
-                       cp = _(".rhosts lstat failed");
-               else if (!S_ISREG(sbuf.st_mode))
-                       cp = _(".rhosts not regular file");
-               else if (fstat(fileno(hostf), &sbuf) < 0)
-                       cp = _(".rhosts fstat failed");
-               else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
-                       cp = _("bad .rhosts owner");
-               else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
-                       cp = _(".rhosts writeable by other than owner");
-               /* If there were any problems, quit. */
-               if (cp) {
-                       __rcmd_errstr = cp;
-                       (void)fclose(hostf);
-                       return -1;
-               }
-               goto again;
+       if (__getpwnam_r (luser, &pwdbuf, buffer, buflen, &pwd))
+           return -1;
+
+       dirlen = strlen (pwd->pw_dir);
+       pbuf = alloca (dirlen + sizeof "/.rhosts");
+       memcpy (pbuf, pwd->pw_dir, dirlen);
+       memcpy (pbuf + dirlen, "/.rhosts", sizeof "/.rhosts");
+
+       /*
+        * Change effective uid while reading .rhosts.  If root and
+        * reading an NFS mounted file system, can't read files that
+        * are protected read/write owner only.
+        */
+       uid = geteuid();
+       seteuid (pwd->pw_uid);
+       hostf = iruserfopen (pbuf, pwd->pw_uid);
+
+       if(hostf)
+       {
+           isbad = __ivaliduser(hostf, raddr, luser, ruser);
+           fclose(hostf);
        }
-       return -1;
+
+       seteuid(uid);
+       return isbad;
+    }
+    return -1;
 }
 
 /*