Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,12 +816,18 @@ nc_session_free_transport(struct nc_session *session, int *multisession)
free(siter);
} while (session->ti.libssh.next != session);
}
/* remember sock so we can close it */
sock = ssh_get_fd(session->ti.libssh.session);
if (connected) {
/* does not close sock */
/* remember sock so we can close it */
sock = ssh_get_fd(session->ti.libssh.session);

/* clears sock but does not close it if passed via options (libssh >= 0.10) */
ssh_disconnect(session->ti.libssh.session);
#if (LIBSSH_VERSION_MAJOR == 0 && LIBSSH_VERSION_MINOR < 10)
sock = -1;
#endif
}

/* closes sock if set */
ssh_free(session->ti.libssh.session);
} else {
/* remove the session from the list */
Expand Down
2 changes: 1 addition & 1 deletion src/session_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,7 @@ struct nc_session *nc_accept_callhome_ssh_sock(int sock, const char *host, uint1
* @brief Establish SSH transport on a socket.
*
* @param[in] session Session structure of the new connection.
* @param[in] sock Socket of the new connection.
* @param[in] sock Socket of the new connection, closed if not set to the session.
* @param[in] timeout Transport operations timeout in msec (not SSH authentication one).
* @return 1 on success, 0 on timeout, -1 on error.
*/
Expand Down
17 changes: 17 additions & 0 deletions src/session_server_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2020,8 +2020,25 @@ nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts *opt
if (ssh_bind_accept_fd(sbind, session->ti.libssh.session, sock) == SSH_ERROR) {
ERR(session, "SSH failed to accept a new connection (%s).", ssh_get_error(sbind));
rc = -1;

/* Avoid closing the socket on failure to prevent a possible double close.
* On failure, sock may or not be set to the session. In theory, we should
* be able to compare sock with ssh_get_fd() and close it only if it was
* not set, for example:
*
* if (ssh_get_fd(session) == sock)
* sock = -1;
*
* However, if ssh_bind_accept_fd() fails to allocate the socket structure
* internally, calling ssh_get_fd() will dereference a NULL pointer due to
* a buggy behavior in libssh.
*/
sock = -1;
goto cleanup;
}

/* use SSH_OPTIONS_FD so libssh won't close the socket in ssh_disconnect() */
ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_FD, &sock);
sock = -1;

/* set to non-blocking */
Expand Down