From 703418fe9d2e3b1e8d594df5788d8001a8116265 Mon Sep 17 00:00:00 2001
From: Jeffrey Bencteux <jeffbencteux@gmail.com>
Date: Fri, 30 Jun 2023 19:02:45 +0200
Subject: [PATCH] CVE-2023-40303: ftpd,rcp,rlogin,rsh,rshd,uucpd: fix: check
 set*id() return values

Several setuid(), setgid(), seteuid() and setguid() return values
were not checked in ftpd/rcp/rlogin/rsh/rshd/uucpd code potentially
leading to potential security issues.

CVE: CVE-2023-40303
Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=e4e65c03f4c11292a3e40ef72ca3f194c8bffdd6]
Signed-off-by: Jeffrey Bencteux <jeffbencteux@gmail.com>
Signed-off-by: Simon Josefsson <simon@josefsson.org>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 ftpd/ftpd.c  | 10 +++++++---
 src/rcp.c    | 39 +++++++++++++++++++++++++++++++++------
 src/rlogin.c | 11 +++++++++--
 src/rsh.c    | 25 +++++++++++++++++++++----
 src/rshd.c   | 20 +++++++++++++++++---
 src/uucpd.c  | 15 +++++++++++++--
 6 files changed, 100 insertions(+), 20 deletions(-)

diff --git a/ftpd/ftpd.c b/ftpd/ftpd.c
index 92b2cca5..28dd523f 100644
--- a/ftpd/ftpd.c
+++ b/ftpd/ftpd.c
@@ -862,7 +862,9 @@ end_login (struct credentials *pcred)
   char *remotehost = pcred->remotehost;
   int atype = pcred->auth_type;
 
-  seteuid ((uid_t) 0);
+  if (seteuid ((uid_t) 0) == -1)
+    _exit (EXIT_FAILURE);
+
   if (pcred->logged_in)
     {
       logwtmp_keep_open (ttyline, "", "");
@@ -1151,7 +1153,8 @@ getdatasock (const char *mode)
 
   if (data >= 0)
     return fdopen (data, mode);
-  seteuid ((uid_t) 0);
+  if (seteuid ((uid_t) 0) == -1)
+    _exit (EXIT_FAILURE);
   s = socket (ctrl_addr.ss_family, SOCK_STREAM, 0);
   if (s < 0)
     goto bad;
@@ -1978,7 +1981,8 @@ passive (int epsv, int af)
   else	/* !AF_INET6 */
     ((struct sockaddr_in *) &pasv_addr)->sin_port = 0;
 
-  seteuid ((uid_t) 0);
+  if (seteuid ((uid_t) 0) == -1)
+    _exit (EXIT_FAILURE);
   if (bind (pdata, (struct sockaddr *) &pasv_addr, pasv_addrlen) < 0)
     {
       if (seteuid ((uid_t) cred.uid))
diff --git a/src/rcp.c b/src/rcp.c
index 75adb253..cdcf8500 100644
--- a/src/rcp.c
+++ b/src/rcp.c
@@ -345,14 +345,23 @@ main (int argc, char *argv[])
   if (from_option)
     {				/* Follow "protocol", send data. */
       response ();
-      setuid (userid);
+
+      if (setuid (userid) == -1)
+      {
+        error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
+      }
+
       source (argc, argv);
       exit (errs);
     }
 
   if (to_option)
     {				/* Receive data. */
-      setuid (userid);
+      if (setuid (userid) == -1)
+      {
+        error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
+      }
+
       sink (argc, argv);
       exit (errs);
     }
@@ -537,7 +546,11 @@ toremote (char *targ, int argc, char *argv[])
 	      if (response () < 0)
 		exit (EXIT_FAILURE);
 	      free (bp);
-	      setuid (userid);
+
+	      if (setuid (userid) == -1)
+              {
+                error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
+              }
 	    }
 	  source (1, argv + i);
 	  close (rem);
@@ -630,7 +643,12 @@ tolocal (int argc, char *argv[])
 	  ++errs;
 	  continue;
 	}
-      seteuid (userid);
+
+      if (seteuid (userid) == -1)
+      {
+        error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
+      }
+
 #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
       sslen = sizeof (ss);
       (void) getpeername (rem, (struct sockaddr *) &ss, &sslen);
@@ -643,7 +661,12 @@ tolocal (int argc, char *argv[])
 #endif
       vect[0] = target;
       sink (1, vect);
-      seteuid (effuid);
+
+      if (seteuid (effuid) == -1)
+      {
+        error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
+      }
+
       close (rem);
       rem = -1;
 #ifdef SHISHI
@@ -1441,7 +1464,11 @@ susystem (char *s, int userid)
       return (127);
 
     case 0:
-      setuid (userid);
+      if (setuid (userid) == -1)
+      {
+        error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
+      }
+
       execl (PATH_BSHELL, "sh", "-c", s, NULL);
       _exit (127);
     }
diff --git a/src/rlogin.c b/src/rlogin.c
index aa6426fb..c543de0c 100644
--- a/src/rlogin.c
+++ b/src/rlogin.c
@@ -647,8 +647,15 @@ try_connect:
   /* Now change to the real user ID.  We have to be set-user-ID root
      to get the privileged port that rcmd () uses.  We now want, however,
      to run as the real user who invoked us.  */
-  seteuid (uid);
-  setuid (uid);
+  if (seteuid (uid) == -1)
+  {
+    error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
+  }
+
+  if (setuid (uid) == -1)
+  {
+    error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
+  }
 
   doit (&osmask);	/* The old mask will activate SIGURG and SIGUSR1!  */
 
diff --git a/src/rsh.c b/src/rsh.c
index 2d622ca4..6f60667d 100644
--- a/src/rsh.c
+++ b/src/rsh.c
@@ -276,8 +276,17 @@ main (int argc, char **argv)
     {
       if (asrsh)
 	*argv = (char *) "rlogin";
-      seteuid (getuid ());
-      setuid (getuid ());
+
+      if (seteuid (getuid ()) == -1)
+      {
+        error (EXIT_FAILURE, errno, "seteuid() failed");
+      }
+
+      if (setuid (getuid ()) == -1)
+      {
+        error (EXIT_FAILURE, errno, "setuid() failed");
+      }
+
       execv (PATH_RLOGIN, argv);
       error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN);
     }
@@ -541,8 +550,16 @@ try_connect:
 	error (0, errno, "setsockopt DEBUG (ignored)");
     }
 
-  seteuid (uid);
-  setuid (uid);
+  if (seteuid (uid) == -1)
+  {
+    error (EXIT_FAILURE, errno, "seteuid() failed");
+  }
+
+  if (setuid (uid) == -1)
+  {
+    error (EXIT_FAILURE, errno, "setuid() failed");
+  }
+
 #ifdef HAVE_SIGACTION
   sigemptyset (&sigs);
   sigaddset (&sigs, SIGINT);
diff --git a/src/rshd.c b/src/rshd.c
index d1c0d0cd..707790e7 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -1847,8 +1847,18 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
     pwd->pw_shell = PATH_BSHELL;
 
   /* Set the gid, then uid to become the user specified by "locuser" */
-  setegid ((gid_t) pwd->pw_gid);
-  setgid ((gid_t) pwd->pw_gid);
+  if (setegid ((gid_t) pwd->pw_gid) == -1)
+  {
+    rshd_error ("Cannot drop privileges (setegid() failed)\n");
+    exit (EXIT_FAILURE);
+  }
+
+  if (setgid ((gid_t) pwd->pw_gid) == -1)
+  {
+    rshd_error ("Cannot drop privileges (setgid() failed)\n");
+    exit (EXIT_FAILURE);
+  }
+
 #ifdef HAVE_INITGROUPS
   initgroups (pwd->pw_name, pwd->pw_gid);	/* BSD groups */
 #endif
@@ -1870,7 +1880,11 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
     }
 #endif /* WITH_PAM */
 
-  setuid ((uid_t) pwd->pw_uid);
+  if (setuid ((uid_t) pwd->pw_uid) == -1)
+  {
+    rshd_error ("Cannot drop privileges (setuid() failed)\n");
+    exit (EXIT_FAILURE);
+  }
 
   /* We'll execute the client's command in the home directory
    * of locuser. Note, that the chdir must be executed after
diff --git a/src/uucpd.c b/src/uucpd.c
index 107589e1..29cfce35 100644
--- a/src/uucpd.c
+++ b/src/uucpd.c
@@ -252,7 +252,12 @@ doit (struct sockaddr *sap, socklen_t salen)
   snprintf (Username, sizeof (Username), "USER=%s", user);
   snprintf (Logname, sizeof (Logname), "LOGNAME=%s", user);
   dologin (pw, sap, salen);
-  setgid (pw->pw_gid);
+
+  if (setgid (pw->pw_gid) == -1)
+  {
+    fprintf (stderr, "setgid() failed");
+    return;
+  }
 #ifdef HAVE_INITGROUPS
   initgroups (pw->pw_name, pw->pw_gid);
 #endif
@@ -261,7 +266,13 @@ doit (struct sockaddr *sap, socklen_t salen)
       fprintf (stderr, "Login incorrect.");
       return;
     }
-  setuid (pw->pw_uid);
+
+  if (setuid (pw->pw_uid) == -1)
+  {
+    fprintf (stderr, "setuid() failed");
+    return;
+  }
+
   execl (uucico_location, "uucico", NULL);
   perror ("uucico server: execl");
 }
