| 1 | |
| 2 | # HG changeset patch |
| 3 | # User Matt Johnston <matt@ucc.asn.au> |
| 4 | # Date 1322947885 -28800 |
| 5 | # Node ID 818108bf7749bfecd4715a30e2583aac9dbe25e8 |
| 6 | # Parent 5e8d84f3ee7256d054ecf7e9f248765ccaa7f24f |
| 7 | - Fix use-after-free if multiple command requests were sent. Move |
| 8 | the original_command into chansess struct since that makes more sense |
| 9 | |
| 10 | --- a/auth.h |
| 11 | +++ b/auth.h |
| 12 | @@ -133,7 +133,6 @@ struct PubKeyOptions { |
| 13 | int no_pty_flag; |
| 14 | /* "command=" option. */ |
| 15 | unsigned char * forced_command; |
| 16 | - unsigned char * original_command; |
| 17 | }; |
| 18 | #endif |
| 19 | |
| 20 | --- a/chansession.h |
| 21 | +++ b/chansession.h |
| 22 | @@ -69,6 +69,10 @@ struct ChanSess { |
| 23 | char * agentfile; |
| 24 | char * agentdir; |
| 25 | #endif |
| 26 | + |
| 27 | +#ifdef ENABLE_SVR_PUBKEY_OPTIONS |
| 28 | + char *original_command; |
| 29 | +#endif |
| 30 | }; |
| 31 | |
| 32 | struct ChildPid { |
| 33 | --- a/svr-authpubkeyoptions.c |
| 34 | +++ b/svr-authpubkeyoptions.c |
| 35 | @@ -92,14 +92,15 @@ int svr_pubkey_allows_pty() { |
| 36 | * by any 'command' public key option. */ |
| 37 | void svr_pubkey_set_forced_command(struct ChanSess *chansess) { |
| 38 | if (ses.authstate.pubkey_options) { |
| 39 | - ses.authstate.pubkey_options->original_command = chansess->cmd; |
| 40 | - if (!chansess->cmd) |
| 41 | - { |
| 42 | - ses.authstate.pubkey_options->original_command = m_strdup(""); |
| 43 | + if (chansess->cmd) { |
| 44 | + /* original_command takes ownership */ |
| 45 | + chansess->original_command = chansess->cmd; |
| 46 | + } else { |
| 47 | + chansess->original_command = m_strdup(""); |
| 48 | } |
| 49 | - chansess->cmd = ses.authstate.pubkey_options->forced_command; |
| 50 | + chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command); |
| 51 | #ifdef LOG_COMMANDS |
| 52 | - dropbear_log(LOG_INFO, "Command forced to '%s'", ses.authstate.pubkey_options->original_command); |
| 53 | + dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command); |
| 54 | #endif |
| 55 | } |
| 56 | } |
| 57 | --- a/svr-chansession.c |
| 58 | +++ b/svr-chansession.c |
| 59 | @@ -217,6 +217,8 @@ static int newchansess(struct Channel *c |
| 60 | |
| 61 | struct ChanSess *chansess; |
| 62 | |
| 63 | + TRACE(("new chansess %p", channel)) |
| 64 | + |
| 65 | dropbear_assert(channel->typedata == NULL); |
| 66 | |
| 67 | chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess)); |
| 68 | @@ -279,6 +281,10 @@ static void closechansess(struct Channel |
| 69 | m_free(chansess->cmd); |
| 70 | m_free(chansess->term); |
| 71 | |
| 72 | +#ifdef ENABLE_SVR_PUBKEY_OPTIONS |
| 73 | + m_free(chansess->original_command); |
| 74 | +#endif |
| 75 | + |
| 76 | if (chansess->tty) { |
| 77 | /* write the utmp/wtmp login record */ |
| 78 | li = chansess_login_alloc(chansess); |
| 79 | @@ -924,10 +930,8 @@ static void execchild(void *user_data) { |
| 80 | } |
| 81 | |
| 82 | #ifdef ENABLE_SVR_PUBKEY_OPTIONS |
| 83 | - if (ses.authstate.pubkey_options && |
| 84 | - ses.authstate.pubkey_options->original_command) { |
| 85 | - addnewvar("SSH_ORIGINAL_COMMAND", |
| 86 | - ses.authstate.pubkey_options->original_command); |
| 87 | + if (chansess->original_command) { |
| 88 | + addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command); |
| 89 | } |
| 90 | #endif |
| 91 | |
| 92 | |