aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@redhat.com>2015-11-10 12:18:30 +0100
committerAndreas Schneider <asn@cryptomilk.org>2016-05-02 15:28:24 +0200
commitffe8b98cc2ee975c461322f0f119a398d783bdf7 (patch)
treed42a115c4a0968d8c396fa2f031baaa5fbb510f1
parentaa5c7c3b0ca36e415d095df55506df172e299ee2 (diff)
downloadlibssh-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.h2
-rw-r--r--src/auth.c27
-rw-r--r--src/session.c3
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: */
diff --git a/src/auth.c b/src/auth.c
index 9f1ba134..43dd0d2b 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -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);