Skip to content

Commit d5b1a2b

Browse files
author
Ilyes Ben Hamouda
committed
session BUGFIX do not close SSH socket twice
Currently, SSH socket is closed twice when created by libssh, causing undefined behavior in multithreaded programs (e.g. netopeer2-server). ssh_disconnect() used to close the SSH socket. However, this behavior changed with libssh 0.10: the socket is no longer closed when passed through options. Only close SSH socket when created by us after disconnecting from the session (if libssh >= 0.10). Fixes #450 Fixes: 70e9062 ("session BUGFIX close SSH socket") Signed-off-by: Ilyes Ben Hamouda <[email protected]>
1 parent 4b05cbe commit d5b1a2b

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

src/session.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -816,12 +816,18 @@ nc_session_free_transport(struct nc_session *session, int *multisession)
816816
free(siter);
817817
} while (session->ti.libssh.next != session);
818818
}
819-
/* remember sock so we can close it */
820-
sock = ssh_get_fd(session->ti.libssh.session);
821819
if (connected) {
822-
/* does not close sock */
820+
/* resets ssh sock but only closes it if not passed through
821+
* options since libssh 0.10
822+
*/
823823
ssh_disconnect(session->ti.libssh.session);
824+
#if (LIBSSH_VERSION_MAJOR == 0 && LIBSSH_VERSION_MINOR >= 10) || LIBSSH_VERSION_MAJOR > 0
825+
if (session->ti.libssh.opt_sock != NC_SSH_INVALID_SOCKET) {
826+
close(session->ti.libssh.opt_sock);
827+
}
828+
#endif
824829
}
830+
/* closes ssh sock if it is still open */
825831
ssh_free(session->ti.libssh.session);
826832
} else {
827833
/* remove the session from the list */

src/session_client_ssh.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,7 @@ _nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx, struct nc_keepal
16551655
NC_CHECK_ERRMEM_RET(!session, NULL);
16561656
session->status = NC_STATUS_STARTING;
16571657
session->ti_type = NC_TI_SSH;
1658+
session->ti.libssh.opt_sock = NC_SSH_INVALID_SOCKET;
16581659
session->ti.libssh.session = ssh_session;
16591660

16601661
/* was port set? */
@@ -1683,6 +1684,7 @@ _nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx, struct nc_keepal
16831684
free(host);
16841685
goto fail;
16851686
}
1687+
session->ti.libssh.opt_sock = sock;
16861688
ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_FD, &sock);
16871689
ssh_set_blocking(session->ti.libssh.session, 0);
16881690

@@ -1809,6 +1811,7 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
18091811

18101812
/* transport-specific data */
18111813
session->ti_type = NC_TI_SSH;
1814+
session->ti.libssh.opt_sock = NC_SSH_INVALID_SOCKET;
18121815
session->ti.libssh.session = ssh_new();
18131816
if (!session->ti.libssh.session) {
18141817
ERR(session, "Unable to initialize SSH session.");
@@ -1833,6 +1836,7 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
18331836
ERR(session, "Unable to connect to %s:%u (%s).", host, port, strerror(errno));
18341837
goto fail;
18351838
}
1839+
session->ti.libssh.opt_sock = sock;
18361840
ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_FD, &sock);
18371841
ssh_set_blocking(session->ti.libssh.session, 0);
18381842

@@ -1903,6 +1907,7 @@ nc_connect_ssh_channel(struct nc_session *session, struct ly_ctx *ctx)
19031907

19041908
/* share some parameters including the IO lock (we are using one socket for both sessions) */
19051909
new_session->ti_type = NC_TI_SSH;
1910+
new_session->ti.libssh.opt_sock = session->ti.libssh.opt_sock;
19061911
new_session->ti.libssh.session = session->ti.libssh.session;
19071912
new_session->io_lock = session->io_lock;
19081913

@@ -2016,6 +2021,9 @@ nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly
20162021
return NULL;
20172022
}
20182023

2024+
if (session->ti.libssh.opt_sock == NC_SSH_INVALID_SOCKET) {
2025+
session->ti.libssh.opt_sock = sock;
2026+
}
20192027
session->flags |= NC_SESSION_CALLHOME;
20202028
return session;
20212029
}

src/session_p.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ enum nc_store_type {
142142
#include <curl/curl.h>
143143
#include <libssh/libssh.h>
144144

145+
/**
146+
* Invalid SSH socket ID.
147+
*/
148+
#define NC_SSH_INVALID_SOCKET -1
149+
145150
/**
146151
* Timeout set for libssh (s).
147152
*/
@@ -786,6 +791,7 @@ struct nc_session {
786791
} unixsock; /**< NC_TI_UNIX transport implementation structure */
787792
#ifdef NC_ENABLED_SSH_TLS
788793
struct {
794+
int opt_sock; /**< socket file descriptor passed through options */
789795
ssh_channel channel;
790796
ssh_session session;
791797
struct nc_session *next; /**< pointer to the next NETCONF session on the same

src/session_server_ssh.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ nc_server_ssh_channel_subsystem(struct nc_session *session, ssh_channel channel,
14491449

14501450
new_session->status = NC_STATUS_STARTING;
14511451
new_session->ti_type = NC_TI_SSH;
1452+
new_session->ti.libssh.opt_sock = session->ti.libssh.opt_sock;
14521453
new_session->io_lock = session->io_lock;
14531454
new_session->ti.libssh.channel = channel;
14541455
new_session->ti.libssh.session = session->ti.libssh.session;
@@ -1955,6 +1956,7 @@ nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts *opt
19551956

19561957
/* other transport-specific data */
19571958
session->ti_type = NC_TI_SSH;
1959+
session->ti.libssh.opt_sock = NC_SSH_INVALID_SOCKET;
19581960
session->ti.libssh.session = ssh_new();
19591961
if (!session->ti.libssh.session) {
19601962
ERR(NULL, "Failed to initialize a new SSH session.");

0 commit comments

Comments
 (0)