Prevent cross-site forgery attacks on lukemftpd(8) due to splitting
long commands into multiple requests. [09:01] Fix incorrect OpenSSL checks for malformed signatures due to invalid check of return value from EVP_VerifyFinal(), DSA_verify, and DSA_do_verify. [09:02] Security: FreeBSD-SA-09:01.lukemftpd Security: FreeBSD-SA-09:02.openssl Obtained from: NetBSD [SA-09:01] Obtained from: OpenSSL Project [SA-09:02] Approved by: so (simon)
This commit is contained in:
parent
7251cf2c6c
commit
8978d9e7ef
@ -139,7 +139,7 @@ void feat(void);
|
||||
void format_path(char *, const char *);
|
||||
int ftpd_pclose(FILE *);
|
||||
FILE *ftpd_popen(char *[], const char *, int);
|
||||
char *getline(char *, int, FILE *);
|
||||
int getline(char *, int, FILE *);
|
||||
void init_curclass(void);
|
||||
void logxfer(const char *, off_t, const char *, const char *,
|
||||
const struct timeval *, const char *);
|
||||
|
@ -1363,8 +1363,12 @@ lookup(struct tab *p, const char *cmd)
|
||||
|
||||
/*
|
||||
* getline - a hacked up version of fgets to ignore TELNET escape codes.
|
||||
* `s' is the buffer to read into.
|
||||
* `n' is the 1 less than the size of the buffer, to allow trailing NUL
|
||||
* `iop' is the FILE to read from.
|
||||
* Returns 0 on success, -1 on EOF, -2 if the command was too long.
|
||||
*/
|
||||
char *
|
||||
int
|
||||
getline(char *s, int n, FILE *iop)
|
||||
{
|
||||
int c;
|
||||
@ -1379,7 +1383,7 @@ getline(char *s, int n, FILE *iop)
|
||||
if (ftpd_debug)
|
||||
syslog(LOG_DEBUG, "command: %s", s);
|
||||
tmpline[0] = '\0';
|
||||
return(s);
|
||||
return(0);
|
||||
}
|
||||
if (c == 0)
|
||||
tmpline[0] = '\0';
|
||||
@ -1418,11 +1422,25 @@ getline(char *s, int n, FILE *iop)
|
||||
}
|
||||
}
|
||||
*cs++ = c;
|
||||
if (--n <= 0 || c == '\n')
|
||||
if (--n <= 0) {
|
||||
/*
|
||||
* If command doesn't fit into buffer, discard the
|
||||
* rest of the command and indicate truncation.
|
||||
* This prevents the command to be split up into
|
||||
* multiple commands.
|
||||
*/
|
||||
if (ftpd_debug)
|
||||
syslog(LOG_DEBUG,
|
||||
"command too long, last char: %d", c);
|
||||
while (c != '\n' && (c = getc(iop)) != EOF)
|
||||
continue;
|
||||
return (-2);
|
||||
}
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
if (c == EOF && cs == s)
|
||||
return (NULL);
|
||||
return (-1);
|
||||
*cs++ = '\0';
|
||||
if (ftpd_debug) {
|
||||
if ((curclass.type != CLASS_GUEST &&
|
||||
@ -1444,7 +1462,7 @@ getline(char *s, int n, FILE *iop)
|
||||
syslog(LOG_DEBUG, "command: %.*s", len, s);
|
||||
}
|
||||
}
|
||||
return (s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1458,15 +1476,20 @@ ftp_handle_line(char *cp)
|
||||
void
|
||||
ftp_loop(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
(void) alarm(curclass.timeout);
|
||||
if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
|
||||
ret = getline(cbuf, sizeof(cbuf)-1, stdin);
|
||||
(void) alarm(0);
|
||||
if (ret == -1) {
|
||||
reply(221, "You could at least say goodbye.");
|
||||
dologout(0);
|
||||
} else if (ret == -2) {
|
||||
reply(500, "Command too long.");
|
||||
} else {
|
||||
ftp_handle_line(cbuf);
|
||||
}
|
||||
(void) alarm(0);
|
||||
ftp_handle_line(cbuf);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ftpd.c,v 1.176 2006/05/09 20:18:06 mrg Exp $ */
|
||||
/* $NetBSD: ftpd.c,v 1.187 2008/09/13 03:30:35 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
|
||||
@ -2896,6 +2896,7 @@ static int
|
||||
handleoobcmd()
|
||||
{
|
||||
char *cp;
|
||||
int ret;
|
||||
|
||||
if (!urgflag)
|
||||
return (0);
|
||||
@ -2904,9 +2905,14 @@ handleoobcmd()
|
||||
if (!transflag)
|
||||
return (0);
|
||||
cp = tmpline;
|
||||
if (getline(cp, sizeof(tmpline), stdin) == NULL) {
|
||||
ret = getline(cp, sizeof(tmpline)-1, stdin);
|
||||
if (ret == -1) {
|
||||
reply(221, "You could at least say goodbye.");
|
||||
dologout(0);
|
||||
} else if (ret == -2) {
|
||||
/* Ignore truncated command */
|
||||
/* XXX: abort xfer with "500 command too long", & return 1 ? */
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Manually parse OOB commands, because we can't
|
||||
|
@ -2038,7 +2038,7 @@ int MAIN(int argc, char **argv)
|
||||
{
|
||||
ret=RSA_verify(NID_md5_sha1, buf,36, buf2,
|
||||
rsa_num, rsa_key[j]);
|
||||
if (ret == 0)
|
||||
if (ret <= 0)
|
||||
{
|
||||
BIO_printf(bio_err,
|
||||
"RSA verify failure\n");
|
||||
|
@ -285,7 +285,7 @@ int MAIN(int argc, char **argv)
|
||||
pkey = NETSCAPE_SPKI_get_pubkey(spki);
|
||||
if(verify) {
|
||||
i = NETSCAPE_SPKI_verify(spki, pkey);
|
||||
if(i) BIO_printf(bio_err, "Signature OK\n");
|
||||
if (i > 0) BIO_printf(bio_err, "Signature OK\n");
|
||||
else {
|
||||
BIO_printf(bio_err, "Signature Failure\n");
|
||||
ERR_print_errors(bio_err);
|
||||
|
@ -266,7 +266,7 @@ static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X
|
||||
|
||||
ret=0;
|
||||
end:
|
||||
if (i)
|
||||
if (i > 0)
|
||||
{
|
||||
fprintf(stdout,"OK\n");
|
||||
ret=1;
|
||||
@ -367,4 +367,3 @@ static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx)
|
||||
ERR_clear_error();
|
||||
return(ok);
|
||||
}
|
||||
|
||||
|
@ -1144,7 +1144,7 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
|
||||
/* NOTE: this certificate can/should be self signed, unless it was
|
||||
* a certificate request in which case it is not. */
|
||||
X509_STORE_CTX_set_cert(&xsc,x);
|
||||
if (!reqfile && !X509_verify_cert(&xsc))
|
||||
if (!reqfile && X509_verify_cert(&xsc) <= 0)
|
||||
goto end;
|
||||
|
||||
if (!X509_check_private_key(xca,pkey))
|
||||
|
@ -1044,7 +1044,7 @@ int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data)
|
||||
|
||||
i=ssl_verify_cert_chain(s,sk);
|
||||
|
||||
if ((s->verify_mode != SSL_VERIFY_NONE) && (!i))
|
||||
if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0))
|
||||
{
|
||||
SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||
goto err;
|
||||
|
@ -1054,7 +1054,7 @@ static int request_certificate(SSL *s)
|
||||
|
||||
i=ssl_verify_cert_chain(s,sk);
|
||||
|
||||
if (i) /* we like the packet, now check the chksum */
|
||||
if (i > 0) /* we like the packet, now check the chksum */
|
||||
{
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_PKEY *pkey=NULL;
|
||||
@ -1083,7 +1083,7 @@ static int request_certificate(SSL *s)
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
if (i)
|
||||
if (i > 0)
|
||||
{
|
||||
if (s->session->peer != NULL)
|
||||
X509_free(s->session->peer);
|
||||
|
@ -883,7 +883,7 @@ int ssl3_get_server_certificate(SSL *s)
|
||||
}
|
||||
|
||||
i=ssl_verify_cert_chain(s,sk);
|
||||
if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)
|
||||
if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
|
||||
#ifndef OPENSSL_NO_KRB5
|
||||
&& (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
|
||||
!= (SSL_aKRB5|SSL_kKRB5)
|
||||
@ -1368,7 +1368,7 @@ int ssl3_get_key_exchange(SSL *s)
|
||||
EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_VerifyUpdate(&md_ctx,param,param_len);
|
||||
if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey))
|
||||
if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
|
||||
{
|
||||
/* bad signature */
|
||||
al=SSL_AD_DECRYPT_ERROR;
|
||||
@ -1386,7 +1386,7 @@ int ssl3_get_key_exchange(SSL *s)
|
||||
EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
|
||||
EVP_VerifyUpdate(&md_ctx,param,param_len);
|
||||
if (!EVP_VerifyFinal(&md_ctx,p,(int)n,pkey))
|
||||
if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
|
||||
{
|
||||
/* bad signature */
|
||||
al=SSL_AD_DECRYPT_ERROR;
|
||||
|
@ -2481,7 +2481,7 @@ int ssl3_get_client_certificate(SSL *s)
|
||||
else
|
||||
{
|
||||
i=ssl_verify_cert_chain(s,sk);
|
||||
if (!i)
|
||||
if (i <= 0)
|
||||
{
|
||||
al=ssl_verify_alarm_type(s->verify_result);
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
|
||||
|
@ -2072,7 +2072,7 @@ static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
|
||||
|
||||
if (cb_arg->proxy_auth)
|
||||
{
|
||||
if (ok)
|
||||
if (ok > 0)
|
||||
{
|
||||
const char *cond_end = NULL;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user