[Ttssh2-commit] [5846] チケット #35047 SSH サーバホスト公開鍵の自動更新

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2015年 5月 4日 (月) 01:46:30 JST


Revision: 5846
          http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5846
Author:   yutakapon
Date:     2015-05-04 01:46:29 +0900 (Mon, 04 May 2015)
Log Message:
-----------
チケット #35047 SSH サーバホスト公開鍵の自動更新

known_hosts ファイルを検索する関数(host key rotation用)を追加した。

Ticket Links:
------------
    http://sourceforge.jp/projects/ttssh2/tracker/detail/35047

Modified Paths:
--------------
    trunk/ttssh2/ttxssh/hosts.c
    trunk/ttssh2/ttxssh/hosts.h
    trunk/ttssh2/ttxssh/key.c

-------------- next part --------------
Modified: trunk/ttssh2/ttxssh/hosts.c
===================================================================
--- trunk/ttssh2/ttxssh/hosts.c	2015-05-01 13:27:34 UTC (rev 5845)
+++ trunk/ttssh2/ttxssh/hosts.c	2015-05-03 16:46:29 UTC (rev 5846)
@@ -765,6 +765,213 @@
 	finish_read_host_files(pvar, 1);
 }
 
+
+// known_hosts\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x8AY\x93\x96\x82\xB7\x82\xE9\x83L\x81[\x8F\xEE\x95\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+//
+// return:
+//   *keyptr != NULL  \x8E擾\x90\xAC\x8C\xF7
+//
+static int parse_hostkey_file(PTInstVar pvar, char FAR * hostname,
+	unsigned short tcpport, char FAR * data, Key **keyptr)
+{
+	int index = eat_spaces(data);
+	int matched = 0;
+	int keybits = 0;
+	ssh_keytype ktype;
+
+	*keyptr = NULL;
+
+	if (data[index] == '#') {
+		return index + eat_to_end_of_line(data + index);
+	}
+
+	/* if we find an empty line, then it won't have any patterns matching the hostname
+	and so we skip it */
+	index--;
+	do {
+		int negated;
+		int bracketed;
+		char *end_bracket;
+		int host_matched = 0;
+		unsigned short keyfile_port = 22;
+
+		index++;
+		negated = data[index] == '!';
+
+		if (negated) {
+			index++;
+			bracketed = data[index] == '[';
+			if (bracketed) {
+				end_bracket = strstr(data + index + 1, "]:");
+				if (end_bracket != NULL) {
+					*end_bracket = ' ';
+					index++;
+				}
+			}
+			host_matched = match_pattern(data + index, hostname);
+			if (bracketed && end_bracket != NULL) {
+				*end_bracket = ']';
+				keyfile_port = atoi(end_bracket + 2);
+			}
+			if (host_matched && keyfile_port == tcpport) {
+				return index + eat_to_end_of_line(data + index);
+			}
+		}
+		else {
+			bracketed = data[index] == '[';
+			if (bracketed) {
+				end_bracket = strstr(data + index + 1, "]:");
+				if (end_bracket != NULL) {
+					*end_bracket = ' ';
+					index++;
+				}
+			}
+			host_matched = match_pattern(data + index, hostname);
+			if (bracketed && end_bracket != NULL) {
+				*end_bracket = ']';
+				keyfile_port = atoi(end_bracket + 2);
+			}
+			if (host_matched && keyfile_port == tcpport) {
+				matched = 1;
+			}
+		}
+
+		index += eat_to_end_of_pattern(data + index);
+	} while (data[index] == ',');
+
+	if (!matched) {
+		return index + eat_to_end_of_line(data + index);
+	}
+	else {
+		// \x8C\xAE\x82̎\xED\x97ނɂ\xE6\x82\xE8\x83t\x83H\x81[\x83}\x83b\x83g\x82\xAA\x88قȂ\xE9
+		// \x82܂\xBD\x81A\x8Dŏ\x89\x82Ɉ\xEA\x92v\x82\xB5\x82\xBD\x83G\x83\x93\x83g\x83\x8A\x82\xF0\x8E擾\x82\xB7\x82邱\x82ƂɂȂ\xE9\x81B
+		/*
+		[SSH1]
+		192.168.1.2 1024 35 13032....
+
+		[SSH2]
+		192.168.1.2 ssh-rsa AAAAB3NzaC1....
+		192.168.1.2 ssh-dss AAAAB3NzaC1....
+		192.168.1.2 rsa AAAAB3NzaC1....
+		192.168.1.2 dsa AAAAB3NzaC1....
+		192.168.1.2 rsa1 AAAAB3NzaC1....
+		*/
+		int rsa1_key_bits;
+
+		index += eat_spaces(data + index);
+
+		rsa1_key_bits = atoi(data + index);
+		if (rsa1_key_bits > 0) { // RSA1\x82ł\xA0\x82\xE9
+			if (!SSHv1(pvar)) { // SSH2\x90ڑ\xB1\x82ł\xA0\x82\xEA\x82Ζ\xB3\x8E\x8B\x82\xB7\x82\xE9
+				return index + eat_to_end_of_line(data + index);
+			}
+			index += eat_digits(data + index);
+			index += eat_spaces(data + index);
+
+			index += eat_digits(data + index);
+			index += eat_spaces(data + index);
+
+		}
+		else {
+			char *cp, *p;
+			Key *key;
+
+			if (!SSHv2(pvar)) { // SSH1\x90ڑ\xB1\x82ł\xA0\x82\xEA\x82Ζ\xB3\x8E\x8B\x82\xB7\x82\xE9
+				return index + eat_to_end_of_line(data + index);
+			}
+
+			cp = data + index;
+			p = strchr(cp, ' ');
+			if (p == NULL) {
+				return index + eat_to_end_of_line(data + index);
+			}
+			index += (p - cp);  // setup index
+			*p = '\0';
+			ktype = get_keytype_from_name(cp);
+			*p = ' ';
+
+			index += eat_spaces(data + index);  // update index
+
+			// uudecode
+			key = parse_uudecode(data + index);
+			if (key == NULL) {
+				return index + eat_to_end_of_line(data + index);
+			}
+
+			// setup
+			*keyptr = key;
+
+			index += eat_base64(data + index);
+			index += eat_spaces(data + index);
+		}
+
+		return index + eat_to_end_of_line(data + index);
+	}
+}
+
+// known_hosts\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x83z\x83X\x83g\x8C\xF6\x8AJ\x8C\xAE\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+// \x8A\xF9\x91\xB6\x82̏\x88\x97\x9D\x82\xF0\x89\xFC\x95ς\xB5\x82\xBD\x82\xAD\x82Ȃ\xA2\x82̂ŁAHost key rotation\x97p\x82ɐV\x8BK\x82ɗp\x88ӂ\xB7\x82\xE9\x81B
+//
+// return 1: success
+//        0: fail
+int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx)
+{
+	int success = 0;
+	int suppress_errors = 1;
+	unsigned short tcpport;
+	char FAR *filename;
+	char *hostname;
+	Key *key;
+
+	if (!begin_read_host_files(pvar, 1)) {
+		goto error;
+	}
+
+	// Host key rotation\x82ł́Aknown_hosts \x83t\x83@\x83C\x83\x8B\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x82̂ŁA
+	// \x8C\x9F\x8D\x{142DC2}\xE9\x82̂\xCD1\x82‚߂̃t\x83@\x83C\x83\x8B\x82݂̂ł悢\x81i2\x82‚߂̃t\x83@\x83C\x83\x8B\x82\xCDReadOnly\x82̂\xBD\x82߁j\x81B
+	filename = pvar->hosts_state.file_names[pvar->hosts_state.file_num];
+	pvar->hosts_state.file_num++;
+
+	pvar->hosts_state.file_data_index = -1;
+	if (filename[0] != 0) {
+		if (begin_read_file(pvar, filename, suppress_errors)) {
+			pvar->hosts_state.file_data_index = 0;
+		}
+	}
+	if (pvar->hosts_state.file_data_index == -1)
+		goto error;
+
+	// \x8C\x9F\x8D\xF5\x91ΏۂƂȂ\xE9\x83z\x83X\x83g\x96\xBC\x82ƃ|\x81[\x83g\x94ԍ\x86\x81B
+	hostname = pvar->ssh_state.hostname;
+	tcpport = pvar->ssh_state.tcpport;
+
+	// known_hosts\x83t\x83@\x83C\x83\x8B\x82̓\xE0\x97e\x82\xAA\x82\xB7\x82ׂ\xC4 pvar->hosts_state.file_data \x82ɓǂݍ\x9E\x82܂\xEA\x82Ă\xA2\x82\xE9\x81B
+	// \x96\x96\x94\xF6\x82\xCD \0 \x81B
+	while (pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] != 0) {
+		key = NULL;
+
+		pvar->hosts_state.file_data_index +=
+			parse_hostkey_file(pvar, hostname, tcpport,
+				pvar->hosts_state.file_data +
+				pvar->hosts_state.file_data_index,
+				&key);
+
+		if (key != NULL) {
+			key = key;
+			key_free(key);
+		}
+
+	}
+
+	success = 1;
+
+error:
+	finish_read_host_files(pvar, 1);
+
+	return (success);
+}
+
+
 static BOOL equal_mp_ints(unsigned char FAR * num1,
                           unsigned char FAR * num2)
 {

Modified: trunk/ttssh2/ttxssh/hosts.h
===================================================================
--- trunk/ttssh2/ttxssh/hosts.h	2015-05-01 13:27:34 UTC (rev 5845)
+++ trunk/ttssh2/ttxssh/hosts.h	2015-05-03 16:46:29 UTC (rev 5846)
@@ -55,6 +55,8 @@
   HWND hosts_dialog;
 } HOSTSState;
 
+typedef int hostkeys_foreach_fn(void *ctx);
+
 void HOSTS_init(PTInstVar pvar);
 void HOSTS_open(PTInstVar pvar);
 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport);
@@ -72,5 +74,6 @@
 int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize);
 
 int HOSTS_compare_public_key(Key *src, Key *key);
+int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx);
 
 #endif

Modified: trunk/ttssh2/ttxssh/key.c
===================================================================
--- trunk/ttssh2/ttxssh/key.c	2015-05-01 13:27:34 UTC (rev 5845)
+++ trunk/ttssh2/ttxssh/key.c	2015-05-03 16:46:29 UTC (rev 5846)
@@ -1968,6 +1968,8 @@
 		goto error;
 	}
 
+	//HOSTS_hostkey_foreach(pvar, NULL, ctx);
+
 	success = 1;
 
 error:



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