From 900b0eb96e588bdd1bb99a25496ed7be59897d2c Mon Sep 17 00:00:00 2001 From: cameronrich Date: Sun, 18 Feb 2007 08:14:01 +0000 Subject: [PATCH] fixed memory leak git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@63 9a5d90b5-6617-0410-8a86-bb477d3ed2e3 --- CHANGELOG | 9 ++++++--- Makefile | 11 +++-------- config/Config.in | 1 + config/makefile.conf | 6 +++++- httpd/README | 2 +- httpd/axhttpd.c | 45 +++++++++++++++++++++++--------------------- httpd/proc.c | 13 +++++++++---- ssl/crypto_misc.c | 13 ++----------- ssl/os_port.c | 45 ++++++++++++++++++++++++++++++++++++-------- ssl/os_port.h | 14 +++++++++----- ssl/test/ssltest.c | 23 +--------------------- www/bin/.htaccess | 2 ++ 12 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 www/bin/.htaccess diff --git a/CHANGELOG b/CHANGELOG index 568d44076..fed344cdb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,13 +6,16 @@ Changes since 1.0.0 * -DCYGWIN replaced with -DCONFIG_PLATFORM_CYGWIN (and the same for solaris). * removed "-noextern" option in Swig. Fixed some other warnings in Win32. * SSLCTX changed to SSL_CTX (to be consistent with openssl). +* malloc()/open() etc call abort() on failure. +* Fixed a memory leak in directory listings. axhttpd Changes * main.c now becomes axhttpd.c. * Header file issue fixed (in mime_types.c). * chroot() now used for better security. -* Basic authentication implemented (with .htpasswd). -* SSL access/denial protection implemented (with .htaccess). -* Directory access protection implemented (with .htaccess). +* Basic authentication implemented (via .htpasswd). +* SSL access/denial protection implemented (via .htaccess). +* Directory access protection implemented (via .htaccess). * Can now have more than one CGI file extension in mconf. * "If-Modified-Since" request now handled properly. + diff --git a/Makefile b/Makefile index 6be5fbe5f..e78798ba0 100644 --- a/Makefile +++ b/Makefile @@ -81,14 +81,9 @@ ifdef CONFIG_PERL_BINDINGS -install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'` endif @mkdir -p -m 755 $(PREFIX)/include/axTLS - -install -m 644 ssl/bigint.h $(PREFIX)/include/axTLS - -install -m 644 ssl/bigint_impl.h $(PREFIX)/include/axTLS - -install -m 644 ssl/crypto.h $(PREFIX)/include/axTLS - -install -m 644 ssl/os_port.h $(PREFIX)/include/axTLS - -install -m 644 ssl/bigint.h $(PREFIX)/include/axTLS - -install -m 644 ssl/ssl.h $(PREFIX)/include/axTLS - -install -m 644 ssl/tls1.h $(PREFIX)/include/axTLS - -install -m 644 ssl/version.h $(PREFIX)/include/axTLS + -install -m 644 ssl/*.h $(PREFIX)/include/axTLS + -rm $(PREFIX)/include/axTLS/cert.h + -rm $(PREFIX)/include/axTLS/private_key.h -install -m 644 config/config.h $(PREFIX)/include/axTLS installclean: diff --git a/config/Config.in b/config/Config.in index de1808d8e..c68e95a66 100644 --- a/config/Config.in +++ b/config/Config.in @@ -117,3 +117,4 @@ source httpd/Config.in source bindings/Config.in source samples/Config.in source ssl/BigIntConfig.in + diff --git a/config/makefile.conf b/config/makefile.conf index ffdf33d88..77a341be3 100644 --- a/config/makefile.conf +++ b/config/makefile.conf @@ -84,11 +84,15 @@ CFLAGS += -DCONFIG_PLATFORM_SOLARIS LDFLAGS += -lsocket -lnsl -lc LDSHARED = -G # Linux/Cygwin -else # Linux +else CFLAGS += -Wall -Wstrict-prototypes -Wshadow LDSHARED = -shared + +# Linux ifndef CONFIG_PLATFORM_CYGWIN CFLAGS += -fPIC + +# Cygwin else CFLAGS += -DCONFIG_PLATFORM_CYGWIN endif diff --git a/httpd/README b/httpd/README index e74f66de0..8ab78cbd3 100644 --- a/httpd/README +++ b/httpd/README @@ -33,7 +33,7 @@ normal http access for a directory needs to be disabled, then put Conversely, use "SSLDenySSL" to deny access to directories via SSL. -An example is in /test_dir/ssl_only and /test_dir/no_ssl. +An example is in /test_dir/no_http and /test_dir/no_ssl. Entire directories can be denied access with a "Deny all" directive (regardless of SSL or authentication). diff --git a/httpd/axhttpd.c b/httpd/axhttpd.c index a8f70e45e..3f6eaba9f 100644 --- a/httpd/axhttpd.c +++ b/httpd/axhttpd.c @@ -53,8 +53,6 @@ static void sigint_cleanup(int sig) { struct serverstruct *sp; struct connstruct *tp; - int i; - while (servers != NULL) { @@ -66,16 +64,20 @@ static void sigint_cleanup(int sig) servers = sp; } - for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) + while (freeconns != NULL) { - if (freeconns == NULL) - break; - tp = freeconns->next; free(freeconns); freeconns = tp; } + while (usedconns != NULL) + { + tp = usedconns->next; + free(usedconns); + usedconns = tp; + } + #if defined(CONFIG_HTTP_HAS_CGI) while (cgiexts) { @@ -129,20 +131,6 @@ int main(int argc, char *argv[]) freeconns->next = tp; } - /* change to webroot for better security */ - if (chroot(webroot)) - { -#ifdef CONFIG_HTTP_VERBOSE - fprintf(stderr, "'%s' is not a directory\n", webroot); -#endif - exit(1); - } - -#ifndef WIN32 - setgid(32767); - setuid(32767); -#endif - if ((active = openlistener(CONFIG_HTTP_PORT)) == -1) { #ifdef CONFIG_HTTP_VERBOSE @@ -179,6 +167,21 @@ int main(int argc, char *argv[]) ssl_version(), CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT); TTY_FLUSH(); #endif + + /* change to webroot for better security */ + if (chroot(webroot)) + { +#ifdef CONFIG_HTTP_VERBOSE + fprintf(stderr, "'%s' is not a directory\n", webroot); +#endif + exit(1); + } + +#ifndef WIN32 + setgid(32767); + setuid(32767); +#endif + #if defined(CONFIG_HTTP_IS_DAEMON) if (fork() > 0) /* parent will die */ exit(0); @@ -560,7 +563,7 @@ static void addconnection(int sd, char *ip, int is_ssl) /* Get ourselves a connstruct */ if (freeconns == NULL) - tp = (struct connstruct *)malloc(sizeof(struct connstruct)); + tp = (struct connstruct *)calloc(1, sizeof(struct connstruct)); else { tp = freeconns; diff --git a/httpd/proc.c b/httpd/proc.c index 9f70fbbaa..753304f76 100644 --- a/httpd/proc.c +++ b/httpd/proc.c @@ -163,9 +163,6 @@ static void procdirlisting(struct connstruct *cn) send_error(cn, 404); return; } - - /* Get rid of the "." */ - readdir(cn->dirp); #endif snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n" @@ -198,6 +195,9 @@ void procdodir(struct connstruct *cn) snprintf(buf, sizeof(buf), "\n"); special_write(cn, buf, strlen(buf)); removeconnection(cn); +#ifndef WIN32 + closedir(cn->dirp); +#endif return; } @@ -430,7 +430,7 @@ void procsendhead(struct connstruct *cn) flags |= O_BINARY; #endif - cn->filedesc = open(cn->actualfile, flags); + cn->filedesc = ax_open(cn->actualfile, flags); if (cn->filedesc == -1) { send_error(cn, 404); @@ -1011,6 +1011,11 @@ static void send_error(struct connstruct *cn, int err) title = "Not Found"; text = title; break; + + default: + title = "Unknown"; + text = "Unknown"; + break; } snprintf(buf, MAXREQUESTLENGTH, "HTTP/1.1 %d %s\n" diff --git a/ssl/crypto_misc.c b/ssl/crypto_misc.c index 6f70665d9..4f4ffa698 100644 --- a/ssl/crypto_misc.c +++ b/ssl/crypto_misc.c @@ -52,13 +52,8 @@ int get_file(const char *filename, uint8_t **buf) int total_bytes = 0; int bytes_read = 0; int filesize; - FILE *stream = fopen(filename, "rb"); + FILE *stream = ax_fopen(filename, "rb"); - if (stream == NULL) - { - return -1; - } - /* Win CE doesn't support stat() */ fseek(stream, 0, SEEK_END); filesize = ftell(stream); @@ -87,11 +82,7 @@ EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size) if (rng_ref_count == 0) { #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) - if ((rng_fd = open("/dev/urandom", O_RDONLY)) < 0) - { - printf(unsupported_str); - exit(1); - } + rng_fd = ax_open("/dev/urandom", O_RDONLY); #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB) if (!CryptAcquireContext(&gCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) diff --git a/ssl/os_port.c b/ssl/os_port.c index 109321e29..e49498907 100644 --- a/ssl/os_port.c +++ b/ssl/os_port.c @@ -23,6 +23,8 @@ */ #include #include +#include +#include #include "os_port.h" #ifdef WIN32 @@ -66,13 +68,20 @@ EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2) #undef open #undef fopen -/* some functions that call abort() on failure */ +static const char * out_of_mem_str = "out of memory"; +static const char * file_open_str = "Could not open file \"%s\""; + +/* + * Some functions that call display some error trace and then call abort(). + * This just makes life much easier on embedded systems, since we're + * suffering major trauma... + */ EXP_FUNC void * STDCALL ax_malloc(size_t s) { void *x; if ((x = malloc(s)) == NULL) - abort(); + exit_now(out_of_mem_str); return x; } @@ -82,7 +91,7 @@ EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s) void *x; if ((x = realloc(y, s)) == NULL) - abort(); + exit_now(out_of_mem_str); return x; } @@ -92,17 +101,20 @@ EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s) void *x; if ((x = calloc(n, s)) == NULL) - abort(); + exit_now(out_of_mem_str); return x; } -EXP_FUNC FILE * STDCALL ax_fopen(const char *name, const char *type) +EXP_FUNC FILE * STDCALL ax_fopen(const char *pathname, const char *type) { FILE *f; - if ((f = fopen(name, type)) == NULL) - abort(); + if ((f = fopen(pathname, type)) == NULL) + { + perror("open: "); + exit_now(file_open_str, pathname); + } return f; } @@ -112,8 +124,25 @@ EXP_FUNC int STDCALL ax_open(const char *pathname, int flags) int x; if ((x = open(pathname, flags)) < 0) - abort(); + { + perror("open: "); + exit_now(file_open_str, pathname); + } return x; } +/** + * This is a call which will deliberately exit an application, but will + * display some information before dying. + */ +void exit_now(const char *format, ...) +{ + va_list argp; + + va_start(argp, format); + vsprintf(stderr, format, argp); + va_end(argp); + abort(); +} + diff --git a/ssl/os_port.h b/ssl/os_port.h index 32e790291..00f4ceb29 100644 --- a/ssl/os_port.h +++ b/ssl/os_port.h @@ -74,7 +74,7 @@ extern "C" { #define random() rand() #define getpid() _getpid() #define snprintf _snprintf -//#define open(A,B) _open(A,B) +#define open(A,B) _open(A,B) #define dup2(A,B) _dup2(A,B) #define unlink(A) _unlink(A) #define close(A) _close(A) @@ -146,14 +146,18 @@ EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2); #define malloc(A) ax_malloc(A) #define realloc(A,B) ax_realloc(A,B) #define calloc(A,B) ax_calloc(A,B) -#define fopen(A,B) ax_fopen(A,B) -#define open(A,B) ax_open(A,B) EXP_FUNC void * STDCALL ax_malloc(size_t s); EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s); EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s); -EXP_FUNC FILE * STDCALL fopen(const char *name, const char *type); -EXP_FUNC int STDCALL open(const char *pathname, int flags); +EXP_FUNC FILE * STDCALL ax_fopen(const char *name, const char *type); +EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); + +#ifdef CONFIG_PLATFORM_LINUX +void exit_now(const char *format, ...) __attribute((noreturn)); +#else +void exit_now(const char *format, ...); +#endif #ifdef __cplusplus } diff --git a/ssl/test/ssltest.c b/ssl/test/ssltest.c index 55ad891c9..d841afaa9 100644 --- a/ssl/test/ssltest.c +++ b/ssl/test/ssltest.c @@ -996,27 +996,6 @@ int SSL_server_tests(void) printf("SSL server test \"%s\" passed\n", "Bad After Cert"); TTY_FLUSH(); - /* this test should fail */ - if ((ret = SSL_server_test(NULL, "Bogus cert", "-cipher RC4-SHA", - "../ssl/test/axTLS.x509_crud.cer", NULL, - "../ssl/test/axTLS.key_512", NULL, - NULL, DEFAULT_SVR_OPTION)) != SSL_ERROR_INVALID_KEY) - goto cleanup; - - printf("SSL server test \"%s\" passed\n", "Bogus cert"); - TTY_FLUSH(); - - /* this test should fail */ - if ((ret = SSL_server_test(NULL, "Bogus private key", - "-cipher RC4-SHA", - "../ssl/test/axTLS.x509_device.cer", NULL, - "../ssl/test/axTLS.crud", NULL, - NULL, DEFAULT_SVR_OPTION)) != SSL_ERROR_INVALID_KEY) - goto cleanup; - - printf("SSL server test \"%s\" passed\n", "Bogus private key"); - TTY_FLUSH(); - /* * Key in PEM format */ @@ -1734,7 +1713,7 @@ int main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */ dup2(fd, 2); #endif - + bi_ctx = bi_initialize(); if (AES_test(bi_ctx)) diff --git a/www/bin/.htaccess b/www/bin/.htaccess new file mode 100644 index 000000000..4496fa9ed --- /dev/null +++ b/www/bin/.htaccess @@ -0,0 +1,2 @@ +Deny all +