From 477bcab946098d094dc5a0b30f06e44f29f5bb54 Mon Sep 17 00:00:00 2001 From: Shibby Date: Fri, 27 Apr 2012 18:15:30 +0700 Subject: [PATCH] Dropbear: 2012.55 update and re-apply all teddy`s patches --- release/src/router/dropbear/CHANGES | 19 +++++++++++++++++++ release/src/router/dropbear/auth.h | 1 - release/src/router/dropbear/channel.h | 4 ++++ release/src/router/dropbear/chansession.h | 4 ++++ release/src/router/dropbear/circbuffer.c | 1 + release/src/router/dropbear/cli-agentfwd.c | 3 +-- release/src/router/dropbear/common-channel.c | 21 ++++++++++++++------- release/src/router/dropbear/common-kex.c | 5 +++++ release/src/router/dropbear/dbutil.c | 12 +++--------- release/src/router/dropbear/dbutil.h | 3 +-- release/src/router/dropbear/debian/changelog | 6 ++++++ release/src/router/dropbear/options.h | 6 +++--- release/src/router/dropbear/signkey.c | 4 ++-- release/src/router/dropbear/svr-authpam.c | 17 ++++------------- release/src/router/dropbear/svr-authpubkeyoptions.c | 13 +++++++------ release/src/router/dropbear/svr-chansession.c | 14 ++++++++++---- release/src/router/dropbear/svr-main.c | 1 + release/src/router/dropbear/svr-x11fwd.c | 2 +- release/src/router/dropbear/sysoptions.h | 2 +- 19 files changed, 87 insertions(+), 51 deletions(-) diff --git a/release/src/router/dropbear/CHANGES b/release/src/router/dropbear/CHANGES index e111dc4406..3e14bad504 100644 --- a/release/src/router/dropbear/CHANGES +++ b/release/src/router/dropbear/CHANGES @@ -1,3 +1,22 @@ +2012.55 - Wednesday 22 February 2012 + +- Security: Fix use-after-free bug that could be triggered if command="..." + authorized_keys restrictions are used. Could allow arbitrary code execution + or bypass of the command="..." restriction to an authenticated user. + This bug affects releases 0.52 onwards. Ref CVE-2012-0920. + Thanks to Danny Fullerton of Mantor Organization for reporting + the bug. + +- Compile fix, only apply IPV6 socket options if they are available in headers + Thanks to Gustavo Zacarias for the patch + +- Overwrite session key memory on exit + +- Fix minor memory leak in unusual PAM authentication configurations. + Thanks to Stathis Voukelatos + +- Other small code cleanups + 2011.54 - Tuesday 8 November 2011 - Building statically works again, broke in 0.53 and 0.53.1 diff --git a/release/src/router/dropbear/auth.h b/release/src/router/dropbear/auth.h index 7ebf9ae7e4..0fd9c73e18 100644 --- a/release/src/router/dropbear/auth.h +++ b/release/src/router/dropbear/auth.h @@ -133,7 +133,6 @@ struct PubKeyOptions { int no_pty_flag; /* "command=" option. */ unsigned char * forced_command; - unsigned char * original_command; }; #endif diff --git a/release/src/router/dropbear/channel.h b/release/src/router/dropbear/channel.h index 5c63226b25..d9e289461e 100644 --- a/release/src/router/dropbear/channel.h +++ b/release/src/router/dropbear/channel.h @@ -69,6 +69,10 @@ struct Channel { int sent_close, recv_close; int recv_eof, sent_eof; + /* Set after running the ChanType-specific close hander + * to ensure we don't run it twice (nor type->checkclose()). */ + int close_handler_done; + int initconn; /* used for TCP forwarding, whether the channel has been fully initialised */ diff --git a/release/src/router/dropbear/chansession.h b/release/src/router/dropbear/chansession.h index 924518b8ea..ef252eaf7e 100644 --- a/release/src/router/dropbear/chansession.h +++ b/release/src/router/dropbear/chansession.h @@ -69,6 +69,10 @@ struct ChanSess { char * agentfile; char * agentdir; #endif + +#ifdef ENABLE_SVR_PUBKEY_OPTIONS + char *original_command; +#endif }; struct ChildPid { diff --git a/release/src/router/dropbear/circbuffer.c b/release/src/router/dropbear/circbuffer.c index f19b70af5e..795373768e 100644 --- a/release/src/router/dropbear/circbuffer.c +++ b/release/src/router/dropbear/circbuffer.c @@ -48,6 +48,7 @@ circbuffer * cbuf_new(unsigned int size) { void cbuf_free(circbuffer * cbuf) { + m_burn(cbuf->data, cbuf->size); m_free(cbuf->data); m_free(cbuf); } diff --git a/release/src/router/dropbear/cli-agentfwd.c b/release/src/router/dropbear/cli-agentfwd.c index c9ce8334c6..a821305631 100644 --- a/release/src/router/dropbear/cli-agentfwd.c +++ b/release/src/router/dropbear/cli-agentfwd.c @@ -260,7 +260,7 @@ void agent_buf_sign(buffer *sigblob, sign_key *key, const unsigned char *data, unsigned int len) { buffer *request_data = NULL; buffer *response = NULL; - unsigned int keylen, siglen; + unsigned int siglen; int packet_type; /* Request format @@ -271,7 +271,6 @@ void agent_buf_sign(buffer *sigblob, sign_key *key, */ request_data = buf_new(MAX_PUBKEY_SIZE + len + 12); buf_put_pub_key(request_data, key, key->type); - keylen = request_data->len - 4; buf_putstring(request_data, data, len); buf_putint(request_data, 0); diff --git a/release/src/router/dropbear/common-channel.c b/release/src/router/dropbear/common-channel.c index 5821b08535..9eaba50907 100644 --- a/release/src/router/dropbear/common-channel.c +++ b/release/src/router/dropbear/common-channel.c @@ -138,6 +138,7 @@ struct Channel* newchannel(unsigned int remotechan, newchan->index = i; newchan->sent_close = newchan->recv_close = 0; newchan->sent_eof = newchan->recv_eof = 0; + newchan->close_handler_done = 0; newchan->remotechan = remotechan; newchan->transwindow = transwindow; @@ -270,7 +271,9 @@ static void check_close(struct Channel *channel) { cbuf_getused(channel->writebuf), channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) - if (!channel->flushing && channel->type->check_close + if (!channel->flushing + && !channel->close_handler_done + && channel->type->check_close && channel->type->check_close(channel)) { channel->flushing = 1; @@ -281,7 +284,8 @@ static void check_close(struct Channel *channel) { channel, to ensure that the shell has exited (and the exit status retrieved) before we close things up. */ if (!channel->type->check_close - || channel->type->check_close(channel)) { + || channel->close_handler_done + || channel->type->check_close(channel)) { close_allowed = 1; } @@ -363,9 +367,11 @@ static void check_in_progress(struct Channel *channel) { /* Send the close message and set the channel as closed */ static void send_msg_channel_close(struct Channel *channel) { - TRACE(("enter send_msg_channel_close")) - if (channel->type->closehandler) { + TRACE(("enter send_msg_channel_close %p", channel)) + if (channel->type->closehandler + && !channel->close_handler_done) { channel->type->closehandler(channel); + channel->close_handler_done = 1; } CHECKCLEARTOWRITE(); @@ -568,16 +574,17 @@ void recv_msg_channel_request() { struct Channel *channel; - TRACE(("enter recv_msg_channel_request")) - channel = getchannel(); + TRACE(("enter recv_msg_channel_request %p", channel)) + if (channel->sent_close) { TRACE(("leave recv_msg_channel_request: already closed channel")) return; } - if (channel->type->reqhandler) { + if (channel->type->reqhandler + && !channel->close_handler_done) { channel->type->reqhandler(channel); } else { send_msg_channel_failure(channel); diff --git a/release/src/router/dropbear/common-kex.c b/release/src/router/dropbear/common-kex.c index 173bf8c458..2b3472b7d6 100644 --- a/release/src/router/dropbear/common-kex.c +++ b/release/src/router/dropbear/common-kex.c @@ -366,6 +366,11 @@ void gen_new_keys() { ses.keys = ses.newkeys; ses.newkeys = NULL; + m_burn(C2S_IV, sizeof(C2S_IV)); + m_burn(C2S_key, sizeof(C2S_key)); + m_burn(S2C_IV, sizeof(S2C_IV)); + m_burn(S2C_key, sizeof(S2C_key)); + TRACE(("leave gen_new_keys")) } diff --git a/release/src/router/dropbear/dbutil.c b/release/src/router/dropbear/dbutil.c index 22929ef464..9a6d846a22 100644 --- a/release/src/router/dropbear/dbutil.c +++ b/release/src/router/dropbear/dbutil.c @@ -164,7 +164,7 @@ static void set_sock_priority(int sock) { /* set the TOS bit for either ipv4 or ipv6 */ #ifdef IPTOS_LOWDELAY val = IPTOS_LOWDELAY; -#if defined(IPPROTO_IPV6) && defined(TCONFIG_IPV6) +#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&val, sizeof(val)); #endif setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val)); @@ -256,7 +256,7 @@ int dropbear_listen(const char* address, const char* port, linger.l_linger = 5; setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger)); -#ifdef IPV6_V6ONLY +#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if (res->ai_family == AF_INET6) { int on = 1; if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, @@ -800,12 +800,6 @@ void * m_strdup(const char * str) { return ret; } -void __m_free(void* ptr) { - if (ptr != NULL) { - free(ptr); - } -} - void * m_realloc(void* ptr, size_t size) { void *ret; @@ -830,7 +824,7 @@ void m_burn(void *data, unsigned int len) { if (data == NULL) return; while (len--) { - *p++ = 0x66; + *p++ = 0x0; } } diff --git a/release/src/router/dropbear/dbutil.h b/release/src/router/dropbear/dbutil.h index 14c4c28033..0f16bf3c16 100644 --- a/release/src/router/dropbear/dbutil.h +++ b/release/src/router/dropbear/dbutil.h @@ -83,8 +83,7 @@ void m_close(int fd); void * m_malloc(size_t size); void * m_strdup(const char * str); void * m_realloc(void* ptr, size_t size); -#define m_free(X) __m_free(X); (X) = NULL; -void __m_free(void* ptr); +#define m_free(X) free(X); (X) = NULL; void m_burn(void* data, unsigned int len); void setnonblocking(int fd); void disallow_core(); diff --git a/release/src/router/dropbear/debian/changelog b/release/src/router/dropbear/debian/changelog index f41594303f..acd9ec4112 100644 --- a/release/src/router/dropbear/debian/changelog +++ b/release/src/router/dropbear/debian/changelog @@ -1,3 +1,9 @@ +dropbear (2012.55-0.1) unstable; urgency=low + + * New upstream release. + + -- Matt Johnston Wed, 22 Feb 2012 22:54:00 +0800 + dropbear (2011.54-0.1) unstable; urgency=low * New upstream release. diff --git a/release/src/router/dropbear/options.h b/release/src/router/dropbear/options.h index 765869d9eb..e3c2d173f7 100644 --- a/release/src/router/dropbear/options.h +++ b/release/src/router/dropbear/options.h @@ -38,7 +38,7 @@ * Both of these flags can be defined at once, don't compile without at least * one of them. */ #define NON_INETD_MODE -/*#define INETD_MODE*/ +#define INETD_MODE /* Setting this disables the fast exptmod bignum code. It saves ~5kB, but is * perhaps 20% slower for pubkey operations (it is probably worth experimenting @@ -49,10 +49,10 @@ several kB in binary size however will make the symmetrical ciphers and hashes slower, perhaps by 50%. Recommended for small systems that aren't doing much traffic. */ -#define DROPBEAR_SMALL_CODE +/*#define DROPBEAR_SMALL_CODE*/ /* Enable X11 Forwarding - server only */ -/*#define ENABLE_X11FWD*/ +#define ENABLE_X11FWD /* Enable TCP Fowarding */ /* 'Local' is "-L" style (client listening port forwarded via server) diff --git a/release/src/router/dropbear/signkey.c b/release/src/router/dropbear/signkey.c index c53805a1c2..1d908f4b8a 100644 --- a/release/src/router/dropbear/signkey.c +++ b/release/src/router/dropbear/signkey.c @@ -105,11 +105,11 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { m_free(ident); if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) { - TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, type)) + TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, *type)) return DROPBEAR_FAILURE; } - TRACE(("buf_get_pub_key keytype is %d")) + TRACE(("buf_get_pub_key keytype is %d", keytype)) *type = keytype; diff --git a/release/src/router/dropbear/svr-authpam.c b/release/src/router/dropbear/svr-authpam.c index f230be76e4..e84f076d17 100644 --- a/release/src/router/dropbear/svr-authpam.c +++ b/release/src/router/dropbear/svr-authpam.c @@ -56,11 +56,7 @@ pamConvFunc(int num_msg, struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr; unsigned int msg_len = 0; unsigned int i = 0; - - const char* message = (*msg)->msg; - - /* make a copy we can strip */ - char * compare_message = m_strdup(message); + char * compare_message = NULL; TRACE(("enter pamConvFunc")) @@ -71,15 +67,10 @@ pamConvFunc(int num_msg, dropbear_log(LOG_INFO, "pamConvFunc() called with >1 messages: not supported."); return PAM_CONV_ERR; } - - TRACE(("msg_style is %d", (*msg)->msg_style)) - if (compare_message) { - TRACE(("message is '%s'", compare_message)) - } else { - TRACE(("null message")) - } - + /* make a copy we can strip */ + compare_message = m_strdup((*msg)->msg); + /* Make the string lowercase. */ msg_len = strlen(compare_message); for (i = 0; i < msg_len; i++) { diff --git a/release/src/router/dropbear/svr-authpubkeyoptions.c b/release/src/router/dropbear/svr-authpubkeyoptions.c index fd87703848..4490b5849c 100644 --- a/release/src/router/dropbear/svr-authpubkeyoptions.c +++ b/release/src/router/dropbear/svr-authpubkeyoptions.c @@ -92,14 +92,15 @@ int svr_pubkey_allows_pty() { * by any 'command' public key option. */ void svr_pubkey_set_forced_command(struct ChanSess *chansess) { if (ses.authstate.pubkey_options) { - ses.authstate.pubkey_options->original_command = chansess->cmd; - if (!chansess->cmd) - { - ses.authstate.pubkey_options->original_command = m_strdup(""); + if (chansess->cmd) { + /* original_command takes ownership */ + chansess->original_command = chansess->cmd; + } else { + chansess->original_command = m_strdup(""); } - chansess->cmd = ses.authstate.pubkey_options->forced_command; + chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command); #ifdef LOG_COMMANDS - dropbear_log(LOG_INFO, "Command forced to '%s'", ses.authstate.pubkey_options->original_command); + dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command); #endif } } diff --git a/release/src/router/dropbear/svr-chansession.c b/release/src/router/dropbear/svr-chansession.c index 0b3e833329..9fd49c1120 100644 --- a/release/src/router/dropbear/svr-chansession.c +++ b/release/src/router/dropbear/svr-chansession.c @@ -137,6 +137,7 @@ static void sesssigchild_handler(int UNUSED(dummy)) { sa_chld.sa_handler = sesssigchild_handler; sa_chld.sa_flags = SA_NOCLDSTOP; + sigemptyset(&sa_chld.sa_mask); sigaction(SIGCHLD, &sa_chld, NULL); TRACE(("leave sigchld handler")) } @@ -217,6 +218,8 @@ static int newchansess(struct Channel *channel) { struct ChanSess *chansess; + TRACE(("new chansess %p", channel)) + dropbear_assert(channel->typedata == NULL); chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess)); @@ -279,6 +282,10 @@ static void closechansess(struct Channel *channel) { m_free(chansess->cmd); m_free(chansess->term); +#ifdef ENABLE_SVR_PUBKEY_OPTIONS + m_free(chansess->original_command); +#endif + if (chansess->tty) { /* write the utmp/wtmp login record */ li = chansess_login_alloc(chansess); @@ -924,10 +931,8 @@ static void execchild(void *user_data) { } #ifdef ENABLE_SVR_PUBKEY_OPTIONS - if (ses.authstate.pubkey_options && - ses.authstate.pubkey_options->original_command) { - addnewvar("SSH_ORIGINAL_COMMAND", - ses.authstate.pubkey_options->original_command); + if (chansess->original_command) { + addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command); } #endif @@ -976,6 +981,7 @@ void svr_chansessinitialise() { svr_ses.lastexit.exitpid = -1; /* Nothing has exited yet */ sa_chld.sa_handler = sesssigchild_handler; sa_chld.sa_flags = SA_NOCLDSTOP; + sigemptyset(&sa_chld.sa_mask); if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) { dropbear_exit("signal() error"); } diff --git a/release/src/router/dropbear/svr-main.c b/release/src/router/dropbear/svr-main.c index d3fa9afc50..b7258e5fb0 100644 --- a/release/src/router/dropbear/svr-main.c +++ b/release/src/router/dropbear/svr-main.c @@ -370,6 +370,7 @@ static void commonsetup() { /* catch and reap zombie children */ sa_chld.sa_handler = sigchld_handler; sa_chld.sa_flags = SA_NOCLDSTOP; + sigemptyset(&sa_chld.sa_mask); if (sigaction(SIGCHLD, &sa_chld, NULL) < 0) { dropbear_exit("signal() error"); } diff --git a/release/src/router/dropbear/svr-x11fwd.c b/release/src/router/dropbear/svr-x11fwd.c index 1af027bdf7..92dadd5c54 100644 --- a/release/src/router/dropbear/svr-x11fwd.c +++ b/release/src/router/dropbear/svr-x11fwd.c @@ -175,7 +175,7 @@ void x11cleanup(struct ChanSess *chansess) { m_free(chansess->x11authprot); m_free(chansess->x11authcookie); - TRACE(("chansess %s", chansess)) + TRACE(("chansess %x", chansess)) if (chansess->x11listener != NULL) { remove_listener(chansess->x11listener); chansess->x11listener = NULL; diff --git a/release/src/router/dropbear/sysoptions.h b/release/src/router/dropbear/sysoptions.h index 1b417e5976..283229e9b3 100644 --- a/release/src/router/dropbear/sysoptions.h +++ b/release/src/router/dropbear/sysoptions.h @@ -4,7 +4,7 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "2011.54" +#define DROPBEAR_VERSION "2012.55" #endif #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION -- 2.11.4.GIT