mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Limit the nesting level of I/O filters.
* until/iobuf.c (MAX_NESTING_FILTER): New. (iobuf_push_filter2): Limit the nesting level. -- This is a more general fix for the nested compression packet bug. In particular this helps g10/import.c:read_block to stop pushing compression filters onto an iobuf stream. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
d90a1d2340
commit
f10b184e48
75
util/iobuf.c
75
util/iobuf.c
@ -27,7 +27,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -41,13 +41,13 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "dynload.h"
|
#include "dynload.h"
|
||||||
#include "iobuf.h"
|
#include "iobuf.h"
|
||||||
|
|
||||||
#ifdef __VMS
|
#ifdef __VMS
|
||||||
# include "vms.h"
|
# include "vms.h"
|
||||||
# define open open_vms
|
# define open open_vms
|
||||||
#endif /* def __VMS */
|
#endif /* def __VMS */
|
||||||
|
|
||||||
/* The size of the internal buffers.
|
/* The size of the internal buffers.
|
||||||
NOTE: If you change this value you MUST also adjust the regression
|
NOTE: If you change this value you MUST also adjust the regression
|
||||||
test "armored_key_8192" and "nopad_armored_msg" in armor.test! */
|
test "armored_key_8192" and "nopad_armored_msg" in armor.test! */
|
||||||
#define IOBUF_BUFFER_SIZE 8192
|
#define IOBUF_BUFFER_SIZE 8192
|
||||||
@ -55,6 +55,11 @@
|
|||||||
|
|
||||||
#undef FILE_FILTER_USES_STDIO
|
#undef FILE_FILTER_USES_STDIO
|
||||||
|
|
||||||
|
/* To avoid a potential DoS with compression packets we better limit
|
||||||
|
the number of filters in a chain. */
|
||||||
|
#define MAX_NESTING_FILTER 64
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
#define USE_SETMODE 1
|
#define USE_SETMODE 1
|
||||||
#endif
|
#endif
|
||||||
@ -76,8 +81,8 @@ typedef struct {
|
|||||||
} file_filter_ctx_t ;
|
} file_filter_ctx_t ;
|
||||||
#else
|
#else
|
||||||
#define my_fileno(a) (a)
|
#define my_fileno(a) (a)
|
||||||
#define my_fopen_ro(a,b) fd_cache_open ((a),(b))
|
#define my_fopen_ro(a,b) fd_cache_open ((a),(b))
|
||||||
#define my_fopen(a,b) direct_open ((a),(b))
|
#define my_fopen(a,b) direct_open ((a),(b))
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
typedef HANDLE FILEP_OR_FD;
|
typedef HANDLE FILEP_OR_FD;
|
||||||
#define INVALID_FP ((HANDLE)-1)
|
#define INVALID_FP ((HANDLE)-1)
|
||||||
@ -99,7 +104,7 @@ typedef struct {
|
|||||||
char fname[1]; /* name of the file */
|
char fname[1]; /* name of the file */
|
||||||
} file_filter_ctx_t ;
|
} file_filter_ctx_t ;
|
||||||
|
|
||||||
struct close_cache_s {
|
struct close_cache_s {
|
||||||
struct close_cache_s *next;
|
struct close_cache_s *next;
|
||||||
FILEP_OR_FD fp;
|
FILEP_OR_FD fp;
|
||||||
char fname[1];
|
char fname[1];
|
||||||
@ -153,7 +158,7 @@ fd_cache_strcmp (const char *a, const char *b)
|
|||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
for (; *a && *b; a++, b++)
|
for (; *a && *b; a++, b++)
|
||||||
{
|
{
|
||||||
if (*a != *b && !((*a == '/' && *b == '\\')
|
if (*a != *b && !((*a == '/' && *b == '\\')
|
||||||
|| (*a == '\\' && *b == '/')) )
|
|| (*a == '\\' && *b == '/')) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -295,7 +300,7 @@ direct_open (const char *fname, const char *mode)
|
|||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
int rc = stat( fname, &buf );
|
int rc = stat( fname, &buf );
|
||||||
|
|
||||||
/* Don't allow iobufs on directories */
|
/* Don't allow iobufs on directories */
|
||||||
if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
|
if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
|
||||||
return __set_errno( EISDIR );
|
return __set_errno( EISDIR );
|
||||||
@ -308,7 +313,7 @@ direct_open (const char *fname, const char *mode)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instead of closing an FD we keep it open and cache it for later reuse
|
* Instead of closing an FD we keep it open and cache it for later reuse
|
||||||
* Note that this caching strategy only works if the process does not chdir.
|
* Note that this caching strategy only works if the process does not chdir.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -471,8 +476,8 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
|
|||||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||||
assert( size ); /* need a buffer */
|
assert( size ); /* need a buffer */
|
||||||
if ( a->eof_seen) {
|
if ( a->eof_seen) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
*ret_len = 0;
|
*ret_len = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
@ -606,8 +611,8 @@ sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
|
|||||||
if( control == IOBUFCTRL_UNDERFLOW ) {
|
if( control == IOBUFCTRL_UNDERFLOW ) {
|
||||||
assert( size ); /* need a buffer */
|
assert( size ); /* need a buffer */
|
||||||
if ( a->eof_seen) {
|
if ( a->eof_seen) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
*ret_len = 0;
|
*ret_len = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int nread;
|
int nread;
|
||||||
@ -1076,7 +1081,7 @@ check_special_filename ( const char *fname )
|
|||||||
fname += 2;
|
fname += 2;
|
||||||
for (i=0; digitp (fname+i); i++ )
|
for (i=0; digitp (fname+i); i++ )
|
||||||
;
|
;
|
||||||
if ( !fname[i] )
|
if ( !fname[i] )
|
||||||
return atoi (fname);
|
return atoi (fname);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -1189,7 +1194,7 @@ iobuf_sockopen ( int fd, const char *mode )
|
|||||||
sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
|
log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
|
||||||
iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
|
iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
|
||||||
#else
|
#else
|
||||||
a = iobuf_fdopen (fd, mode);
|
a = iobuf_fdopen (fd, mode);
|
||||||
#endif
|
#endif
|
||||||
@ -1233,7 +1238,7 @@ iobuf_create( const char *fname )
|
|||||||
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
||||||
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno,
|
log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno,
|
||||||
a->desc?a->desc:"?" );
|
a->desc?a->desc:"?" );
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
@ -1267,7 +1272,7 @@ iobuf_append( const char *fname )
|
|||||||
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
||||||
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno,
|
log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno,
|
||||||
a->desc?a->desc:"?" );
|
a->desc?a->desc:"?" );
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
@ -1296,7 +1301,7 @@ iobuf_openrw( const char *fname )
|
|||||||
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
|
||||||
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno,
|
log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno,
|
||||||
a->desc?a->desc:"?");
|
a->desc?a->desc:"?");
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
@ -1309,7 +1314,7 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
|
|||||||
if ( cmd == 1 ) { /* keep system filepointer/descriptor open */
|
if ( cmd == 1 ) { /* keep system filepointer/descriptor open */
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
|
log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
|
||||||
a? a->no:-1, a?a->subno:-1,
|
a? a->no:-1, a?a->subno:-1,
|
||||||
a&&a->desc?a->desc:"?", intval );
|
a&&a->desc?a->desc:"?", intval );
|
||||||
for( ; a; a = a->chain )
|
for( ; a; a = a->chain )
|
||||||
if( !a->chain && a->filter == file_filter ) {
|
if( !a->chain && a->filter == file_filter ) {
|
||||||
@ -1339,7 +1344,7 @@ iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
|
|||||||
else if ( cmd == 3 ) { /* disallow/allow caching */
|
else if ( cmd == 3 ) { /* disallow/allow caching */
|
||||||
if( DBG_IOBUF )
|
if( DBG_IOBUF )
|
||||||
log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
|
log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
|
||||||
a? a->no:-1, a?a->subno:-1,
|
a? a->no:-1, a?a->subno:-1,
|
||||||
a&&a->desc?a->desc:"?", intval );
|
a&&a->desc?a->desc:"?", intval );
|
||||||
for( ; a; a = a->chain )
|
for( ; a; a = a->chain )
|
||||||
if( !a->chain && a->filter == file_filter ) {
|
if( !a->chain && a->filter == file_filter ) {
|
||||||
@ -1403,6 +1408,12 @@ iobuf_push_filter2( IOBUF a,
|
|||||||
|
|
||||||
if( a->use == 2 && (rc=iobuf_flush(a)) )
|
if( a->use == 2 && (rc=iobuf_flush(a)) )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
if (a->subno >= MAX_NESTING_FILTER) {
|
||||||
|
log_error ("i/o filter too deeply nested - corrupted data?\n");
|
||||||
|
return G10ERR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* make a copy of the current stream, so that
|
/* make a copy of the current stream, so that
|
||||||
* A is the new stream and B the original one.
|
* A is the new stream and B the original one.
|
||||||
* The contents of the buffers are transferred to the
|
* The contents of the buffers are transferred to the
|
||||||
@ -1449,7 +1460,7 @@ iobuf_push_filter2( IOBUF a,
|
|||||||
f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
|
f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
|
||||||
|
|
||||||
if( DBG_IOBUF ) {
|
if( DBG_IOBUF ) {
|
||||||
log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno,
|
log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno,
|
||||||
a->desc?a->desc:"?" );
|
a->desc?a->desc:"?" );
|
||||||
print_chain( a );
|
print_chain( a );
|
||||||
}
|
}
|
||||||
@ -1921,7 +1932,7 @@ iobuf_get_filelength (IOBUF a, int *overflow )
|
|||||||
if (overflow)
|
if (overflow)
|
||||||
*overflow = 0;
|
*overflow = 0;
|
||||||
|
|
||||||
if (a->directfp)
|
if (a->directfp)
|
||||||
{
|
{
|
||||||
FILE *fp = a->directfp;
|
FILE *fp = a->directfp;
|
||||||
|
|
||||||
@ -1949,14 +1960,14 @@ iobuf_get_filelength (IOBUF a, int *overflow )
|
|||||||
|
|
||||||
#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
|
#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
|
||||||
ulong size;
|
ulong size;
|
||||||
static int (* __stdcall get_file_size_ex)
|
static int (* __stdcall get_file_size_ex)
|
||||||
(void *handle, LARGE_INTEGER *size);
|
(void *handle, LARGE_INTEGER *size);
|
||||||
static int get_file_size_ex_initialized;
|
static int get_file_size_ex_initialized;
|
||||||
|
|
||||||
if (!get_file_size_ex_initialized)
|
if (!get_file_size_ex_initialized)
|
||||||
{
|
{
|
||||||
void *handle;
|
void *handle;
|
||||||
|
|
||||||
handle = dlopen ("kernel32.dll", RTLD_LAZY);
|
handle = dlopen ("kernel32.dll", RTLD_LAZY);
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
@ -1974,14 +1985,14 @@ iobuf_get_filelength (IOBUF a, int *overflow )
|
|||||||
return a proper error in case a file is larger than
|
return a proper error in case a file is larger than
|
||||||
4GB. */
|
4GB. */
|
||||||
LARGE_INTEGER size;
|
LARGE_INTEGER size;
|
||||||
|
|
||||||
if (get_file_size_ex (fp, &size))
|
if (get_file_size_ex (fp, &size))
|
||||||
{
|
{
|
||||||
if (!size.u.HighPart)
|
if (!size.u.HighPart)
|
||||||
return size.u.LowPart;
|
return size.u.LowPart;
|
||||||
if (overflow)
|
if (overflow)
|
||||||
*overflow = 1;
|
*overflow = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2007,7 +2018,7 @@ iobuf_get_filelength (IOBUF a, int *overflow )
|
|||||||
|
|
||||||
/* Return the file descriptor of the underlying file or -1 if it is
|
/* Return the file descriptor of the underlying file or -1 if it is
|
||||||
not available. */
|
not available. */
|
||||||
int
|
int
|
||||||
iobuf_get_fd (IOBUF a)
|
iobuf_get_fd (IOBUF a)
|
||||||
{
|
{
|
||||||
if (a->directfp)
|
if (a->directfp)
|
||||||
@ -2260,7 +2271,7 @@ iobuf_translate_file_handle ( int fd, int for_write )
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if ( fd <= 2 )
|
if ( fd <= 2 )
|
||||||
return fd; /* do not do this for error, stdin, stdout, stderr */
|
return fd; /* do not do this for error, stdin, stdout, stderr */
|
||||||
|
|
||||||
@ -2281,17 +2292,17 @@ static int
|
|||||||
translate_file_handle ( int fd, int for_write )
|
translate_file_handle ( int fd, int for_write )
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef FILE_FILTER_USES_STDIO
|
#ifdef FILE_FILTER_USES_STDIO
|
||||||
fd = iobuf_translate_file_handle (fd, for_write);
|
fd = iobuf_translate_file_handle (fd, for_write);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if ( fd == 0 )
|
if ( fd == 0 )
|
||||||
x = (int)GetStdHandle (STD_INPUT_HANDLE);
|
x = (int)GetStdHandle (STD_INPUT_HANDLE);
|
||||||
else if (fd == 1)
|
else if (fd == 1)
|
||||||
x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
|
x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
|
||||||
else if (fd == 2)
|
else if (fd == 2)
|
||||||
x = (int)GetStdHandle (STD_ERROR_HANDLE);
|
x = (int)GetStdHandle (STD_ERROR_HANDLE);
|
||||||
else
|
else
|
||||||
x = fd;
|
x = fd;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user