From 7154d3b11dc9db83edfcbd4eebeccf68f1b6815a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Tue, 8 Aug 2006 21:03:26 +0000 Subject: [PATCH] Check return values from seteuid, prompted by MIT advisory. Thanks to Tom Yu at MIT, and Michael Calmer and Marcus Meissner at SUSE. Either of CVE-2006-3083 or CVE-2006-3084. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@17872 ec53bebd-3082-4978-b11e-865c3cabbd6b --- appl/ftp/ftpd/ftpd.c | 50 ++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/appl/ftp/ftpd/ftpd.c b/appl/ftp/ftpd/ftpd.c index cc9b791bc..e79f395e4 100644 --- a/appl/ftp/ftpd/ftpd.c +++ b/appl/ftp/ftpd/ftpd.c @@ -138,9 +138,9 @@ static int handleoobcmd(void); static int checkuser (char *, char *); static int checkaccess (char *); static FILE *dataconn (const char *, off_t, const char *); -static void dolog (struct sockaddr *sa, int len); +static void dolog (struct sockaddr *, int); static void end_login (void); -static FILE *getdatasock (const char *); +static FILE *getdatasock (const char *, int); static char *gunique (char *); static RETSIGTYPE lostconn (int); static int receive_data (FILE *, FILE *); @@ -835,7 +835,8 @@ static void end_login(void) { - seteuid((uid_t)0); + if (seteuid((uid_t)0) < 0) + fatal("Failed to seteuid"); if (logged_in) ftpd_logwtmp(ttyline, "", ""); pw = NULL; @@ -1208,14 +1209,15 @@ done: } static FILE * -getdatasock(const char *mode) +getdatasock(const char *mode, int domain) { int s, t, tries; if (data >= 0) return (fdopen(data, mode)); - seteuid(0); - s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); + s = socket(domain, SOCK_STREAM, 0); if (s < 0) goto bad; socket_set_reuseaddr (s, 1); @@ -1232,7 +1234,8 @@ getdatasock(const char *mode) goto bad; sleep(tries); } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); #ifdef IPTOS_THROUGHPUT socket_set_tos (s, IPTOS_THROUGHPUT); #endif @@ -1240,7 +1243,8 @@ getdatasock(const char *mode) bad: /* Return the real value of errno (close may change it) */ t = errno; - seteuid((uid_t)pw->pw_uid); + if (seteuid((uid_t)pw->pw_uid) < 0) + fatal("Failed to seteuid"); close(s); errno = t; return (NULL); @@ -1271,7 +1275,7 @@ dataconn(const char *name, off_t size, const char *mode) { char sizebuf[32]; FILE *file; - int retry = 0; + int domain, retry = 0; file_size = size; byte_count = 0; @@ -1318,7 +1322,15 @@ dataconn(const char *name, off_t size, const char *mode) if (usedefault) data_dest = his_addr; usedefault = 1; - file = getdatasock(mode); + /* + * Default to using the same socket type as the ctrl address, + * unless we know the type of the data address. + */ + domain = data_dest->sa_family; + if (domain == PF_UNSPEC) + domain = ctrl_addr->sa_family; + + file = getdatasock(mode, domain); if (file == NULL) { char data_addr[256]; @@ -2006,12 +2018,15 @@ pasv(void) 0); socket_set_portrange(pdata, restricted_data_ports, pasv_addr->sa_family); - seteuid(0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); goto pasv_error; } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); len = sizeof(pasv_addr_ss); if (getsockname(pdata, pasv_addr, &len) < 0) goto pasv_error; @@ -2050,12 +2065,15 @@ epsv(char *proto) 0); socket_set_portrange(pdata, restricted_data_ports, pasv_addr->sa_family); - seteuid(0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid)) + fatal("Failed to seteuid"); goto pasv_error; } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); len = sizeof(pasv_addr_ss); if (getsockname(pdata, pasv_addr, &len) < 0) goto pasv_error;