summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2011-12-04 05:31:25 +0800
committerMatt Johnston <matt@ucc.asn.au>2011-12-04 05:31:25 +0800
commit79e50947f2a6d5638c8e24cb6e90eb2e6d1665c4 (patch)
tree1f92facba7d6354ea1738a8b1f441e54254e6e05
parent034d703f415a91ecba4a61ac165b4bb7e173ac37 (diff)
downloaddropbear-79e50947f2a6d5638c8e24cb6e90eb2e6d1665c4.tar.gz
- Fix use-after-free if multiple command requests were sent. Move
the original_command into chansess struct since that makes more sense
-rw-r--r--auth.h1
-rw-r--r--chansession.h4
-rw-r--r--svr-authpubkeyoptions.c13
-rw-r--r--svr-chansession.c12
4 files changed, 19 insertions, 11 deletions
diff --git a/auth.h b/auth.h
index 7ebf9ae..0fd9c73 100644
--- 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
diff --git a/chansession.h b/chansession.h
index 924518b..ef252ea 100644
--- 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 {
diff --git a/svr-authpubkeyoptions.c b/svr-authpubkeyoptions.c
index fd87703..4490b58 100644
--- 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
}
}
diff --git a/svr-chansession.c b/svr-chansession.c
index 0b3e833..53790d1 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -217,6 +217,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 +281,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 +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