diff --git a/contrib/win32/openssh/ssh-agent.vcxproj b/contrib/win32/openssh/ssh-agent.vcxproj
index 7f8bf17..d045ce6 100644
--- a/contrib/win32/openssh/ssh-agent.vcxproj
+++ b/contrib/win32/openssh/ssh-agent.vcxproj
@@ -23,8 +23,10 @@
+
+
@@ -107,8 +109,7 @@
Disabled
_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
false
-
-
+ $(OpenSSH-Src-Path);$(OpenSSL-Win32-Debug-Path)include
MultiThreadedDebug
ProgramDatabase
@@ -127,8 +128,7 @@
Disabled
_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
false
-
-
+ $(OpenSSH-Src-Path);$(OpenSSL-x64-Debug-Path)include
MultiThreadedDebug
ProgramDatabase
@@ -149,8 +149,7 @@
true
_WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
false
-
-
+ $(OpenSSH-Src-Path);$(OpenSSL-Win32-Release-Path)include
MultiThreaded
@@ -172,8 +171,7 @@
true
_WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
false
-
-
+ $(OpenSSH-Src-Path);$(OpenSSL-64-Release-Path)include
MultiThreaded
diff --git a/contrib/win32/win32compat/ssh-agent/agent-request.c b/contrib/win32/win32compat/ssh-agent/agent-request.c
new file mode 100644
index 0000000..d00d6aa
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent-request.c
@@ -0,0 +1,38 @@
+/*
+ * Author: Manoj Ampalam
+ * ssh-agent implementation on Windows
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "agent-request.h"
+
+int
+process_add_identity(struct sshbuf* request, struct sshbuf* response, HANDLE client) {
+
+ return 0;
+}
diff --git a/contrib/win32/win32compat/ssh-agent/agent-request.h b/contrib/win32/win32compat/ssh-agent/agent-request.h
new file mode 100644
index 0000000..dbb0da7
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent-request.h
@@ -0,0 +1,13 @@
+#include
+typedef unsigned char u_int8_t;
+typedef unsigned short u_int16_t;
+typedef unsigned int u_int32_t;
+typedef unsigned __int64 u_int64_t;
+#define __attribute__(a)
+#include "rsa.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "authfd.h"
+
+
+int process_add_identity(struct sshbuf*, struct sshbuf*, HANDLE);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/agent.h b/contrib/win32/win32compat/ssh-agent/agent.h
index bd40988..c146600 100644
--- a/contrib/win32/win32compat/ssh-agent/agent.h
+++ b/contrib/win32/win32compat/ssh-agent/agent.h
@@ -1,16 +1,18 @@
#include
#include
-#define BUFSIZE 5 * 1024
+#define MAX_MESSAGE_SIZE 5 * 1024
#define HEADER_SIZE 4
struct agent_connection {
OVERLAPPED ol;
HANDLE connection;
+ HANDLE client_token;
struct {
- DWORD size;
- DWORD read;
- char buf[BUFSIZE];
- } request;
+ DWORD num_bytes;
+ DWORD transferred;
+ char buf[MAX_MESSAGE_SIZE];
+ DWORD buf_size;
+ } io_buf;
enum {
LISTENING = 0,
READING_HEADER,
diff --git a/contrib/win32/win32compat/ssh-agent/connection.c b/contrib/win32/win32compat/ssh-agent/connection.c
index 11e1684..3d147da 100644
--- a/contrib/win32/win32compat/ssh-agent/connection.c
+++ b/contrib/win32/win32compat/ssh-agent/connection.c
@@ -29,20 +29,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "agent.h"
+#include "agent-request.h"
+
+void process_request(struct agent_connection*);
+
+#define ABORT_CONNECTION_RETURN(c) do { \
+ con->state = DONE; \
+ agent_cleanup_connection(con); \
+ return; \
+} while (0)
void agent_connection_on_error(struct agent_connection* con, DWORD error) {
- con->state = DONE;
- agent_cleanup_connection(con);
+ ABORT_CONNECTION_RETURN(con);
}
void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPED* ol) {
/* process error */
- if ( (bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE)) {
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ if ((bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE))
+ ABORT_CONNECTION_RETURN(c);
if (con->state == DONE)
DebugBreak();
@@ -54,56 +59,47 @@ void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPE
agent_listen();
case WRITING:
/* Writing is done, read next request */
+ /* assert on assumption that write always completes on sending all bytes*/
+ if (bytes != con->io_buf.num_bytes)
+ DebugBreak();
con->state = READING_HEADER;
- ZeroMemory(&con->request, sizeof(con->request));
- if (!ReadFile(con->connection, con->request.buf,
- HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING)) {
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ ZeroMemory(&con->io_buf, sizeof(con->io_buf));
+ if (!ReadFile(con->connection, con->io_buf.buf,
+ HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(c);
break;
case READING_HEADER:
- con->request.read += bytes;
- if (con->request.read == HEADER_SIZE) {
- con->request.size = *((DWORD*)con->request.buf);
- con->request.read = 0;
+ con->io_buf.transferred += bytes;
+ if (con->io_buf.transferred == HEADER_SIZE) {
+ con->io_buf.num_bytes = PEEK_U32(con->io_buf.buf);
+ con->io_buf.transferred = 0;
+ if (con->io_buf.num_bytes > MAX_MESSAGE_SIZE)
+ ABORT_CONNECTION_RETURN(c);
+
con->state = READING;
- if (!ReadFile(con->connection, con->request.buf,
- con->request.size, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING)) {
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ if (!ReadFile(con->connection, con->io_buf.buf,
+ con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(c);
}
else {
- if (!ReadFile(con->connection, con->request.buf + con->request.read,
- HEADER_SIZE - con->request.read, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING)) {
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.num_bytes,
+ HEADER_SIZE - con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(c);
}
break;
case READING:
- con->request.read += bytes;
- if (con->request.read == con->request.size) {
- /* process request and get response */
+ con->io_buf.transferred += bytes;
+ if (con->io_buf.transferred == con->io_buf.num_bytes) {
+ process_request(con);
con->state = WRITING;
- if (!WriteFile(con->connection, con->request.buf,
- con->request.size, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) ){
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ if (!WriteFile(con->connection, con->io_buf.buf,
+ con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
+ ABORT_CONNECTION_RETURN(c);
}
else {
- if (!ReadFile(con->connection, con->request.buf + con->request.read,
- con->request.size - con->request.read, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING)) {
- con->state = DONE;
- agent_cleanup_connection(con);
- return;
- }
+ if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.transferred,
+ con->io_buf.num_bytes - con->io_buf.transferred, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(c);
}
break;
default:
@@ -116,3 +112,48 @@ void agent_connection_disconnect(struct agent_connection* con) {
CancelIoEx(con->connection, NULL);
DisconnectNamedPipe(con->connection);
}
+
+static void
+process_request(struct agent_connection* con) {
+ int r;
+ struct sshbuf *request = NULL, *response = NULL;
+ u_char type;
+
+ request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
+ response = sshbuf_new();
+ if ((request == NULL) || (response == NULL)) {
+ r = ENOMEM;
+ goto done;
+ }
+
+ if ((r = sshbuf_get_u8(request, &type)) != 0)
+ goto done;
+
+ switch (type) {
+ case SSH2_AGENTC_ADD_IDENTITY:
+ r = process_add_identity(request, response, con->client_token);
+ break;
+ default:
+ r = EINVAL;
+ goto done;
+ }
+
+done:
+ if (request)
+ sshbuf_free(request);
+
+ ZeroMemory(&con->io_buf, sizeof(con->io_buf));
+ if (r == 0) {
+ POKE_U32(con->io_buf.buf, sshbuf_len(response));
+ memcpy(con->io_buf.buf + 4, sshbuf_ptr(response), sshbuf_len(response));
+ con->io_buf.num_bytes = sshbuf_len(response) + 4;
+ }
+ else {
+ POKE_U32(con->io_buf.buf, 1);
+ *(con->io_buf.buf + 4) = SSH_AGENT_FAILURE;
+ con->io_buf.num_bytes = 5;
+ }
+
+ if (response)
+ sshbuf_free(response);
+}
\ No newline at end of file