Module Name:    src
Committed By:   lukem
Date:           Sat Sep  2 12:16:29 UTC 2023

Modified Files:
        src/libexec/ftpd: ftpd.c version.h

Log Message:
ftpd: improve seteuid error handling

Handle seteuid() failures. Per suggestion by Simon Josefsson.
Consistent logging and fatal exit if uid/gid switching fails.
Log correct errno if dataconn() fails.


To generate a diff of this commit:
cvs rdiff -u -r1.206 -r1.207 src/libexec/ftpd/ftpd.c
cvs rdiff -u -r1.77 -r1.78 src/libexec/ftpd/version.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/ftpd/ftpd.c
diff -u src/libexec/ftpd/ftpd.c:1.206 src/libexec/ftpd/ftpd.c:1.207
--- src/libexec/ftpd/ftpd.c:1.206	Sat Jul  3 14:59:49 2021
+++ src/libexec/ftpd/ftpd.c	Sat Sep  2 12:16:29 2023
@@ -1,7 +1,7 @@
-/*	$NetBSD: ftpd.c,v 1.206 2021/07/03 14:59:49 christos Exp $	*/
+/*	$NetBSD: ftpd.c,v 1.207 2023/09/02 12:16:29 lukem Exp $	*/
 
 /*
- * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2023 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -97,7 +97,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 19
 #if 0
 static char sccsid[] = "@(#)ftpd.c	8.5 (Berkeley) 4/28/95";
 #else
-__RCSID("$NetBSD: ftpd.c,v 1.206 2021/07/03 14:59:49 christos Exp $");
+__RCSID("$NetBSD: ftpd.c,v 1.207 2023/09/02 12:16:29 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -1300,7 +1300,12 @@ end_login(void)
 	quietmessages = 0;
 	gidcount = 0;
 	curclass.type = CLASS_REAL;
-	(void) seteuid((uid_t)0);
+	if (!dropprivs) {
+		if (seteuid((uid_t)0) < 0) {
+			syslog(LOG_NOTICE, "end_login: can't seteuid 0: %m");
+			fatal("Can't reset privileges.");
+		}
+	}
 #ifdef	LOGIN_CAP
 	setusercontext(NULL, getpwuid(0), 0,
 		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
@@ -1441,8 +1446,8 @@ do_pass(int pass_checked, int pass_rval,
 
 	login_attempts = 0;		/* this time successful */
 	if (setegid((gid_t)pw->pw_gid) < 0) {
-		reply(550, "Can't set gid.");
-		goto bad;
+		syslog(LOG_NOTICE, "user %s: can't setegid: %m", pw->pw_name);
+		fatal("Can't drop privileges.");
 	}
 #ifdef	LOGIN_CAP
 	if ((lc = login_getpwclass(pw)) != NULL) {
@@ -1615,17 +1620,17 @@ do_pass(int pass_checked, int pass_rval,
 	    ntohs(ctrl_addr.su_port) > IPPORT_RESERVED + 1)) {
 		dropprivs++;
 		if (setgid((gid_t)pw->pw_gid) < 0) {
-			reply(550, "Can't set gid.");
-			goto bad_perms;
+			syslog(LOG_NOTICE, "user %s: can't setgid: %m", pw->pw_name);
+			fatal("Can't drop privileges.");
 		}
 		if (setuid((uid_t)pw->pw_uid) < 0) {
-			reply(550, "Can't set uid.");
-			goto bad_perms;
+			syslog(LOG_NOTICE, "user %s: can't setuid: %m", pw->pw_name);
+			fatal("Can't drop privileges.");
 		}
 	} else {
 		if (seteuid((uid_t)pw->pw_uid) < 0) {
-			reply(550, "Can't set uid.");
-			goto bad_perms;
+			syslog(LOG_NOTICE, "user %s: can't seteuid: %m", pw->pw_name);
+			fatal("Can't drop privileges.");
 		}
 	}
 	setenv("HOME", homedir, 1);
@@ -1684,11 +1689,6 @@ do_pass(int pass_checked, int pass_rval,
 #endif
 			/* Forget all about it... */
 	end_login();
-	return;
-
-bad_perms:
-	syslog(LOG_NOTICE, "user %s: can't setuid/gid: %m", pw->pw_name);
-	fatal("Can't drop privileges.");
 }
 
 void
@@ -1924,8 +1924,12 @@ getdatasock(const char *fmode)
 	on = 1;
 	if (data >= 0)
 		return (fdopen(data, fmode));
-	if (! dropprivs)
-		(void) seteuid((uid_t)0);
+	if (! dropprivs) {
+		if (seteuid((uid_t)0) < 0) {
+			syslog(LOG_NOTICE, "getdatasock: can't seteuid 0: %m");
+			fatal("Can't reset privileges.");
+		}
+	}
 	s = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
 	if (s < 0)
 		goto bad;
@@ -1960,8 +1964,12 @@ getdatasock(const char *fmode)
 			goto bad;
 		sleep(tries);
 	}
-	if (! dropprivs)
-		(void) seteuid((uid_t)pw->pw_uid);
+	if (! dropprivs) {
+		if (seteuid((uid_t)pw->pw_uid) < 0) {
+			syslog(LOG_NOTICE, "user %s: can't seteuid: %m", pw->pw_name);
+			fatal("Can't drop privileges.");
+		}
+	}
 #ifdef IP_TOS
 	if (!mapped && ctrl_addr.su_family == AF_INET) {
 		on = IPTOS_THROUGHPUT;
@@ -1974,8 +1982,12 @@ getdatasock(const char *fmode)
  bad:
 		/* Return the real value of errno (close may change it) */
 	t = errno;
-	if (! dropprivs)
-		(void) seteuid((uid_t)pw->pw_uid);
+	if (! dropprivs) {
+		if (seteuid((uid_t)pw->pw_uid) < 0) {
+			syslog(LOG_NOTICE, "user %s: can't seteuid: %m", pw->pw_name);
+			fatal("Can't drop privileges.");
+		}
+	}
 	if (s >= 0)
 		(void) close(s);
 	errno = t;
@@ -2048,13 +2060,13 @@ dataconn(const char *name, off_t size, c
 		if (file == NULL) {
 			char hbuf[NI_MAXHOST];
 			char pbuf[NI_MAXSERV];
-
+			conerrno = errno;
 			if (getnameinfo((struct sockaddr *)&data_source.si_su,
 			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
 			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV))
 				strlcpy(hbuf, "?", sizeof(hbuf));
 			reply(425, "Can't create data socket (%s,%s): %s.",
-			      hbuf, pbuf, strerror(errno));
+			      hbuf, pbuf, strerror(conerrno));
 			return (NULL);
 		}
 		data = fileno(file);

Index: src/libexec/ftpd/version.h
diff -u src/libexec/ftpd/version.h:1.77 src/libexec/ftpd/version.h:1.78
--- src/libexec/ftpd/version.h:1.77	Sat Jul  4 01:20:42 2020
+++ src/libexec/ftpd/version.h	Sat Sep  2 12:16:29 2023
@@ -1,6 +1,6 @@
-/*	$NetBSD: version.h,v 1.77 2020/07/04 01:20:42 lukem Exp $	*/
+/*	$NetBSD: version.h,v 1.78 2023/09/02 12:16:29 lukem Exp $	*/
 /*-
- * Copyright (c) 1999-2020 The NetBSD Foundation, Inc.
+ * Copyright (c) 1999-2023 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -29,5 +29,5 @@
  */
 
 #ifndef FTPD_VERSION
-#define	FTPD_VERSION	"NetBSD-ftpd 20200615"
+#define	FTPD_VERSION	"NetBSD-ftpd 20230902"
 #endif

Reply via email to