diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c index fad7e0b690a38c67bedcafe6a406a161a1f81ff2..5a9dafad3cbe78a90d6a6b420b04806cd966fc1b 100644 --- a/src/syncterm/bbslist.c +++ b/src/syncterm/bbslist.c @@ -770,6 +770,20 @@ read_item(str_list_t listfile, struct bbslist *entry, char *bbsname, int id, int entry->rip = iniGetEnum(section, NULL, "RIP", rip_versions, RIP_VERSION_NONE); entry->force_lcf = iniGetBool(section, NULL, "ForceLCF", false); entry->yellow_is_yellow = iniGetBool(section, NULL, "YellowIsYellow", false); + if (iniKeyExists(section, NULL, "SSHFingerprint")) { + char fp[41]; + int i; + iniGetString(section, NULL, "SSHFingerprint", "", fp); + for (i = 0; i < 20; i++) { + if (sscanf(&fp[i * 2], "%2" SCNx8, &entry->ssh_fingerprint[i]) != 1) + break; + } + if (i == 20) + entry->has_fingerprint = true; + } + else { + entry->has_fingerprint = false; + } iniGetString(section, NULL, "DownloadPath", home, entry->dldir); iniGetString(section, NULL, "UploadPath", home, entry->uldir); @@ -1711,6 +1725,14 @@ add_bbs(char *listpath, struct bbslist *bbs) iniSetString(&inifile, bbs->name, "Comment", bbs->comment, &ini_style); iniSetBool(&inifile, bbs->name, "ForceLCF", bbs->force_lcf, &ini_style); iniSetBool(&inifile, bbs->name, "YellowIsYellow", bbs->yellow_is_yellow, &ini_style); + if (bbs->has_fingerprint) { + char fp[41]; + fp[0] = 0; + for (int i = 0; i < 20; i++) { + sprintf(&fp[i * 2], "%02x", bbs->ssh_fingerprint[i]); + } + iniSetString(&inifile, bbs->name, "SSHFingerprint", fp, &ini_style); + } if ((listfile = fopen(listpath, "w")) != NULL) { iniWriteFile(listfile, inifile); fclose(listfile); diff --git a/src/syncterm/bbslist.h b/src/syncterm/bbslist.h index d0f7247f23bc0ed3a75670ff673d4c915d582f3b..02a7e84b143d01d02aa962a3e051cc09d5c1e7b8 100644 --- a/src/syncterm/bbslist.h +++ b/src/syncterm/bbslist.h @@ -140,6 +140,8 @@ struct bbslist { char comment[1024]; bool force_lcf; bool yellow_is_yellow; + bool has_fingerprint; + uint8_t ssh_fingerprint[20]; }; extern char *music_names[]; diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c index 907bd2020e85f3a36038ac007707e504b9c11f8d..437641850ad87532aea71322996e47d47434f6a7 100644 --- a/src/syncterm/ssh.c +++ b/src/syncterm/ssh.c @@ -253,6 +253,8 @@ ssh_connect(struct bbslist *bbs) char username[MAX_USER_LEN + 1]; int rows, cols; const char *term; + int slen; + uint8_t server_fp[sizeof(bbs->ssh_fingerprint)]; ssh_channel = -1; sftp_channel = -1; @@ -456,6 +458,64 @@ ssh_connect(struct bbslist *bbs) return -1; } + memset(server_fp, 0, sizeof(server_fp)); + status = cl.GetAttributeString(ssh_session, CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1, server_fp, &slen); + if (cryptStatusOK(status)) { + if (memcmp(bbs->ssh_fingerprint, server_fp, sizeof(server_fp))) { + static const char * const opts[4] = {"Disconnect", "Update", "Ignore", ""}; + FILE *listfile; + str_list_t inifile; + char fpstr[41]; + int i; + + slen = 0; + if (bbs->has_fingerprint) { + char ofpstr[41]; + + for (i = 0; i < sizeof(server_fp); i++) { + sprintf(&fpstr[i * 2], "%02x", server_fp[i]); + } + for (i = 0; i < sizeof(server_fp); i++) { + sprintf(&ofpstr[i * 2], "%02x", bbs->ssh_fingerprint[i]); + } + asprintf(&uifc.helpbuf, "`Fingerprint Changed`\n\n" + "The server fingerprint has changed from the last known good connection.\n" + "This may indicate someone is evesdropping on your connection.\n" + "It is also possible that a host key has just been changed.\n" + "\n" + "Last known fingerprint: %s\n" + "Fingerprint sent now: %s\n", ofpstr, fpstr); + i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &slen, NULL, "Fingerprint Changed", (char **)opts); + free(uifc.helpbuf); + } + else + i = 1; + switch(i) { + case 1: + if ((listfile = fopen(settings.list_path, "r")) != NULL) { + inifile = iniReadFile(listfile); + fclose(listfile); + iniSetString(&inifile, bbs->name, "SSHFingerprint", fpstr, &ini_style); + if ((listfile = fopen(settings.list_path, "w")) != NULL) { + iniWriteFile(listfile, inifile); + fclose(listfile); + } + strListFree(&inifile); + } + break; + case 2: + break; + default: + if (!bbs->hidepopups) + uifc.pop(NULL); + return -1; + } + } + bbs->has_fingerprint = true; + } else { + fprintf(stderr, "Failed to get fingerprint. :(\n"); + } + if (!bbs->hidepopups) uifc.pop(NULL);