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
This commit is contained in:
@@ -138,9 +138,9 @@ static int handleoobcmd(void);
|
|||||||
static int checkuser (char *, char *);
|
static int checkuser (char *, char *);
|
||||||
static int checkaccess (char *);
|
static int checkaccess (char *);
|
||||||
static FILE *dataconn (const char *, off_t, const 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 void end_login (void);
|
||||||
static FILE *getdatasock (const char *);
|
static FILE *getdatasock (const char *, int);
|
||||||
static char *gunique (char *);
|
static char *gunique (char *);
|
||||||
static RETSIGTYPE lostconn (int);
|
static RETSIGTYPE lostconn (int);
|
||||||
static int receive_data (FILE *, FILE *);
|
static int receive_data (FILE *, FILE *);
|
||||||
@@ -835,7 +835,8 @@ static void
|
|||||||
end_login(void)
|
end_login(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
seteuid((uid_t)0);
|
if (seteuid((uid_t)0) < 0)
|
||||||
|
fatal("Failed to seteuid");
|
||||||
if (logged_in)
|
if (logged_in)
|
||||||
ftpd_logwtmp(ttyline, "", "");
|
ftpd_logwtmp(ttyline, "", "");
|
||||||
pw = NULL;
|
pw = NULL;
|
||||||
@@ -1208,14 +1209,15 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
getdatasock(const char *mode)
|
getdatasock(const char *mode, int domain)
|
||||||
{
|
{
|
||||||
int s, t, tries;
|
int s, t, tries;
|
||||||
|
|
||||||
if (data >= 0)
|
if (data >= 0)
|
||||||
return (fdopen(data, mode));
|
return (fdopen(data, mode));
|
||||||
seteuid(0);
|
if (seteuid(0) < 0)
|
||||||
s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
|
fatal("Failed to seteuid");
|
||||||
|
s = socket(domain, SOCK_STREAM, 0);
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
socket_set_reuseaddr (s, 1);
|
socket_set_reuseaddr (s, 1);
|
||||||
@@ -1232,7 +1234,8 @@ getdatasock(const char *mode)
|
|||||||
goto bad;
|
goto bad;
|
||||||
sleep(tries);
|
sleep(tries);
|
||||||
}
|
}
|
||||||
seteuid(pw->pw_uid);
|
if (seteuid(pw->pw_uid) < 0)
|
||||||
|
fatal("Failed to seteuid");
|
||||||
#ifdef IPTOS_THROUGHPUT
|
#ifdef IPTOS_THROUGHPUT
|
||||||
socket_set_tos (s, IPTOS_THROUGHPUT);
|
socket_set_tos (s, IPTOS_THROUGHPUT);
|
||||||
#endif
|
#endif
|
||||||
@@ -1240,7 +1243,8 @@ getdatasock(const char *mode)
|
|||||||
bad:
|
bad:
|
||||||
/* Return the real value of errno (close may change it) */
|
/* Return the real value of errno (close may change it) */
|
||||||
t = errno;
|
t = errno;
|
||||||
seteuid((uid_t)pw->pw_uid);
|
if (seteuid((uid_t)pw->pw_uid) < 0)
|
||||||
|
fatal("Failed to seteuid");
|
||||||
close(s);
|
close(s);
|
||||||
errno = t;
|
errno = t;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -1271,7 +1275,7 @@ dataconn(const char *name, off_t size, const char *mode)
|
|||||||
{
|
{
|
||||||
char sizebuf[32];
|
char sizebuf[32];
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int retry = 0;
|
int domain, retry = 0;
|
||||||
|
|
||||||
file_size = size;
|
file_size = size;
|
||||||
byte_count = 0;
|
byte_count = 0;
|
||||||
@@ -1318,7 +1322,15 @@ dataconn(const char *name, off_t size, const char *mode)
|
|||||||
if (usedefault)
|
if (usedefault)
|
||||||
data_dest = his_addr;
|
data_dest = his_addr;
|
||||||
usedefault = 1;
|
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) {
|
if (file == NULL) {
|
||||||
char data_addr[256];
|
char data_addr[256];
|
||||||
|
|
||||||
@@ -2006,12 +2018,15 @@ pasv(void)
|
|||||||
0);
|
0);
|
||||||
socket_set_portrange(pdata, restricted_data_ports,
|
socket_set_portrange(pdata, restricted_data_ports,
|
||||||
pasv_addr->sa_family);
|
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) {
|
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;
|
goto pasv_error;
|
||||||
}
|
}
|
||||||
seteuid(pw->pw_uid);
|
if (seteuid(pw->pw_uid) < 0)
|
||||||
|
fatal("Failed to seteuid");
|
||||||
len = sizeof(pasv_addr_ss);
|
len = sizeof(pasv_addr_ss);
|
||||||
if (getsockname(pdata, pasv_addr, &len) < 0)
|
if (getsockname(pdata, pasv_addr, &len) < 0)
|
||||||
goto pasv_error;
|
goto pasv_error;
|
||||||
@@ -2050,12 +2065,15 @@ epsv(char *proto)
|
|||||||
0);
|
0);
|
||||||
socket_set_portrange(pdata, restricted_data_ports,
|
socket_set_portrange(pdata, restricted_data_ports,
|
||||||
pasv_addr->sa_family);
|
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) {
|
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;
|
goto pasv_error;
|
||||||
}
|
}
|
||||||
seteuid(pw->pw_uid);
|
if (seteuid(pw->pw_uid) < 0)
|
||||||
|
fatal("Failed to seteuid");
|
||||||
len = sizeof(pasv_addr_ss);
|
len = sizeof(pasv_addr_ss);
|
||||||
if (getsockname(pdata, pasv_addr, &len) < 0)
|
if (getsockname(pdata, pasv_addr, &len) < 0)
|
||||||
goto pasv_error;
|
goto pasv_error;
|
||||||
|
Reference in New Issue
Block a user