| 1915 |
static void update_known_hosts(PTInstVar pvar, struct hostkeys_update_ctx *ctx) |
static void update_known_hosts(PTInstVar pvar, struct hostkeys_update_ctx *ctx) |
| 1916 |
{ |
{ |
| 1917 |
size_t i; |
size_t i; |
|
char msg[128]; |
|
| 1918 |
int dlgresult; |
int dlgresult; |
| 1919 |
|
char msg[1024]; |
| 1920 |
|
char *fp; |
| 1921 |
|
|
| 1922 |
// "/nosecuritywarning"が指定されている場合、更新は一切行わない。 |
// "/nosecuritywarning"が指定されている場合、更新は一切行わない。 |
| 1923 |
if (pvar->nocheck_known_hosts) { |
if (pvar->nocheck_known_hosts) { |
| 1928 |
|
|
| 1929 |
// known_hostsファイルの更新を行うため、ユーザに問い合わせを行う。 |
// known_hostsファイルの更新を行うため、ユーザに問い合わせを行う。 |
| 1930 |
if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_ASK) { |
if (pvar->settings.UpdateHostkeys == SSH_UPDATE_HOSTKEYS_ASK) { |
| 1931 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Accept updated hostkeys? (yes/no)"); |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, |
| 1932 |
dlgresult = MessageBox(NULL, msg, "TTSSH: confirm", MB_YESNO | MB_ICONWARNING); |
"Are you sure you want to accept updated hostkeys?\n\n" |
| 1933 |
|
"A user has been received complete hostkeys from a remote server.\n" |
| 1934 |
|
"Your known_hosts file can be updated to the latest public hostkeys \n" |
| 1935 |
|
"because the file does not contain in the following keys:\n\n" |
| 1936 |
|
); |
| 1937 |
|
|
| 1938 |
|
for (i = 0; i < ctx->nkeys; i++) { |
| 1939 |
|
if (ctx->keys_seen[i]) |
| 1940 |
|
continue; |
| 1941 |
|
fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX); |
| 1942 |
|
strcat_s(msg, sizeof(msg), get_sshname_from_key(ctx->keys[i])); |
| 1943 |
|
strcat_s(msg, sizeof(msg), " "); |
| 1944 |
|
strcat_s(msg, sizeof(msg), fp); |
| 1945 |
|
strcat_s(msg, sizeof(msg), "\n"); |
| 1946 |
|
free(fp); |
| 1947 |
|
} |
| 1948 |
|
|
| 1949 |
|
dlgresult = MessageBox(NULL, msg, "TTSSH: confirm", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2); |
| 1950 |
if (dlgresult != IDYES) { |
if (dlgresult != IDYES) { |
| 1951 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because a user cancelled."); |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey was not updated because a user cancelled."); |
| 1952 |
notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE); |
notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE); |
| 1968 |
return; |
return; |
| 1969 |
} |
} |
| 1970 |
|
|
| 1971 |
static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx) |
static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx) |
| 1972 |
{ |
{ |
| 1973 |
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
| 1974 |
char msg[128]; |
char msg[128]; |
| 1975 |
char *data; |
char *data; |
| 1976 |
int len; |
int len; |
| 1979 |
buffer_t *b = NULL; |
buffer_t *b = NULL; |
| 1980 |
buffer_t *bsig = NULL; |
buffer_t *bsig = NULL; |
| 1981 |
char *cp, *sig; |
char *cp, *sig; |
| 1982 |
size_t i, ndone, siglen; |
size_t i, ndone, siglen; |
| 1983 |
int ret; |
int ret; |
| 1984 |
|
|
| 1985 |
// SSH2 packet format: |
// SSH2 packet format: |
| 1986 |
// [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)] |
// [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)] |
| 1993 |
data = pvar->ssh_state.payload; |
data = pvar->ssh_state.payload; |
| 1994 |
// len = size - (padding size + 1): パディングを除くボディ。typeが先頭に含まれる。 |
// len = size - (padding size + 1): パディングを除くボディ。typeが先頭に含まれる。 |
| 1995 |
len = pvar->ssh_state.payloadlen; |
len = pvar->ssh_state.payloadlen; |
| 1996 |
len--; // type 分を除く |
len--; // type 分を除く |
| 1997 |
|
|
| 1998 |
bsig = buffer_init(); |
bsig = buffer_init(); |
| 1999 |
if (bsig == NULL) |
if (bsig == NULL) |
| 2000 |
goto error; |
goto error; |
| 2001 |
cp = buffer_append_space(bsig, len); |
cp = buffer_append_space(bsig, len); |
| 2002 |
memcpy(cp, data, len); |
memcpy(cp, data, len); |
| 2003 |
|
|
| 2004 |
if (ctx->nnew == 0) { |
if (ctx->nnew == 0) { |
| 2005 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew); |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew); |
| 2006 |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
| 2007 |
goto error; |
goto error; |
| 2008 |
} |
} |
| 2009 |
if (type != SSH2_MSG_REQUEST_SUCCESS) { |
if (type != SSH2_MSG_REQUEST_SUCCESS) { |
| 2010 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Server failed to confirm ownership of private host keys(type %d)", type); |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Server failed to confirm ownership of private host keys(type %d)", type); |
| 2011 |
notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR); |
notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR); |
| 2012 |
goto error; |
goto error; |
| 2013 |
} |
} |
| 2014 |
if (pvar->session_id_len == 0) { |
if (pvar->session_id_len == 0) { |
| 2015 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because pvar->session_id_len %d(program bug).", pvar->session_id_len); |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because pvar->session_id_len %d(program bug).", pvar->session_id_len); |
| 2016 |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
| 2017 |
goto error; |
goto error; |
| 2018 |
} |
} |
| 2019 |
|
|
| 2020 |
b = buffer_init(); |
b = buffer_init(); |
| 2021 |
if (b == NULL) |
if (b == NULL) |
| 2022 |
goto error; |
goto error; |
| 2023 |
|
|
| 2024 |
ndone = 0; |
ndone = 0; |
| 2025 |
for (i = 0; i < ctx->nkeys; i++) { |
for (i = 0; i < ctx->nkeys; i++) { |
| 2026 |
if (ctx->keys_seen[i]) |
if (ctx->keys_seen[i]) |
| 2027 |
continue; |
continue; |
| 2028 |
|
|
| 2029 |
buffer_clear(b); |
buffer_clear(b); |
| 2030 |
buffer_put_cstring(b, "hostkeys-prove-00@openssh.com"); |
buffer_put_cstring(b, "hostkeys-prove-00@openssh.com"); |
| 2031 |
buffer_put_string(b, pvar->session_id, pvar->session_id_len); |
buffer_put_string(b, pvar->session_id, pvar->session_id_len); |
| 2032 |
key_to_blob(ctx->keys[i], &blob, &bloblen); |
key_to_blob(ctx->keys[i], &blob, &bloblen); |
| 2033 |
buffer_put_string(b, blob, bloblen); |
buffer_put_string(b, blob, bloblen); |
| 2034 |
free(blob); |
free(blob); |
| 2035 |
blob = NULL; |
blob = NULL; |
| 2036 |
|
|
| 2037 |
sig = buffer_get_string_msg(bsig, &siglen); |
sig = buffer_get_string_msg(bsig, &siglen); |
| 2038 |
// Verify signature |
// Verify signature |
| 2039 |
ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b)); |
ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b)); |
| 2040 |
free(sig); |
free(sig); |
| 2041 |
sig = NULL; |
sig = NULL; |
| 2042 |
if (ret != 1) { |
if (ret != 1) { |
| 2043 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "server gave bad signature for %s key %u", |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "server gave bad signature for %s key %u", |
| 2044 |
get_sshname_from_key(ctx->keys[i]), i); |
get_sshname_from_key(ctx->keys[i]), i); |
| 2045 |
notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR); |
notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR); |
| 2046 |
goto error; |
goto error; |
| 2047 |
} |
} |
| 2048 |
ndone++; |
ndone++; |
| 2049 |
} |
} |
| 2050 |
|
|
| 2051 |
if (ndone != ctx->nnew) { |
if (ndone != ctx->nnew) { |
| 2052 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).", |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).", |
| 2053 |
ndone, ctx->nnew); |
ndone, ctx->nnew); |
| 2054 |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL); |
| 2055 |
goto error; |
goto error; |
| 2056 |
} |
} |
| 2057 |
|
|
| 2058 |
update_known_hosts(pvar, ctx); |
update_known_hosts(pvar, ctx); |
| 2059 |
|
|
| 2060 |
error: |
error: |
| 2061 |
buffer_free(b); |
buffer_free(b); |
| 2062 |
buffer_free(bsig); |
buffer_free(bsig); |
| 2063 |
hostkeys_update_ctx_free(ctx); |
hostkeys_update_ctx_free(ctx); |
| 2064 |
} |
} |
| 2065 |
|
|
| 2066 |
// |
// |
| 2190 |
buffer_put_cstring(b, "hostkeys-prove-00@openssh.com"); |
buffer_put_cstring(b, "hostkeys-prove-00@openssh.com"); |
| 2191 |
buffer_put_char(b, 1); /* bool: want reply */ |
buffer_put_char(b, 1); /* bool: want reply */ |
| 2192 |
|
|
| 2193 |
for (i = 0; i < ctx->nkeys; i++) { |
for (i = 0; i < ctx->nkeys; i++) { |
| 2194 |
if (ctx->keys_seen[i]) |
if (ctx->keys_seen[i]) |
| 2195 |
continue; |
continue; |
| 2196 |
key_to_blob(ctx->keys[i], &blob, &len); |
key_to_blob(ctx->keys[i], &blob, &len); |
| 2197 |
buffer_put_string(b, blob, len); |
buffer_put_string(b, blob, len); |
| 2198 |
free(blob); |
free(blob); |
| 2199 |
blob = NULL; |
blob = NULL; |
| 2200 |
} |
} |
| 2201 |
|
|
| 2202 |
len = buffer_len(b); |
len = buffer_len(b); |
| 2203 |
outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len); |
outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len); |
| 2204 |
memcpy(outmsg, buffer_ptr(b), len); |
memcpy(outmsg, buffer_ptr(b), len); |