From 899ec9e519994b9d39bba502c4b11a1934b03cc2 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Tue, 20 Jul 2021 13:57:31 -0700 Subject: [PATCH] Enable ssh agent authentication on Windows Windows has supported unix domain sockets for a couple of years now; see this article for more information about that: This commit allows libssh to consider using agent authentication on Windows systems. It is mostly removing `#ifndef _WIN32` that prevented the unix domain socket code from being compiled in, and adjusting the use of `read(2)` and `write(2)` to `recv(2)` and `send(2)`, as the former functions are not compatible with sockets on Windows systems. For mingw systems, afunix.h isn't available so we use the technique as was used to resolve building with mingw as used by the curl project in: https://github.com/curl/curl/pull/5170 Signed-off-by: Wez Furlong Reviewed-by: Andreas Schneider --- include/libssh/agent.h | 2 -- include/libssh/socket.h | 2 +- src/agent.c | 14 ++++++++------ src/auth.c | 6 ------ src/pki.c | 2 -- src/session.c | 2 -- src/socket.c | 17 +++++++++++++---- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/libssh/agent.h b/include/libssh/agent.h index d4eefbbf..72052159 100644 --- a/include/libssh/agent.h +++ b/include/libssh/agent.h @@ -77,7 +77,6 @@ struct ssh_agent_struct { ssh_channel channel; }; -#ifndef _WIN32 /* agent.c */ /** * @brief Create a new ssh agent structure. @@ -115,6 +114,5 @@ ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session, ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data); -#endif #endif /* __AGENT_H */ diff --git a/include/libssh/socket.h b/include/libssh/socket.h index 32f51580..ae56f5f6 100644 --- a/include/libssh/socket.h +++ b/include/libssh/socket.h @@ -35,9 +35,9 @@ void ssh_socket_reset(ssh_socket s); void ssh_socket_free(ssh_socket s); void ssh_socket_set_fd(ssh_socket s, socket_t fd); socket_t ssh_socket_get_fd(ssh_socket s); -#ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path); void ssh_execute_command(const char *command, socket_t in, socket_t out); +#ifndef _WIN32 int ssh_socket_connect_proxycommand(ssh_socket s, const char *command); #endif void ssh_socket_close(ssh_socket s); diff --git a/src/agent.c b/src/agent.c index 8cbb02fc..2e1d33b3 100644 --- a/src/agent.c +++ b/src/agent.c @@ -33,8 +33,6 @@ * the agent returns the signed data */ -#ifndef _WIN32 - #include "config.h" #include @@ -46,8 +44,14 @@ #include #endif +#ifndef _WIN32 #include #include +#include +#else +#include +#include +#endif #include "libssh/agent.h" #include "libssh/priv.h" @@ -79,9 +83,9 @@ static uint32_t atomicio(struct ssh_agent_struct *agent, void *buf, uint32_t n, while (n > pos) { if (do_read) { - res = read(fd, b + pos, n - pos); + res = recv(fd, b + pos, n - pos, 0); } else { - res = write(fd, b + pos, n - pos); + res = send(fd, b + pos, n - pos, 0); } switch (res) { case -1: @@ -588,5 +592,3 @@ ssh_string ssh_agent_sign_data(ssh_session session, return sig_blob; } - -#endif /* _WIN32 */ diff --git a/src/auth.c b/src/auth.c index 5ab2e0fa..2e48cfc6 100644 --- a/src/auth.c +++ b/src/auth.c @@ -744,7 +744,6 @@ fail: return SSH_AUTH_ERROR; } -#ifndef _WIN32 static int ssh_userauth_agent_publickey(ssh_session session, const char *username, ssh_key pubkey) @@ -993,7 +992,6 @@ int ssh_userauth_agent(ssh_session session, session->agent_state = NULL; return rc; } -#endif enum ssh_auth_auto_state_e { SSH_AUTH_AUTO_STATE_NONE = 0, @@ -1119,7 +1117,6 @@ int ssh_userauth_publickey_auto(ssh_session session, } state = session->auth.auto_state; if (state->state == SSH_AUTH_AUTO_STATE_NONE) { -#ifndef _WIN32 /* Try authentication with ssh-agent first */ rc = ssh_userauth_agent(session, username); if (rc == SSH_AUTH_SUCCESS || @@ -1127,7 +1124,6 @@ int ssh_userauth_publickey_auto(ssh_session session, rc == SSH_AUTH_AGAIN ) { return rc; } -#endif state->state = SSH_AUTH_AUTO_STATE_PUBKEY; } if (state->it == NULL) { @@ -1394,7 +1390,6 @@ fail: return SSH_AUTH_ERROR; } -#ifndef _WIN32 /* LEGACY */ int ssh_userauth_agent_pubkey(ssh_session session, const char *username, @@ -1422,7 +1417,6 @@ int ssh_userauth_agent_pubkey(ssh_session session, return rc; } -#endif /* _WIN32 */ ssh_kbdint ssh_kbdint_new(void) { diff --git a/src/pki.c b/src/pki.c index 09756fd9..30790c68 100644 --- a/src/pki.c +++ b/src/pki.c @@ -2677,7 +2677,6 @@ end: return sig_blob; } -#ifndef _WIN32 ssh_string ssh_pki_do_sign_agent(ssh_session session, struct ssh_buffer_struct *buf, const ssh_key pubkey) @@ -2731,7 +2730,6 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session, return sig_blob; } -#endif /* _WIN32 */ #ifdef WITH_SERVER ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, diff --git a/src/session.c b/src/session.c index f729c491..7eacc925 100644 --- a/src/session.c +++ b/src/session.c @@ -97,12 +97,10 @@ ssh_session ssh_new(void) ssh_set_blocking(session, 1); session->maxchannel = FIRST_CHANNEL; -#ifndef _WIN32 session->agent = ssh_agent_new(session); if (session->agent == NULL) { goto err; } -#endif /* _WIN32 */ /* OPTIONS */ session->opts.StrictHostKeyChecking = 1; diff --git a/src/socket.c b/src/socket.c index d0cd015d..c7c6a9cc 100644 --- a/src/socket.c +++ b/src/socket.c @@ -28,6 +28,15 @@ #ifdef _WIN32 #include #include +#ifndef UNIX_PATH_MAX + /* Inlining the key portions of afunix.h in Windows 10 SDK; + * that header isn't available in the mingw environment. */ +#define UNIX_PATH_MAX 108 +typedef struct sockaddr_un { + ADDRESS_FAMILY sun_family; + char sun_path[UNIX_PATH_MAX]; +}; +#endif #if _MSC_VER >= 1400 #include #undef open @@ -410,7 +419,6 @@ void ssh_socket_free(ssh_socket s) SAFE_FREE(s); } -#ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path) { struct sockaddr_un sunaddr; @@ -426,24 +434,25 @@ int ssh_socket_unix(ssh_socket s, const char *path) return -1; } +#ifndef _WIN32 if (fcntl(fd, F_SETFD, 1) == -1) { ssh_set_error(s->session, SSH_FATAL, "Error from fcntl(fd, F_SETFD, 1): %s", strerror(errno)); - close(fd); + CLOSE_SOCKET(fd); return -1; } +#endif if (connect(fd, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s", strerror(errno)); - close(fd); + CLOSE_SOCKET(fd); return -1; } ssh_socket_set_fd(s,fd); return 0; } -#endif /** \internal * \brief closes a socket