Add support for pageant in libssh.

This commit is contained in:
KingToolbox 2020-10-18 15:39:32 +08:00
parent ef43da390e
commit 95c30ebc9c
6 changed files with 105 additions and 20 deletions

View File

@ -71,13 +71,14 @@
#define SSH_AGENT_RSA_SHA2_512 0x04
struct ssh_agent_struct {
#ifndef _WIN32
struct ssh_socket_struct *sock;
#endif
ssh_buffer ident;
unsigned int count;
ssh_channel channel;
};
#ifndef _WIN32
/* agent.c */
/**
* @brief Create a new ssh agent structure.
@ -115,6 +116,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 */

View File

@ -34,10 +34,8 @@ typedef struct ssh_public_key_struct* ssh_public_key;
LIBSSH_API int ssh_auth_list(ssh_session session);
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
#ifndef _WIN32
LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
ssh_public_key publickey);
#endif
LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase);
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
const char *filename, const char *passphrase);

View File

@ -730,7 +730,9 @@ LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socke
fd_set *readfds, struct timeval *timeout);
LIBSSH_API int ssh_service_request(ssh_session session, const char *service);
LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel);
#ifndef _WIN32
LIBSSH_API int ssh_set_agent_socket(ssh_session session, socket_t fd);
#endif
LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking);
LIBSSH_API void ssh_set_counters(ssh_session session, ssh_counter scounter,
ssh_counter rcounter);
@ -749,10 +751,8 @@ LIBSSH_API int ssh_userauth_try_publickey(ssh_session session,
LIBSSH_API int ssh_userauth_publickey(ssh_session session,
const char *username,
const ssh_key privkey);
#ifndef _WIN32
LIBSSH_API int ssh_userauth_agent(ssh_session session,
const char *username);
#endif
LIBSSH_API int ssh_userauth_publickey_auto(ssh_session session,
const char *username,
const char *passphrase);

View File

@ -33,7 +33,6 @@
* the agent returns the signed data
*/
#ifndef _WIN32
#include "config.h"
@ -46,9 +45,6 @@
#include <unistd.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include "libssh/agent.h"
#include "libssh/priv.h"
#include "libssh/socket.h"
@ -58,11 +54,21 @@
#include "libssh/pki.h"
#include "libssh/bytearray.h"
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <Windows.h>
#endif
#define AGENT_MSG_MAXLEN 256 * 1024
/* macro to check for "agent failure" message */
#define agent_failed(x) \
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \
((x) == SSH2_AGENT_FAILURE))
#ifndef _WIN32
static size_t atomicio(struct ssh_agent_struct *agent, void *buf, size_t n, int do_read) {
char *b = buf;
size_t pos = 0;
@ -122,6 +128,7 @@ static size_t atomicio(struct ssh_agent_struct *agent, void *buf, size_t n, int
return pos;
}
}
#endif
ssh_agent ssh_agent_new(struct ssh_session_struct *session) {
ssh_agent agent = NULL;
@ -133,12 +140,16 @@ ssh_agent ssh_agent_new(struct ssh_session_struct *session) {
ZERO_STRUCTP(agent);
agent->count = 0;
#ifndef _WIN32
agent->sock = ssh_socket_new(session);
if (agent->sock == NULL) {
SAFE_FREE(agent);
return NULL;
}
agent->channel = NULL;
#endif
return agent;
}
@ -165,6 +176,7 @@ int ssh_set_agent_channel(ssh_session session, ssh_channel channel){
return SSH_OK;
}
#ifndef _WIN32
/** @brief sets the SSH agent socket.
* The SSH agent will be used to authenticate this client using
* the given socket to communicate with the ssh-agent. The caller
@ -192,20 +204,24 @@ void ssh_agent_close(struct ssh_agent_struct *agent) {
ssh_socket_close(agent->sock);
}
#endif
void ssh_agent_free(ssh_agent agent) {
if (agent) {
if (agent->ident) {
SSH_BUFFER_FREE(agent->ident);
}
#ifndef _WIN32
if (agent->sock) {
ssh_agent_close(agent);
ssh_socket_free(agent->sock);
}
#endif
SAFE_FREE(agent);
}
}
#ifndef _WIN32
static int agent_connect(ssh_session session) {
const char *auth_sock = NULL;
@ -227,6 +243,7 @@ static int agent_connect(ssh_session session) {
return -1;
}
#endif
#if 0
static int agent_decode_reply(struct ssh_session_struct *session, int type) {
@ -248,6 +265,8 @@ static int agent_decode_reply(struct ssh_session_struct *session, int type) {
}
#endif
#ifndef _WIN32
static int agent_talk(struct ssh_session_struct *session,
struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) {
uint32_t len = 0;
@ -280,7 +299,7 @@ static int agent_talk(struct ssh_session_struct *session,
}
len = PULL_BE_U32(payload, 0);
if (len > 256 * 1024) {
if (len > AGENT_MSG_MAXLEN) {
ssh_set_error(session, SSH_FATAL,
"Authentication response too long: %u", len);
return -1;
@ -307,6 +326,78 @@ static int agent_talk(struct ssh_session_struct *session,
return 0;
}
#else
#define AGENT_COPYDATA_ID 0x804e50ba;
static int agent_talk(struct ssh_session_struct *session,
struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) {
HWND hwnd = FindWindow("Pageant", "Pageant");
if (hwnd == NULL) {
ssh_set_error(session, SSH_FATAL,
"Pageant message window not found: %u", GetLastError());
return -1;
}
char map_name[39];
sprintf(map_name, "libssh_agent_%08x_%016zx",
GetCurrentProcessId(), (size_t)session->agent);
HANDLE hmap = CreateFileMapping(NULL, NULL, PAGE_READWRITE,
0, AGENT_MSG_MAXLEN + sizeof(uint32_t), map_name);
if (hmap == NULL) {
ssh_set_error(session, SSH_FATAL,
"Failed to create file mapping: %u", GetLastError());
return -1;
}
char *buf = MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (buf == NULL) {
ssh_set_error(session, SSH_FATAL,
"Failed to map the file mapping into memory: %u", GetLastError());
CloseHandle(hmap);
return -1;
}
uint32_t len = ssh_buffer_get_len(request);
SSH_LOG(SSH_LOG_TRACE, "Request length: %u", len);
PUSH_BE_U32(buf, 0, len);
memcpy(buf + sizeof(uint32_t), ssh_buffer_get(request), len);
COPYDATASTRUCT data;
data.dwData = AGENT_COPYDATA_ID;
data.cbData = strlen(map_name) + 1;
data.lpData = map_name;
if (SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data) < 0) {
ssh_set_error(session, SSH_FATAL, "Pageant returned an error");
UnmapViewOfFile(buf);
CloseHandle(hmap);
return -1;
}
len = PULL_BE_U32(buf, 0);
if (len > AGENT_MSG_MAXLEN) {
ssh_set_error(session, SSH_FATAL,
"Authentication response too long: %u", len);
UnmapViewOfFile(buf);
CloseHandle(hmap);
return -1;
}
SSH_LOG(SSH_LOG_TRACE, "Response length: %u", len);
int rc = ssh_buffer_add_data(reply, buf + sizeof(uint32_t), len);
UnmapViewOfFile(buf);
CloseHandle(hmap);
if (rc < 0) {
SSH_LOG(SSH_LOG_WARN, "Not enough space");
return -1;
}
return 0;
}
#endif /* _WIN32 */
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
{
ssh_buffer request = NULL;
@ -459,6 +550,7 @@ int ssh_agent_is_running(ssh_session session) {
return 0;
}
#ifndef _WIN32
if (ssh_socket_is_open(session->agent->sock)) {
return 1;
} else {
@ -470,6 +562,10 @@ int ssh_agent_is_running(ssh_session session) {
}
return 0;
#else
HWND hwnd = FindWindow("Pageant", "Pageant");
return hwnd != NULL;
#endif
}
ssh_string ssh_agent_sign_data(ssh_session session,
@ -591,4 +687,3 @@ ssh_string ssh_agent_sign_data(ssh_session session,
return sig_blob;
}
#endif /* _WIN32 */

View File

@ -2372,7 +2372,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)
@ -2422,7 +2421,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,

View File

@ -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;
@ -242,9 +240,7 @@ void ssh_free(ssh_session session)
crypto_free(session->current_crypto);
crypto_free(session->next_crypto);
#ifndef _WIN32
ssh_agent_free(session->agent);
#endif /* _WIN32 */
ssh_key_free(session->srv.dsa_key);
session->srv.dsa_key = NULL;
@ -292,9 +288,7 @@ void ssh_free(ssh_session session)
}
ssh_list_free(session->out_queue);
#ifndef _WIN32
ssh_agent_state_free (session->agent_state);
#endif
session->agent_state = NULL;
SAFE_FREE(session->auth.auto_state);