| 548 |
} |
} |
| 549 |
|
|
| 550 |
|
|
| 551 |
char* key_fingerprint_raw(Key *k, enum fp_type dgst_type, int *dgst_raw_length) |
char* key_fingerprint_raw(Key *k, enum digest_algorithm dgst_alg, int *dgst_raw_length) |
| 552 |
{ |
{ |
| 553 |
const EVP_MD *md = NULL; |
const EVP_MD *md = NULL; |
| 554 |
EVP_MD_CTX ctx; |
EVP_MD_CTX ctx; |
| 560 |
|
|
| 561 |
*dgst_raw_length = 0; |
*dgst_raw_length = 0; |
| 562 |
|
|
| 563 |
switch (dgst_type) { |
switch (dgst_alg) { |
| 564 |
case SSH_FP_MD5: |
case SSH_DIGEST_MD5: |
| 565 |
md = EVP_md5(); |
md = EVP_md5(); |
| 566 |
break; |
break; |
| 567 |
case SSH_FP_SHA1: |
case SSH_DIGEST_SHA1: |
| 568 |
md = EVP_sha1(); |
md = EVP_sha1(); |
| 569 |
break; |
break; |
| 570 |
case SSH_FP_SHA256: |
case SSH_DIGEST_SHA256: |
| 571 |
md = EVP_sha256(); |
md = EVP_sha256(); |
| 572 |
break; |
break; |
| 573 |
default: |
default: |
| 603 |
break; |
break; |
| 604 |
|
|
| 605 |
default: |
default: |
| 606 |
//fatal("key_fingerprint_raw: bad key type %d", k->type); |
//fatal("key_fingerprint_raw: bad key type %d", dgst_alg); |
| 607 |
break; |
break; |
| 608 |
} |
} |
| 609 |
|
|
| 667 |
return 0; |
return 0; |
| 668 |
} |
} |
| 669 |
|
|
| 670 |
|
// based on OpenSSH 7.1 |
| 671 |
static char * |
static char * |
| 672 |
key_fingerprint_b64(u_char *dgst_raw, u_int dgst_raw_len) |
key_fingerprint_b64(const char *alg, u_char *dgst_raw, u_int dgst_raw_len) |
| 673 |
{ |
{ |
| 674 |
char *retval; |
char *retval; |
| 675 |
unsigned int i, retval_len; |
unsigned int i, retval_len; |
| 676 |
BIO *bio, *b64; |
BIO *bio, *b64; |
| 677 |
BUF_MEM *bufferPtr; |
BUF_MEM *bufferPtr; |
| 678 |
|
|
| 679 |
retval_len = ((dgst_raw_len + 2) / 3) * 4 + 1; |
retval_len = strlen(alg) + 1 + ((dgst_raw_len + 2) / 3) * 4 + 1; |
| 680 |
retval = malloc(retval_len); |
retval = malloc(retval_len); |
| 681 |
retval[0] = '\0'; |
retval[0] = '\0'; |
| 682 |
|
|
| 683 |
|
strncat_s(retval, retval_len, alg, _TRUNCATE); |
| 684 |
|
strncat_s(retval, retval_len, ":", _TRUNCATE); |
| 685 |
|
|
| 686 |
b64 = BIO_new(BIO_f_base64()); |
b64 = BIO_new(BIO_f_base64()); |
| 687 |
bio = BIO_new(BIO_s_mem()); |
bio = BIO_new(BIO_s_mem()); |
| 688 |
bio = BIO_push(b64, bio); |
bio = BIO_push(b64, bio); |
| 704 |
} |
} |
| 705 |
|
|
| 706 |
static char * |
static char * |
| 707 |
key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) |
key_fingerprint_hex(const char *alg, u_char *dgst_raw, u_int dgst_raw_len) |
| 708 |
{ |
{ |
| 709 |
char *retval; |
char *retval; |
| 710 |
unsigned int i, retval_len; |
unsigned int i, retval_len; |
| 711 |
|
|
| 712 |
retval_len = dgst_raw_len * 3 + 1; |
retval_len = strlen(alg) + 1 + dgst_raw_len * 3 + 1; |
| 713 |
retval = malloc(retval_len); |
retval = malloc(retval_len); |
| 714 |
retval[0] = '\0'; |
retval[0] = '\0'; |
| 715 |
|
|
| 716 |
|
strncat_s(retval, retval_len, alg, _TRUNCATE); |
| 717 |
|
strncat_s(retval, retval_len, ":", _TRUNCATE); |
| 718 |
|
|
| 719 |
for (i = 0; i < dgst_raw_len; i++) { |
for (i = 0; i < dgst_raw_len; i++) { |
| 720 |
char hex[4]; |
char hex[4]; |
| 721 |
_snprintf_s(hex, sizeof(hex), _TRUNCATE, "%02x:", dgst_raw[i]); |
_snprintf_s(hex, sizeof(hex), _TRUNCATE, "%02x:", dgst_raw[i]); |
| 728 |
return (retval); |
return (retval); |
| 729 |
} |
} |
| 730 |
|
|
|
// based on OpenSSH 5.1 |
|
| 731 |
#define FLDBASE 8 |
#define FLDBASE 8 |
| 732 |
#define FLDSIZE_Y (FLDBASE + 1) |
#define FLDSIZE_Y (FLDBASE + 1) |
| 733 |
#define FLDSIZE_X (FLDBASE * 2 + 1) |
#define FLDSIZE_X (FLDBASE * 2 + 1) |
| 734 |
static char * |
static char * |
| 735 |
key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) |
key_fingerprint_randomart(const char *alg, u_char *dgst_raw, u_int dgst_raw_len, const Key *k) |
| 736 |
{ |
{ |
| 737 |
/* |
/* |
| 738 |
* Chars to be used after each other every time the worm |
* Chars to be used after each other every time the worm |
| 739 |
* intersects with itself. Matter of taste. |
* intersects with itself. Matter of taste. |
| 740 |
*/ |
*/ |
| 741 |
char *augmentation_string = " .o+=*BOX@%&#/^SE"; |
char *augmentation_string = " .o+=*BOX@%&#/^SE"; |
| 742 |
char *retval, *p; |
char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; |
| 743 |
unsigned char field[FLDSIZE_X][FLDSIZE_Y]; |
unsigned char field[FLDSIZE_X][FLDSIZE_Y]; |
| 744 |
unsigned int i, b; |
size_t i, tlen, hlen; |
| 745 |
int x, y; |
unsigned int b; |
| 746 |
|
int x, y, r; |
| 747 |
size_t len = strlen(augmentation_string) - 1; |
size_t len = strlen(augmentation_string) - 1; |
| 748 |
|
|
| 749 |
retval = calloc(1, (FLDSIZE_X + 3 + 1) * (FLDSIZE_Y + 2)); |
retval = calloc((FLDSIZE_X + 3 + 1), (FLDSIZE_Y + 2)); |
| 750 |
|
|
| 751 |
/* initialize field */ |
/* initialize field */ |
| 752 |
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); |
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); |
| 770 |
y = min(y, FLDSIZE_Y - 1); |
y = min(y, FLDSIZE_Y - 1); |
| 771 |
|
|
| 772 |
/* augment the field */ |
/* augment the field */ |
| 773 |
field[x][y]++; |
if (field[x][y] < len - 2) |
| 774 |
|
field[x][y]++; |
| 775 |
input = input >> 2; |
input = input >> 2; |
| 776 |
} |
} |
| 777 |
} |
} |
| 780 |
field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; |
field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; |
| 781 |
field[x][y] = len; |
field[x][y] = len; |
| 782 |
|
|
| 783 |
/* fill in retval */ |
/* assemble title */ |
| 784 |
_snprintf_s(retval, FLDSIZE_X, _TRUNCATE, "+--[%4s %4u]", ssh_key_type(k->type), key_size(k)); |
r = _snprintf_s(title, sizeof(title), _TRUNCATE, "[%s %u]", |
| 785 |
p = strchr(retval, '\0'); |
ssh_key_type(k->type), key_size(k)); |
| 786 |
|
/* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ |
| 787 |
|
if (r < 0 || r >(int)sizeof(title)) |
| 788 |
|
r = _snprintf_s(title, sizeof(title), _TRUNCATE, "[%s]", |
| 789 |
|
ssh_key_type(k->type)); |
| 790 |
|
tlen = (r <= 0) ? 0 : strlen(title); |
| 791 |
|
|
| 792 |
|
/* assemble hash ID. */ |
| 793 |
|
r = _snprintf_s(hash, sizeof(hash), _TRUNCATE, "[%s]", alg); |
| 794 |
|
hlen = (r <= 0) ? 0 : strlen(hash); |
| 795 |
|
|
| 796 |
/* output upper border */ |
/* output upper border */ |
| 797 |
for (i = p - retval - 1; i < FLDSIZE_X; i++) |
p = retval; |
| 798 |
|
*p++ = '+'; |
| 799 |
|
for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) |
| 800 |
|
*p++ = '-'; |
| 801 |
|
memcpy(p, title, tlen); |
| 802 |
|
p += tlen; |
| 803 |
|
for (i += tlen; i < FLDSIZE_X; i++) |
| 804 |
*p++ = '-'; |
*p++ = '-'; |
| 805 |
*p++ = '+'; |
*p++ = '+'; |
| 806 |
*p++ = '\r'; |
*p++ = '\r'; |
| 818 |
|
|
| 819 |
/* output lower border */ |
/* output lower border */ |
| 820 |
*p++ = '+'; |
*p++ = '+'; |
| 821 |
for (i = 0; i < FLDSIZE_X; i++) |
for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) |
| 822 |
|
*p++ = '-'; |
| 823 |
|
memcpy(p, hash, hlen); |
| 824 |
|
p += hlen; |
| 825 |
|
for (i += hlen; i < FLDSIZE_X; i++) |
| 826 |
*p++ = '-'; |
*p++ = '-'; |
| 827 |
*p++ = '+'; |
*p++ = '+'; |
| 828 |
|
|
| 835 |
// |
// |
| 836 |
// fingerprint(指紋:ホスト公開鍵のハッシュ)を生成する |
// fingerprint(指紋:ホスト公開鍵のハッシュ)を生成する |
| 837 |
// |
// |
| 838 |
char *key_fingerprint(Key *key, enum fp_rep dgst_rep, enum fp_type dgst_type) |
char *key_fingerprint(Key *key, enum fp_rep dgst_rep, enum digest_algorithm dgst_alg) |
| 839 |
{ |
{ |
| 840 |
char *retval = NULL; |
char *retval = NULL, *alg; |
| 841 |
unsigned char *dgst_raw; |
unsigned char *dgst_raw; |
| 842 |
int dgst_raw_len; |
int dgst_raw_len; |
| 843 |
|
|
| 844 |
// fingerprintのハッシュ値(バイナリ)を求める |
// fingerprintのハッシュ値(バイナリ)を求める |
| 845 |
dgst_raw = key_fingerprint_raw(key, dgst_type, &dgst_raw_len); |
dgst_raw = key_fingerprint_raw(key, dgst_alg, &dgst_raw_len); |
| 846 |
if (dgst_raw == NULL) |
if (dgst_raw == NULL) |
| 847 |
return NULL; |
return NULL; |
| 848 |
|
|
| 849 |
|
alg = get_digest_algorithm_name(dgst_alg); |
| 850 |
|
|
| 851 |
switch (dgst_rep) { |
switch (dgst_rep) { |
| 852 |
case SSH_FP_HEX: |
case SSH_FP_HEX: |
| 853 |
retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); |
retval = key_fingerprint_hex(alg, dgst_raw, dgst_raw_len); |
| 854 |
break; |
break; |
| 855 |
case SSH_FP_BASE64: |
case SSH_FP_BASE64: |
| 856 |
retval = key_fingerprint_b64(dgst_raw, dgst_raw_len); |
retval = key_fingerprint_b64(alg, dgst_raw, dgst_raw_len); |
| 857 |
break; |
break; |
| 858 |
case SSH_FP_RANDOMART: |
case SSH_FP_RANDOMART: |
| 859 |
retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, key); |
retval = key_fingerprint_randomart(alg, dgst_raw, dgst_raw_len, key); |
| 860 |
break; |
break; |
| 861 |
} |
} |
| 862 |
|
|
| 2028 |
for (i = 0; i < ctx->nkeys; i++) { |
for (i = 0; i < ctx->nkeys; i++) { |
| 2029 |
if (ctx->keys_seen[i]) |
if (ctx->keys_seen[i]) |
| 2030 |
continue; |
continue; |
| 2031 |
fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX, SSH_FP_MD5); |
fp = key_fingerprint(ctx->keys[i], SSH_FP_HEX, SSH_DIGEST_MD5); |
| 2032 |
buf[0] = 0; |
buf[0] = 0; |
| 2033 |
strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->keys[i])); |
strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->keys[i])); |
| 2034 |
strcat_s(buf, sizeof(buf), " "); |
strcat_s(buf, sizeof(buf), " "); |
| 2043 |
_snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nold); |
_snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, ctx->nold); |
| 2044 |
SetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, buf); |
SetDlgItemText(dlg, IDC_REMOVEKEY_TEXT, buf); |
| 2045 |
for (i = 0; i < ctx->nold; i++) { |
for (i = 0; i < ctx->nold; i++) { |
| 2046 |
fp = key_fingerprint(ctx->old_keys[i], SSH_FP_HEX, SSH_FP_MD5); |
fp = key_fingerprint(ctx->old_keys[i], SSH_FP_HEX, SSH_DIGEST_MD5); |
| 2047 |
buf[0] = 0; |
buf[0] = 0; |
| 2048 |
strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->old_keys[i])); |
strcat_s(buf, sizeof(buf), get_sshname_from_key(ctx->old_keys[i])); |
| 2049 |
strcat_s(buf, sizeof(buf), " "); |
strcat_s(buf, sizeof(buf), " "); |
| 2301 |
free(blob); |
free(blob); |
| 2302 |
blob = NULL; |
blob = NULL; |
| 2303 |
|
|
| 2304 |
fp = key_fingerprint(key, SSH_FP_HEX, SSH_FP_MD5); |
fp = key_fingerprint(key, SSH_FP_HEX, SSH_DIGEST_MD5); |
| 2305 |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received %s host key %s", |
_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Received %s host key %s", |
| 2306 |
get_sshname_from_key(key), fp); |
get_sshname_from_key(key), fp); |
| 2307 |
notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE); |
notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE); |