From 60c7e2bef571542ae032d3f47395e3f2775cae75 Mon Sep 17 00:00:00 2001
From: jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Sat, 25 Feb 2012 12:40:46 +0000
Subject: [package] dropbear: patch possible use after free by authenticated
 remote users with active command restrictions (CVE-2012-0920)

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30714 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 package/dropbear/Makefile                         |  4 +-
 package/dropbear/patches/140-disable_assert.patch |  2 +-
 package/dropbear/patches/400-CVE-2012-0920.patch  | 91 +++++++++++++++++++++++
 3 files changed, 94 insertions(+), 3 deletions(-)
 create mode 100644 package/dropbear/patches/400-CVE-2012-0920.patch

diff --git a/package/dropbear/Makefile b/package/dropbear/Makefile
index cbfa0ee3d..2f78030da 100644
--- a/package/dropbear/Makefile
+++ b/package/dropbear/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2006-2011 OpenWrt.org
+# Copyright (C) 2006-2012 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=dropbear
 PKG_VERSION:=2011.54
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:= \
diff --git a/package/dropbear/patches/140-disable_assert.patch b/package/dropbear/patches/140-disable_assert.patch
index 2628f3407..e99376333 100644
--- a/package/dropbear/patches/140-disable_assert.patch
+++ b/package/dropbear/patches/140-disable_assert.patch
@@ -1,6 +1,6 @@
 --- a/dbutil.h
 +++ b/dbutil.h
-@@ -94,6 +94,10 @@
+@@ -94,6 +94,10 @@ int m_str_to_uint(const char* str, unsig
  #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
  
  /* Dropbear assertion */
diff --git a/package/dropbear/patches/400-CVE-2012-0920.patch b/package/dropbear/patches/400-CVE-2012-0920.patch
new file mode 100644
index 000000000..164909f56
--- /dev/null
+++ b/package/dropbear/patches/400-CVE-2012-0920.patch
@@ -0,0 +1,91 @@
+
+# HG changeset patch
+# User Matt Johnston <matt@ucc.asn.au>
+# Date 1322947885 -28800
+# Node ID 818108bf7749bfecd4715a30e2583aac9dbe25e8
+# Parent  5e8d84f3ee7256d054ecf7e9f248765ccaa7f24f
+- Fix use-after-free if multiple command requests were sent. Move
+the original_command into chansess struct since that makes more sense
+
+--- a/auth.h
++++ b/auth.h
+@@ -133,7 +133,6 @@ struct PubKeyOptions {
+ 	int no_pty_flag;
+ 	/* "command=" option. */
+ 	unsigned char * forced_command;
+-	unsigned char * original_command;
+ };
+ #endif
+ 
+--- a/chansession.h
++++ b/chansession.h
+@@ -69,6 +69,10 @@ struct ChanSess {
+ 	char * agentfile;
+ 	char * agentdir;
+ #endif
++
++#ifdef ENABLE_SVR_PUBKEY_OPTIONS
++	char *original_command;
++#endif
+ };
+ 
+ struct ChildPid {
+--- a/svr-authpubkeyoptions.c
++++ b/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
+ 	}
+ }
+--- a/svr-chansession.c
++++ b/svr-chansession.c
+@@ -217,6 +217,8 @@ static int newchansess(struct Channel *c
+ 
+ 	struct ChanSess *chansess;
+ 
++	TRACE(("new chansess %p", channel))
++
+ 	dropbear_assert(channel->typedata == NULL);
+ 
+ 	chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
+@@ -279,6 +281,10 @@ static void closechansess(struct 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 +930,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
+ 
-- 
cgit v1.2.3