[ttssh2-commit] [10699] sshagentc に ssh1 に関連する関数を実装した

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2023年 5月 13日 (土) 22:34:22 JST


Revision: 10699
          https://osdn.net/projects/ttssh2/scm/svn/commits/10699
Author:   zmatsuo
Date:     2023-05-13 22:34:22 +0900 (Sat, 13 May 2023)
Log Message:
-----------
sshagentc に ssh1 に関連する関数を実装した

- putty_get_ssh1_keylist()
- putty_get_ssh1_keylen()
- putty_hash_ssh1_challenge()

Ticket #45653

Ticket Links:
------------
    https://osdn.net/projects/ttssh2/tracker/detail/45653

Modified Paths:
--------------
    trunk/ttssh2/libsshagentc/sshagentc/agentc.cpp

-------------- next part --------------
Modified: trunk/ttssh2/libsshagentc/sshagentc/agentc.cpp
===================================================================
--- trunk/ttssh2/libsshagentc/sshagentc/agentc.cpp	2023-05-13 13:34:11 UTC (rev 10698)
+++ trunk/ttssh2/libsshagentc/sshagentc/agentc.cpp	2023-05-13 13:34:22 UTC (rev 10699)
@@ -48,6 +48,7 @@
 #define PUTTY_SHM		1	// pageant shared memory
 #define PUTTY_NAMEDPIPE	1	// pageant named pipe
 #define MS_NAMEDPIPE	1	// Microsoft agent
+#define SSH1_ENABLE		1
 
 // SSH Agent
 //	Message numbers
@@ -68,6 +69,14 @@
 #define SSH_AGENT_IDENTITIES_ANSWER				12
 #define SSH_AGENT_SIGN_RESPONSE					14
 
+// ssh1
+#if SSH1_ENABLE
+#define SSH1_AGENTC_REQUEST_RSA_IDENTITIES		1
+#define SSH1_AGENT_RSA_IDENTITIES_ANSWER		2
+#define SSH1_AGENTC_RSA_CHALLENGE				3
+#define SSH1_AGENT_RSA_RESPONSE					4
+#endif
+
 #if PUTTY_SHM
 static PSID usersid;
 #endif
@@ -78,6 +87,13 @@
 			((uint32_t)p[1] << 16) | ((uint32_t)p[0] << 24));
 }
 
+#if SSH1_ENABLE
+static uint16_t get_uint16(const uint8_t *p)
+{
+	return ((uint32_t)p[1] | ((uint32_t)p[0] << 8));
+}
+#endif
+
 /**
  *	pageant \x82\xCC named pipe\x96\xBC\x82̈ꕔ
  *	from putty windows/utils/cryptapi.c
@@ -539,32 +555,47 @@
 	return r;
 }
 
-// https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04#section-4.4
-int putty_get_ssh2_keylist(unsigned char **keylist)
+static int putty_get_keylist(unsigned char **keylist, uint8_t req_byte, uint8_t rep_byte)
 {
 	Buffer req;
 	req.append_uint32(1);
-	req.append_byte(SSH_AGENTC_REQUEST_IDENTITIES);
+	req.append_byte(req_byte);
 
 	Buffer rep;
 	query(req, rep);
 
-	// check
-	const uint8_t *reply_ptr = (uint8_t *)rep.get_ptr();
-	uint32_t reply_len = get_uint32(reply_ptr);
-	if (rep.size() != reply_len + 4 || reply_ptr[4] != SSH_AGENT_IDENTITIES_ANSWER) {
-		*keylist = NULL;
-		return 0;
+	uint32_t key_blob_len;
+	uint8_t *key_blob_ptr;
+	if (rep.size() < 4) {
+	error:
+		key_blob_len = 0;
+		key_blob_ptr = NULL;
 	}
+	else {
+		// check
+		const uint8_t *reply_ptr = (uint8_t *)rep.get_ptr();
+		uint32_t reply_len = get_uint32(reply_ptr);
+		if (rep.size() < reply_len + 4 || reply_ptr[4] != rep_byte) {
+			key_blob_len = 0;
+			key_blob_ptr = NULL;
+			goto error;
+		}
+		key_blob_len = reply_len - (4+1);
+		key_blob_ptr = (uint8_t *)malloc(key_blob_len);
+		memcpy(key_blob_ptr, reply_ptr + (4+1), key_blob_len);
+	}
 
-	uint32_t key_blob_len = reply_len - (4+1);
-	uint8_t *key_blob_ptr = (uint8_t *)malloc(key_blob_len);
-	memcpy(key_blob_ptr, reply_ptr + (4+1), key_blob_len);
-
 	*keylist = key_blob_ptr;
 	return key_blob_len;
 }
 
+// https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04#section-4.4
+int putty_get_ssh2_keylist(unsigned char **keylist)
+{
+	return putty_get_keylist(keylist, SSH_AGENTC_REQUEST_IDENTITIES, SSH_AGENT_IDENTITIES_ANSWER);
+}
+
+// https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04#section-4.5
 void *putty_sign_ssh2_key(unsigned char *pubkey,
 						  unsigned char *data,
 						  int datalen,
@@ -599,8 +630,12 @@
 
 int putty_get_ssh1_keylist(unsigned char **keylist)
 {
-	(void)keylist;
+#if SSH1_ENABLE
+	return putty_get_keylist(keylist, SSH1_AGENTC_REQUEST_RSA_IDENTITIES, SSH1_AGENT_RSA_IDENTITIES_ANSWER);
+#else
+	*keylist = NULL;
 	return 0;
+#endif
 }
 
 void *putty_hash_ssh1_challenge(unsigned char *pubkey,
@@ -610,20 +645,107 @@
 								unsigned char *session_id,
 								int *outlen)
 {
+#if SSH1_ENABLE
+	Buffer req;
+	req.append_byte(SSH1_AGENTC_RSA_CHALLENGE);
+	req.append_array(pubkey, pubkeylen);
+	req.append_array(data, datalen);
+	req.append_array(session_id, 16);
+	req.append_uint32(1); // response format
+	req.prepend_uint32((uint32_t)req.size());
+
+	Buffer rep;
+	query(req, rep);
+
+	uint32_t ret_len;
+	uint8_t *ret_ptr;
+	if (rep.size() < 4) {
+	error:
+		ret_ptr = NULL;
+		ret_len = 0;
+	}
+	else {
+		const uint8_t *reply_ptr = (uint8_t *)rep.get_ptr();
+		uint32_t reply_len = get_uint32(reply_ptr);
+		if (reply_len != (uint32_t)(rep.size() - 4)) {
+			goto error;
+		}
+		if (reply_len < 1 + 16 || reply_ptr[4] != SSH1_AGENT_RSA_RESPONSE) {
+			goto error;
+		}
+		ret_len = (uint32_t)(reply_len - 1);
+		ret_ptr = (uint8_t *)malloc(ret_len);
+		memcpy(ret_ptr, reply_ptr + (4+1), ret_len);
+	}
+#else
 	(void)pubkey;
 	(void)pubkeylen;
 	(void)data;
 	(void)datalen;
 	(void)session_id;
-	(void)outlen;
-	return NULL;
+	uint32_t ret_len = 0;
+	uint8_t *ret_ptr = NULL;
+#endif
+
+	if (outlen)
+		*outlen = ret_len;
+
+	return ret_ptr;
 }
 
+#if SSH1_ENABLE
+static int mp_ssh1(const uint8_t *data, int len)
+{
+	if (len < 2) {
+		return 0;
+	}
+	int bit_len = get_uint16(data);
+	len -= 2;
+	data += 2;
+	int byte_len = (int)((bit_len + 7) / 8);
+	if (len < byte_len) {
+		return 0;
+	}
+	return 2 + byte_len;
+}
+#endif
+
 int putty_get_ssh1_keylen(unsigned char *key, int maxlen)
 {
+#if SSH1_ENABLE
+	int left = maxlen;
+	const uint8_t *key_ptr = key;
+
+	// 4byte
+	if (left < 4) {
+	error:
+		return 0;
+	}
+	key_ptr += 4;
+	left -= 4;
+
+	// mp
+	int len = mp_ssh1(key_ptr, left);
+	if (len == 0) {
+		goto error;
+	}
+	left -= len;
+	key_ptr += len;
+
+	// mp
+	len = mp_ssh1(key_ptr, left);
+	if (left == 0) {
+		goto error;
+	}
+	left -= len;
+	key_ptr += len;
+
+	return maxlen - left;
+#else
 	(void)key;
 	(void)maxlen;
 	return 0;
+#endif
 }
 
 const char *putty_get_version()
@@ -665,7 +787,7 @@
 static BOOL check_puttyagent_wm_copydata()
 {
 	HWND hwnd;
-	hwnd = FindWindow("Pageant", "Pageant");
+	hwnd = FindWindowA("Pageant", "Pageant");
 	if (!hwnd)
 		return false;
 	else


ttssh2-commit メーリングリストの案内
Back to archive index