diff options
author | Stef Walter <stefw@redhat.com> | 2015-11-10 12:18:30 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2016-05-02 15:28:24 +0200 |
commit | ffe8b98cc2ee975c461322f0f119a398d783bdf7 (patch) | |
tree | d42a115c4a0968d8c396fa2f031baaa5fbb510f1 | |
parent | aa5c7c3b0ca36e415d095df55506df172e299ee2 (diff) | |
download | libssh-ffe8b98cc2ee975c461322f0f119a398d783bdf7.tar.gz libssh-ffe8b98cc2ee975c461322f0f119a398d783bdf7.tar.xz libssh-ffe8b98cc2ee975c461322f0f119a398d783bdf7.zip |
auth: Cleanup memory leak when using SSH agent
In Cockpit we've seen this memory leak:
at 0x4C2A9C7: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x5B76B03: ssh_userauth_agent (auth.c:778)
by 0x40DD5A: cockpit_ssh_authenticate (cockpitsshtransport.c:327)
BUG: https://red.libssh.org/issues/208
Signed-off-by: Stef Walter <stefw@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
-rw-r--r-- | include/libssh/priv.h | 2 | ||||
-rw-r--r-- | src/auth.c | 27 | ||||
-rw-r--r-- | src/session.c | 3 |
3 files changed, 25 insertions, 7 deletions
diff --git a/include/libssh/priv.h b/include/libssh/priv.h index b7a80fe2..9b34b247 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -361,5 +361,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len); #define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0) +void ssh_agent_state_free(void *data); + #endif /* _LIBSSH_PRIV_H */ /* vim: set ts=4 sw=4 et cindent: */ @@ -745,6 +745,15 @@ struct ssh_agent_state_struct { char *comment; }; +/* Internal function */ +void ssh_agent_state_free(void *data) { + struct ssh_agent_state_struct *state = data; + if (state) { + ssh_string_free_char(state->comment); + ssh_key_free(state->pubkey); + free (state); + } +} /** * @brief Try to do public key authentication with ssh agent. @@ -805,9 +814,8 @@ int ssh_userauth_agent(ssh_session session, state->state == SSH_AGENT_STATE_PUBKEY){ rc = ssh_userauth_try_publickey(session, username, state->pubkey); if (rc == SSH_AUTH_ERROR) { - ssh_string_free_char(state->comment); - ssh_key_free(state->pubkey); - SAFE_FREE(session->agent_state); + ssh_agent_state_free (state); + session->agent_state = NULL; return rc; } else if (rc == SSH_AUTH_AGAIN) { state->state = SSH_AGENT_STATE_PUBKEY; @@ -816,6 +824,7 @@ int ssh_userauth_agent(ssh_session session, SSH_LOG(SSH_LOG_DEBUG, "Public key of %s refused by server", state->comment); ssh_string_free_char(state->comment); + state->comment = NULL; ssh_key_free(state->pubkey); state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->state = SSH_AGENT_STATE_NONE; @@ -831,23 +840,27 @@ int ssh_userauth_agent(ssh_session session, if (rc == SSH_AUTH_AGAIN) return rc; ssh_string_free_char(state->comment); - ssh_key_free(state->pubkey); + state->comment = NULL; if (rc == SSH_AUTH_ERROR) { - SAFE_FREE(session->agent_state); + ssh_agent_state_free (session->agent_state); + session->agent_state = NULL; return rc; } else if (rc != SSH_AUTH_SUCCESS) { SSH_LOG(SSH_LOG_INFO, "Server accepted public key but refused the signature"); + ssh_key_free(state->pubkey); state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->state = SSH_AGENT_STATE_NONE; continue; } - SAFE_FREE(session->agent_state); + ssh_agent_state_free (session->agent_state); + session->agent_state = NULL; return SSH_AUTH_SUCCESS; } } - SAFE_FREE(session->agent_state); + ssh_agent_state_free (session->agent_state); + session->agent_state = NULL; return rc; } #endif diff --git a/src/session.c b/src/session.c index a61af44b..a9db298e 100644 --- a/src/session.c +++ b/src/session.c @@ -261,6 +261,9 @@ void ssh_free(ssh_session session) { ssh_list_free(session->opts.identity); } + ssh_agent_state_free (session->agent_state); + session->agent_state = NULL; + SAFE_FREE(session->auth_auto_state); SAFE_FREE(session->serverbanner); SAFE_FREE(session->clientbanner); |