mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Refactor confirm_weak to use SeatDialogText.
This centralises the messages for weak crypto algorithms (general, and host keys in particular, the latter including a list of all the other available host key types) into ssh/common.c, in much the same way as we previously did for ordinary host key warnings. The reason is the same too: I'm about to want to vary the text in one of those dialog boxes, so it's convenient to start by putting it somewhere that I can modify just once.
This commit is contained in:
parent
f2e7086902
commit
9fcbb86f71
14
console.c
14
console.c
@ -9,18 +9,6 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
const char weakcrypto_msg_common_fmt[] =
|
|
||||||
"The first %s supported by the server is\n"
|
|
||||||
"%s, which is below the configured warning threshold.\n";
|
|
||||||
|
|
||||||
const char weakhk_msg_common_fmt[] =
|
|
||||||
"The first host key type we have stored for this server\n"
|
|
||||||
"is %s, which is below the configured warning threshold.\n"
|
|
||||||
"The server also provides the following types of host key\n"
|
|
||||||
"above the threshold, which we do not have stored:\n"
|
|
||||||
"%s\n";
|
|
||||||
|
|
||||||
const char console_continue_prompt[] = "Continue with connection? (y/n) ";
|
|
||||||
const char console_abandoned_msg[] = "Connection abandoned.\n";
|
const char console_abandoned_msg[] = "Connection abandoned.\n";
|
||||||
|
|
||||||
const SeatDialogPromptDescriptions *console_prompt_descriptions(Seat *seat)
|
const SeatDialogPromptDescriptions *console_prompt_descriptions(Seat *seat)
|
||||||
@ -30,6 +18,8 @@ const SeatDialogPromptDescriptions *console_prompt_descriptions(Seat *seat)
|
|||||||
.hk_connect_once_action = "enter \"n\"",
|
.hk_connect_once_action = "enter \"n\"",
|
||||||
.hk_cancel_action = "press Return",
|
.hk_cancel_action = "press Return",
|
||||||
.hk_cancel_action_Participle = "Pressing Return",
|
.hk_cancel_action_Participle = "Pressing Return",
|
||||||
|
.weak_accept_action = "enter \"y\"",
|
||||||
|
.weak_cancel_action = "enter \"n\"",
|
||||||
};
|
};
|
||||||
return &descs;
|
return &descs;
|
||||||
}
|
}
|
||||||
|
@ -430,8 +430,32 @@ static SeatPromptResult sshproxy_confirm_ssh_host_key(
|
|||||||
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm host key");
|
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm host key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sshproxy_format_seatdialogtext(strbuf *sb, SeatDialogText *text)
|
||||||
|
{
|
||||||
|
for (SeatDialogTextItem *item = text->items,
|
||||||
|
*end = item+text->nitems; item < end; item++) {
|
||||||
|
switch (item->type) {
|
||||||
|
case SDT_SCARY_HEADING:
|
||||||
|
case SDT_PARA:
|
||||||
|
case SDT_DISPLAY:
|
||||||
|
put_stringz(sb, item->text);
|
||||||
|
put_byte(sb, '\n');
|
||||||
|
break;
|
||||||
|
case SDT_BATCH_ABORT:
|
||||||
|
put_stringz(sb, item->text);
|
||||||
|
put_byte(sb, '\n');
|
||||||
|
goto endloop;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endloop:
|
||||||
|
while (strbuf_chomp(sb, '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
static SeatPromptResult sshproxy_confirm_weak_crypto_primitive(
|
static SeatPromptResult sshproxy_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
SshProxy *sp = container_of(seat, SshProxy, seat);
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
||||||
@ -442,22 +466,24 @@ static SeatPromptResult sshproxy_confirm_weak_crypto_primitive(
|
|||||||
* request on to it.
|
* request on to it.
|
||||||
*/
|
*/
|
||||||
return seat_confirm_weak_crypto_primitive(
|
return seat_confirm_weak_crypto_primitive(
|
||||||
wrap(sp->clientseat), algtype, algname, callback, ctx);
|
wrap(sp->clientseat), text, callback, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, behave as if we're in batch mode: take the safest
|
* Otherwise, behave as if we're in batch mode: take the safest
|
||||||
* option.
|
* option.
|
||||||
*/
|
*/
|
||||||
sshproxy_error(sp, "First %s supported by server is %s, below warning "
|
strbuf *sb = strbuf_new();
|
||||||
"threshold. Abandoning proxy SSH connection.",
|
sshproxy_format_seatdialogtext(sb, text);
|
||||||
algtype, algname);
|
sshproxy_error(sp, sb->s);
|
||||||
|
strbuf_free(sb);
|
||||||
|
|
||||||
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm "
|
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm "
|
||||||
"weak crypto primitive");
|
"weak crypto primitive");
|
||||||
}
|
}
|
||||||
|
|
||||||
static SeatPromptResult sshproxy_confirm_weak_cached_hostkey(
|
static SeatPromptResult sshproxy_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
SshProxy *sp = container_of(seat, SshProxy, seat);
|
SshProxy *sp = container_of(seat, SshProxy, seat);
|
||||||
@ -468,16 +494,18 @@ static SeatPromptResult sshproxy_confirm_weak_cached_hostkey(
|
|||||||
* request on to it.
|
* request on to it.
|
||||||
*/
|
*/
|
||||||
return seat_confirm_weak_cached_hostkey(
|
return seat_confirm_weak_cached_hostkey(
|
||||||
wrap(sp->clientseat), algname, betteralgs, callback, ctx);
|
wrap(sp->clientseat), text, callback, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, behave as if we're in batch mode: take the safest
|
* Otherwise, behave as if we're in batch mode: take the safest
|
||||||
* option.
|
* option.
|
||||||
*/
|
*/
|
||||||
sshproxy_error(sp, "First host key type stored for server is %s, below "
|
strbuf *sb = strbuf_new();
|
||||||
"warning threshold. Abandoning proxy SSH connection.",
|
sshproxy_format_seatdialogtext(sb, text);
|
||||||
algname);
|
sshproxy_error(sp, sb->s);
|
||||||
|
strbuf_free(sb);
|
||||||
|
|
||||||
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm "
|
return SPR_SW_ABORT("Noninteractive SSH proxy cannot confirm "
|
||||||
"weak cached host key");
|
"weak cached host key");
|
||||||
}
|
}
|
||||||
|
24
putty.h
24
putty.h
@ -1293,7 +1293,7 @@ struct SeatVtable {
|
|||||||
* confirm_ssh_host_key above.
|
* confirm_ssh_host_key above.
|
||||||
*/
|
*/
|
||||||
SeatPromptResult (*confirm_weak_crypto_primitive)(
|
SeatPromptResult (*confirm_weak_crypto_primitive)(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1304,11 +1304,10 @@ struct SeatVtable {
|
|||||||
* This form is used in the case where we're using a host key
|
* This form is used in the case where we're using a host key
|
||||||
* below the warning threshold because that's the best one we have
|
* below the warning threshold because that's the best one we have
|
||||||
* cached, but at least one host key algorithm *above* the
|
* cached, but at least one host key algorithm *above* the
|
||||||
* threshold is available that we don't have cached. 'betteralgs'
|
* threshold is available that we don't have cached.
|
||||||
* lists the better algorithm(s).
|
|
||||||
*/
|
*/
|
||||||
SeatPromptResult (*confirm_weak_cached_hostkey)(
|
SeatPromptResult (*confirm_weak_cached_hostkey)(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1444,15 +1443,15 @@ static inline SeatPromptResult seat_confirm_ssh_host_key(
|
|||||||
{ return iseat.seat->vt->confirm_ssh_host_key(
|
{ return iseat.seat->vt->confirm_ssh_host_key(
|
||||||
iseat.seat, h, p, ktyp, kstr, text, helpctx, cb, ctx); }
|
iseat.seat, h, p, ktyp, kstr, text, helpctx, cb, ctx); }
|
||||||
static inline SeatPromptResult seat_confirm_weak_crypto_primitive(
|
static inline SeatPromptResult seat_confirm_weak_crypto_primitive(
|
||||||
InteractionReadySeat iseat, const char *atyp, const char *aname,
|
InteractionReadySeat iseat, SeatDialogText *text,
|
||||||
void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return iseat.seat->vt->confirm_weak_crypto_primitive(
|
{ return iseat.seat->vt->confirm_weak_crypto_primitive(
|
||||||
iseat.seat, atyp, aname, cb, ctx); }
|
iseat.seat, text, cb, ctx); }
|
||||||
static inline SeatPromptResult seat_confirm_weak_cached_hostkey(
|
static inline SeatPromptResult seat_confirm_weak_cached_hostkey(
|
||||||
InteractionReadySeat iseat, const char *aname, const char *better,
|
InteractionReadySeat iseat, SeatDialogText *text,
|
||||||
void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return iseat.seat->vt->confirm_weak_cached_hostkey(
|
{ return iseat.seat->vt->confirm_weak_cached_hostkey(
|
||||||
iseat.seat, aname, better, cb, ctx); }
|
iseat.seat, text, cb, ctx); }
|
||||||
static inline const SeatDialogPromptDescriptions *seat_prompt_descriptions(
|
static inline const SeatDialogPromptDescriptions *seat_prompt_descriptions(
|
||||||
Seat *seat)
|
Seat *seat)
|
||||||
{ return seat->vt->prompt_descriptions(seat); }
|
{ return seat->vt->prompt_descriptions(seat); }
|
||||||
@ -1505,6 +1504,7 @@ struct SeatDialogPromptDescriptions {
|
|||||||
const char *hk_accept_action;
|
const char *hk_accept_action;
|
||||||
const char *hk_connect_once_action;
|
const char *hk_connect_once_action;
|
||||||
const char *hk_cancel_action, *hk_cancel_action_Participle;
|
const char *hk_cancel_action, *hk_cancel_action_Participle;
|
||||||
|
const char *weak_accept_action, *weak_cancel_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* In the utils subdir: print a message to the Seat which can't be
|
/* In the utils subdir: print a message to the Seat which can't be
|
||||||
@ -1537,10 +1537,10 @@ SeatPromptResult nullseat_confirm_ssh_host_key(
|
|||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult nullseat_confirm_weak_crypto_primitive(
|
SeatPromptResult nullseat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult nullseat_confirm_weak_cached_hostkey(
|
SeatPromptResult nullseat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat);
|
const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat);
|
||||||
bool nullseat_is_never_utf8(Seat *seat);
|
bool nullseat_is_never_utf8(Seat *seat);
|
||||||
@ -1573,10 +1573,10 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult console_confirm_weak_crypto_primitive(
|
SeatPromptResult console_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult console_confirm_weak_cached_hostkey(
|
SeatPromptResult console_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
StripCtrlChars *console_stripctrl_new(
|
StripCtrlChars *console_stripctrl_new(
|
||||||
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
|
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
|
||||||
|
6
ssh.h
6
ssh.h
@ -1908,6 +1908,12 @@ SeatPromptResult verify_ssh_host_key(
|
|||||||
ssh_key *key, const char *keytype, char *keystr, const char *keydisp,
|
ssh_key *key, const char *keytype, char *keystr, const char *keydisp,
|
||||||
char **fingerprints, int ca_count,
|
char **fingerprints, int ca_count,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
|
SeatPromptResult confirm_weak_crypto_primitive(
|
||||||
|
InteractionReadySeat iseat, const char *algtype, const char *algname,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
|
SeatPromptResult confirm_weak_cached_hostkey(
|
||||||
|
InteractionReadySeat iseat, const char *algname, const char **betteralgs,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
|
|
||||||
typedef struct ssh_transient_hostkey_cache ssh_transient_hostkey_cache;
|
typedef struct ssh_transient_hostkey_cache ssh_transient_hostkey_cache;
|
||||||
ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void);
|
ssh_transient_hostkey_cache *ssh_transient_hostkey_cache_new(void);
|
||||||
|
73
ssh/common.c
73
ssh/common.c
@ -1085,6 +1085,79 @@ SeatPromptResult verify_ssh_host_key(
|
|||||||
return toret;
|
return toret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SeatPromptResult confirm_weak_crypto_primitive(
|
||||||
|
InteractionReadySeat iseat, const char *algtype, const char *algname,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
|
{
|
||||||
|
SeatDialogText *text = seat_dialog_text_new();
|
||||||
|
const SeatDialogPromptDescriptions *pds =
|
||||||
|
seat_prompt_descriptions(iseat.seat);
|
||||||
|
|
||||||
|
seat_dialog_text_append(text, SDT_TITLE, "%s Security Alert", appname);
|
||||||
|
|
||||||
|
seat_dialog_text_append(
|
||||||
|
text, SDT_PARA,
|
||||||
|
"The first %s supported by the server is %s, "
|
||||||
|
"which is below the configured warning threshold.",
|
||||||
|
algtype, algname);
|
||||||
|
|
||||||
|
/* In batch mode, we print the above information and then this
|
||||||
|
* abort message, and stop. */
|
||||||
|
seat_dialog_text_append(text, SDT_BATCH_ABORT, "Connection abandoned.");
|
||||||
|
|
||||||
|
seat_dialog_text_append(
|
||||||
|
text, SDT_PARA, "To accept the risk and continue, %s. "
|
||||||
|
"To abandon the connection, %s.",
|
||||||
|
pds->weak_accept_action, pds->weak_cancel_action);
|
||||||
|
|
||||||
|
seat_dialog_text_append(text, SDT_PROMPT, "Continue with connection?");
|
||||||
|
|
||||||
|
SeatPromptResult toret = seat_confirm_weak_crypto_primitive(
|
||||||
|
iseat, text, callback, ctx);
|
||||||
|
seat_dialog_text_free(text);
|
||||||
|
return toret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SeatPromptResult confirm_weak_cached_hostkey(
|
||||||
|
InteractionReadySeat iseat, const char *algname, const char **betteralgs,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
|
{
|
||||||
|
SeatDialogText *text = seat_dialog_text_new();
|
||||||
|
const SeatDialogPromptDescriptions *pds =
|
||||||
|
seat_prompt_descriptions(iseat.seat);
|
||||||
|
|
||||||
|
seat_dialog_text_append(text, SDT_TITLE, "%s Security Alert", appname);
|
||||||
|
|
||||||
|
seat_dialog_text_append(
|
||||||
|
text, SDT_PARA,
|
||||||
|
"The first host key type we have stored for this server "
|
||||||
|
"is %s, which is below the configured warning threshold.", algname);
|
||||||
|
|
||||||
|
seat_dialog_text_append(
|
||||||
|
text, SDT_PARA,
|
||||||
|
"The server also provides the following types of host key "
|
||||||
|
"above the threshold, which we do not have stored:");
|
||||||
|
|
||||||
|
for (const char **p = betteralgs; *p; p++)
|
||||||
|
seat_dialog_text_append(text, SDT_DISPLAY, "%s", *p);
|
||||||
|
|
||||||
|
/* In batch mode, we print the above information and then this
|
||||||
|
* abort message, and stop. */
|
||||||
|
seat_dialog_text_append(text, SDT_BATCH_ABORT, "Connection abandoned.");
|
||||||
|
|
||||||
|
seat_dialog_text_append(
|
||||||
|
text, SDT_PARA, "To accept the risk and continue, %s. "
|
||||||
|
"To abandon the connection, %s.",
|
||||||
|
pds->weak_accept_action, pds->weak_cancel_action);
|
||||||
|
|
||||||
|
seat_dialog_text_append(text, SDT_PROMPT, "Continue with connection?");
|
||||||
|
|
||||||
|
SeatPromptResult toret = seat_confirm_weak_cached_hostkey(
|
||||||
|
iseat, text, callback, ctx);
|
||||||
|
seat_dialog_text_free(text);
|
||||||
|
return toret;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* Common functions shared between SSH-1 layers.
|
* Common functions shared between SSH-1 layers.
|
||||||
*/
|
*/
|
||||||
|
@ -323,7 +323,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||||||
|
|
||||||
/* Warn about chosen cipher if necessary. */
|
/* Warn about chosen cipher if necessary. */
|
||||||
if (warn) {
|
if (warn) {
|
||||||
s->spr = seat_confirm_weak_crypto_primitive(
|
s->spr = confirm_weak_crypto_primitive(
|
||||||
ppl_get_iseat(&s->ppl), "cipher", cipher_string,
|
ppl_get_iseat(&s->ppl), "cipher", cipher_string,
|
||||||
ssh1_login_dialog_callback, s);
|
ssh1_login_dialog_callback, s);
|
||||||
crMaybeWaitUntilV(s->spr.kind != SPRK_INCOMPLETE);
|
crMaybeWaitUntilV(s->spr.kind != SPRK_INCOMPLETE);
|
||||||
|
@ -98,11 +98,11 @@ void mainchan_terminal_size(mainchan *mc, int width, int height) {}
|
|||||||
/* Seat functions to ensure we don't get choosy about crypto - as the
|
/* Seat functions to ensure we don't get choosy about crypto - as the
|
||||||
* server, it's not up to us to give user warnings */
|
* server, it's not up to us to give user warnings */
|
||||||
static SeatPromptResult server_confirm_weak_crypto_primitive(
|
static SeatPromptResult server_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return SPR_OK; }
|
{ return SPR_OK; }
|
||||||
static SeatPromptResult server_confirm_weak_cached_hostkey(
|
static SeatPromptResult server_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return SPR_OK; }
|
{ return SPR_OK; }
|
||||||
|
|
||||||
|
@ -1514,7 +1514,8 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
|||||||
|
|
||||||
if (s->warn_hk) {
|
if (s->warn_hk) {
|
||||||
int j, k;
|
int j, k;
|
||||||
char *betteralgs;
|
const char **betteralgs = NULL;
|
||||||
|
size_t nbetter = 0, bettersize = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change warning box wording depending on why we chose a
|
* Change warning box wording depending on why we chose a
|
||||||
@ -1523,7 +1524,6 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
|||||||
* could usefully cross-certify. Otherwise, use the same
|
* could usefully cross-certify. Otherwise, use the same
|
||||||
* standard wording as any other weak crypto primitive.
|
* standard wording as any other weak crypto primitive.
|
||||||
*/
|
*/
|
||||||
betteralgs = NULL;
|
|
||||||
for (j = 0; j < s->n_uncert_hostkeys; j++) {
|
for (j = 0; j < s->n_uncert_hostkeys; j++) {
|
||||||
const struct ssh_signkey_with_user_pref_id *hktype =
|
const struct ssh_signkey_with_user_pref_id *hktype =
|
||||||
&ssh2_hostkey_algs[s->uncert_hostkeys[j]];
|
&ssh2_hostkey_algs[s->uncert_hostkeys[j]];
|
||||||
@ -1538,19 +1538,16 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (better) {
|
if (better) {
|
||||||
if (betteralgs) {
|
sgrowarray(betteralgs, bettersize, nbetter);
|
||||||
char *old_ba = betteralgs;
|
betteralgs[nbetter++] = hktype->alg->ssh_id;
|
||||||
betteralgs = dupcat(betteralgs, ",", hktype->alg->ssh_id);
|
|
||||||
sfree(old_ba);
|
|
||||||
} else {
|
|
||||||
betteralgs = dupstr(hktype->alg->ssh_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (betteralgs) {
|
if (betteralgs) {
|
||||||
/* Use the special warning prompt that lets us provide
|
/* Use the special warning prompt that lets us provide
|
||||||
* a list of better algorithms */
|
* a list of better algorithms */
|
||||||
s->spr = seat_confirm_weak_cached_hostkey(
|
sgrowarray(betteralgs, bettersize, nbetter);
|
||||||
|
betteralgs[nbetter] = NULL;
|
||||||
|
s->spr = confirm_weak_cached_hostkey(
|
||||||
ppl_get_iseat(&s->ppl), s->hostkey_alg->ssh_id, betteralgs,
|
ppl_get_iseat(&s->ppl), s->hostkey_alg->ssh_id, betteralgs,
|
||||||
ssh2_transport_dialog_callback, s);
|
ssh2_transport_dialog_callback, s);
|
||||||
sfree(betteralgs);
|
sfree(betteralgs);
|
||||||
@ -2389,7 +2386,7 @@ static int ca_blob_compare(void *av, void *bv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper on seat_confirm_weak_crypto_primitive(), which uses the
|
* Wrapper on confirm_weak_crypto_primitive(), which uses the
|
||||||
* tree234 s->weak_algorithms_consented_to to ensure we ask at most
|
* tree234 s->weak_algorithms_consented_to to ensure we ask at most
|
||||||
* once about any given crypto primitive.
|
* once about any given crypto primitive.
|
||||||
*/
|
*/
|
||||||
@ -2401,7 +2398,7 @@ static SeatPromptResult ssh2_transport_confirm_weak_crypto_primitive(
|
|||||||
return SPR_OK;
|
return SPR_OK;
|
||||||
add234(s->weak_algorithms_consented_to, (void *)alg);
|
add234(s->weak_algorithms_consented_to, (void *)alg);
|
||||||
|
|
||||||
return seat_confirm_weak_crypto_primitive(
|
return confirm_weak_crypto_primitive(
|
||||||
ppl_get_iseat(&s->ppl), type, name, ssh2_transport_dialog_callback, s);
|
ppl_get_iseat(&s->ppl), type, name, ssh2_transport_dialog_callback, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,11 +26,11 @@ SeatPromptResult nullseat_confirm_ssh_host_key(
|
|||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
||||||
SeatPromptResult nullseat_confirm_weak_crypto_primitive(
|
SeatPromptResult nullseat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
||||||
SeatPromptResult nullseat_confirm_weak_cached_hostkey(
|
SeatPromptResult nullseat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
{ return SPR_SW_ABORT("this seat can't handle interactive prompts"); }
|
||||||
bool nullseat_is_never_utf8(Seat *seat) { return false; }
|
bool nullseat_is_never_utf8(Seat *seat) { return false; }
|
||||||
@ -60,6 +60,8 @@ const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat)
|
|||||||
.hk_connect_once_action = "",
|
.hk_connect_once_action = "",
|
||||||
.hk_cancel_action = "",
|
.hk_cancel_action = "",
|
||||||
.hk_cancel_action_Participle = "",
|
.hk_cancel_action_Participle = "",
|
||||||
|
.weak_accept_action = "",
|
||||||
|
.weak_cancel_action = "",
|
||||||
};
|
};
|
||||||
return &descs;
|
return &descs;
|
||||||
}
|
}
|
||||||
|
@ -102,20 +102,18 @@ static int block_and_read(int fd, void *buf, size_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_ssh_host_key(
|
/*
|
||||||
Seat *seat, const char *host, int port, const char *keytype,
|
* Helper function to print the message from a SeatDialogText. Returns
|
||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
* the final prompt to print on the input line, or NULL if a
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
* batch-mode abort is needed. In the latter case it will have printed
|
||||||
|
* the abort text already.
|
||||||
|
*/
|
||||||
|
static const char *console_print_seatdialogtext(SeatDialogText *text)
|
||||||
{
|
{
|
||||||
char line[32];
|
|
||||||
struct termios cf;
|
|
||||||
const char *prompt = NULL;
|
const char *prompt = NULL;
|
||||||
|
|
||||||
stdio_sink errsink[1];
|
stdio_sink errsink[1];
|
||||||
stdio_sink_init(errsink, stderr);
|
stdio_sink_init(errsink, stderr);
|
||||||
|
|
||||||
premsg(&cf);
|
|
||||||
|
|
||||||
for (SeatDialogTextItem *item = text->items,
|
for (SeatDialogTextItem *item = text->items,
|
||||||
*end = item+text->nitems; item < end; item++) {
|
*end = item+text->nitems; item < end; item++) {
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
@ -135,8 +133,7 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
if (console_batch_mode) {
|
if (console_batch_mode) {
|
||||||
fprintf(stderr, "%s\n", item->text);
|
fprintf(stderr, "%s\n", item->text);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
postmsg(&cf);
|
return NULL;
|
||||||
return SPR_SW_ABORT("Cannot confirm a host key in batch mode");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDT_PROMPT:
|
case SDT_PROMPT:
|
||||||
@ -146,7 +143,26 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(prompt); /* something in the SeatDialogText should have set this */
|
assert(prompt); /* something in the SeatDialogText should have set this */
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
SeatPromptResult console_confirm_ssh_host_key(
|
||||||
|
Seat *seat, const char *host, int port, const char *keytype,
|
||||||
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
|
{
|
||||||
|
char line[32];
|
||||||
|
struct termios cf;
|
||||||
|
|
||||||
|
premsg(&cf);
|
||||||
|
|
||||||
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
|
if (!prompt) {
|
||||||
|
postmsg(&cf);
|
||||||
|
return SPR_SW_ABORT("Cannot confirm a host key in batch mode");
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -202,23 +218,22 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_weak_crypto_primitive(
|
SeatPromptResult console_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
char line[32];
|
char line[32];
|
||||||
struct termios cf;
|
struct termios cf;
|
||||||
|
|
||||||
premsg(&cf);
|
premsg(&cf);
|
||||||
fprintf(stderr, weakcrypto_msg_common_fmt, algtype, algname);
|
|
||||||
|
|
||||||
if (console_batch_mode) {
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
fputs(console_abandoned_msg, stderr);
|
if (!prompt) {
|
||||||
postmsg(&cf);
|
postmsg(&cf);
|
||||||
return SPR_SW_ABORT("Cannot confirm a weak crypto primitive "
|
return SPR_SW_ABORT("Cannot confirm a weak crypto primitive "
|
||||||
"in batch mode");
|
"in batch mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(console_continue_prompt, stderr);
|
fprintf(stderr, "%s (y/n) ", prompt);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -244,23 +259,22 @@ SeatPromptResult console_confirm_weak_crypto_primitive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_weak_cached_hostkey(
|
SeatPromptResult console_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
char line[32];
|
char line[32];
|
||||||
struct termios cf;
|
struct termios cf;
|
||||||
|
|
||||||
premsg(&cf);
|
premsg(&cf);
|
||||||
fprintf(stderr, weakhk_msg_common_fmt, algname, betteralgs);
|
|
||||||
|
|
||||||
if (console_batch_mode) {
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
fputs(console_abandoned_msg, stderr);
|
if (!prompt) {
|
||||||
postmsg(&cf);
|
postmsg(&cf);
|
||||||
return SPR_SW_ABORT("Cannot confirm a weak cached host key "
|
return SPR_SW_ABORT("Cannot confirm a weak cached host key "
|
||||||
"in batch mode");
|
"in batch mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(console_continue_prompt, stderr);
|
fprintf(stderr, "%s (y/n) ", prompt);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
118
unix/dialog.c
118
unix/dialog.c
@ -3609,10 +3609,54 @@ const SeatDialogPromptDescriptions *gtk_seat_prompt_descriptions(Seat *seat)
|
|||||||
.hk_connect_once_action = "press \"Connect Once\"",
|
.hk_connect_once_action = "press \"Connect Once\"",
|
||||||
.hk_cancel_action = "press \"Cancel\"",
|
.hk_cancel_action = "press \"Cancel\"",
|
||||||
.hk_cancel_action_Participle = "Pressing \"Cancel\"",
|
.hk_cancel_action_Participle = "Pressing \"Cancel\"",
|
||||||
|
.weak_accept_action = "press \"Yes\"",
|
||||||
|
.weak_cancel_action = "press \"No\"",
|
||||||
};
|
};
|
||||||
return &descs;
|
return &descs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a SeatDialogText into a strbuf, also adjusting the box width
|
||||||
|
* to cope with displayed text. Returns the dialog box title.
|
||||||
|
*/
|
||||||
|
static const char *gtk_format_seatdialogtext(
|
||||||
|
SeatDialogText *text, strbuf *dlg_text, int *width)
|
||||||
|
{
|
||||||
|
const char *dlg_title = NULL;
|
||||||
|
|
||||||
|
for (SeatDialogTextItem *item = text->items,
|
||||||
|
*end = item + text->nitems; item < end; item++) {
|
||||||
|
switch (item->type) {
|
||||||
|
case SDT_PARA:
|
||||||
|
put_fmt(dlg_text, "%s\n\n", item->text);
|
||||||
|
break;
|
||||||
|
case SDT_DISPLAY: {
|
||||||
|
put_fmt(dlg_text, "%s\n\n", item->text);
|
||||||
|
int thiswidth = string_width(item->text);
|
||||||
|
if (*width < thiswidth)
|
||||||
|
*width = thiswidth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDT_SCARY_HEADING:
|
||||||
|
/* Can't change font size or weight in this context */
|
||||||
|
put_fmt(dlg_text, "%s\n\n", item->text);
|
||||||
|
break;
|
||||||
|
case SDT_TITLE:
|
||||||
|
dlg_title = item->text;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trim trailing newlines.
|
||||||
|
*/
|
||||||
|
while (strbuf_chomp(dlg_text, '\n'));
|
||||||
|
|
||||||
|
return dlg_title;
|
||||||
|
}
|
||||||
|
|
||||||
SeatPromptResult gtk_seat_confirm_ssh_host_key(
|
SeatPromptResult gtk_seat_confirm_ssh_host_key(
|
||||||
Seat *seat, const char *host, int port, const char *keytype,
|
Seat *seat, const char *host, int port, const char *keytype,
|
||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
@ -3627,35 +3671,9 @@ SeatPromptResult gtk_seat_confirm_ssh_host_key(
|
|||||||
button_array_hostkey, lenof(button_array_hostkey),
|
button_array_hostkey, lenof(button_array_hostkey),
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *dlg_title = NULL;
|
|
||||||
strbuf *dlg_text = strbuf_new();
|
|
||||||
int width = string_width("default dialog width determination string");
|
int width = string_width("default dialog width determination string");
|
||||||
|
strbuf *dlg_text = strbuf_new();
|
||||||
for (SeatDialogTextItem *item = text->items,
|
const char *dlg_title = gtk_format_seatdialogtext(text, dlg_text, &width);
|
||||||
*end = item + text->nitems; item < end; item++) {
|
|
||||||
switch (item->type) {
|
|
||||||
case SDT_PARA:
|
|
||||||
put_fmt(dlg_text, "%s\n\n", item->text);
|
|
||||||
break;
|
|
||||||
case SDT_DISPLAY: {
|
|
||||||
put_fmt(dlg_text, "%s\n\n", item->text);
|
|
||||||
int thiswidth = string_width(item->text);
|
|
||||||
if (width < thiswidth)
|
|
||||||
width = thiswidth;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDT_SCARY_HEADING:
|
|
||||||
/* Can't change font size or weight in this context */
|
|
||||||
put_fmt(dlg_text, "%s\n\n", item->text);
|
|
||||||
break;
|
|
||||||
case SDT_TITLE:
|
|
||||||
dlg_title = item->text;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (strbuf_chomp(dlg_text, '\n'));
|
|
||||||
|
|
||||||
GtkWidget *mainwin, *msgbox;
|
GtkWidget *mainwin, *msgbox;
|
||||||
|
|
||||||
@ -3752,19 +3770,16 @@ static void simple_prompt_result_spr_callback(void *vctx, int result)
|
|||||||
* below the configured 'warn' threshold).
|
* below the configured 'warn' threshold).
|
||||||
*/
|
*/
|
||||||
SeatPromptResult gtk_seat_confirm_weak_crypto_primitive(
|
SeatPromptResult gtk_seat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
static const char msg[] =
|
|
||||||
"The first %s supported by the server is "
|
|
||||||
"%s, which is below the configured warning threshold.\n"
|
|
||||||
"Continue with connection?";
|
|
||||||
|
|
||||||
char *text;
|
|
||||||
struct simple_prompt_result_spr_ctx *result_ctx;
|
struct simple_prompt_result_spr_ctx *result_ctx;
|
||||||
GtkWidget *mainwin, *msgbox;
|
GtkWidget *mainwin, *msgbox;
|
||||||
|
|
||||||
text = dupprintf(msg, algtype, algname);
|
int width = string_width("Reasonably long line of text "
|
||||||
|
"as a width template");
|
||||||
|
strbuf *dlg_text = strbuf_new();
|
||||||
|
const char *dlg_title = gtk_format_seatdialogtext(text, dlg_text, &width);
|
||||||
|
|
||||||
result_ctx = snew(struct simple_prompt_result_spr_ctx);
|
result_ctx = snew(struct simple_prompt_result_spr_ctx);
|
||||||
result_ctx->callback = callback;
|
result_ctx->callback = callback;
|
||||||
@ -3774,33 +3789,26 @@ SeatPromptResult gtk_seat_confirm_weak_crypto_primitive(
|
|||||||
|
|
||||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||||
msgbox = create_message_box(
|
msgbox = create_message_box(
|
||||||
mainwin, "PuTTY Security Alert", text,
|
mainwin, dlg_title, dlg_text->s, width, false,
|
||||||
string_width("Reasonably long line of text as a width template"),
|
&buttons_yn, simple_prompt_result_spr_callback, result_ctx);
|
||||||
false, &buttons_yn, simple_prompt_result_spr_callback, result_ctx);
|
|
||||||
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
||||||
|
|
||||||
sfree(text);
|
strbuf_free(dlg_text);
|
||||||
|
|
||||||
return SPR_INCOMPLETE;
|
return SPR_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult gtk_seat_confirm_weak_cached_hostkey(
|
SeatPromptResult gtk_seat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
static const char msg[] =
|
|
||||||
"The first host key type we have stored for this server\n"
|
|
||||||
"is %s, which is below the configured warning threshold.\n"
|
|
||||||
"The server also provides the following types of host key\n"
|
|
||||||
"above the threshold, which we do not have stored:\n"
|
|
||||||
"%s\n"
|
|
||||||
"Continue with connection?";
|
|
||||||
|
|
||||||
char *text;
|
|
||||||
struct simple_prompt_result_spr_ctx *result_ctx;
|
struct simple_prompt_result_spr_ctx *result_ctx;
|
||||||
GtkWidget *mainwin, *msgbox;
|
GtkWidget *mainwin, *msgbox;
|
||||||
|
|
||||||
text = dupprintf(msg, algname, betteralgs);
|
int width = string_width("is ecdsa-nistp521, which is below the configured"
|
||||||
|
" warning threshold.");
|
||||||
|
strbuf *dlg_text = strbuf_new();
|
||||||
|
const char *dlg_title = gtk_format_seatdialogtext(text, dlg_text, &width);
|
||||||
|
|
||||||
result_ctx = snew(struct simple_prompt_result_spr_ctx);
|
result_ctx = snew(struct simple_prompt_result_spr_ctx);
|
||||||
result_ctx->callback = callback;
|
result_ctx->callback = callback;
|
||||||
@ -3810,13 +3818,11 @@ SeatPromptResult gtk_seat_confirm_weak_cached_hostkey(
|
|||||||
|
|
||||||
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
|
||||||
msgbox = create_message_box(
|
msgbox = create_message_box(
|
||||||
mainwin, "PuTTY Security Alert", text,
|
mainwin, dlg_title, dlg_text->s, width, false,
|
||||||
string_width("is ecdsa-nistp521, which is below the configured"
|
&buttons_yn, simple_prompt_result_spr_callback, result_ctx);
|
||||||
" warning threshold."),
|
|
||||||
false, &buttons_yn, simple_prompt_result_spr_callback, result_ctx);
|
|
||||||
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
register_dialog(seat, result_ctx->dialog_slot, msgbox);
|
||||||
|
|
||||||
sfree(text);
|
strbuf_free(dlg_text);
|
||||||
|
|
||||||
return SPR_INCOMPLETE;
|
return SPR_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
@ -225,10 +225,10 @@ SeatPromptResult gtk_seat_confirm_ssh_host_key(
|
|||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult gtk_seat_confirm_weak_crypto_primitive(
|
SeatPromptResult gtk_seat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult gtk_seat_confirm_weak_cached_hostkey(
|
SeatPromptResult gtk_seat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
const SeatDialogPromptDescriptions *gtk_seat_prompt_descriptions(Seat *seat);
|
const SeatDialogPromptDescriptions *gtk_seat_prompt_descriptions(Seat *seat);
|
||||||
#ifdef MAY_REFER_TO_GTK_IN_HEADERS
|
#ifdef MAY_REFER_TO_GTK_IN_HEADERS
|
||||||
|
@ -255,7 +255,7 @@ static SeatPromptResult tempseat_confirm_ssh_host_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SeatPromptResult tempseat_confirm_weak_crypto_primitive(
|
static SeatPromptResult tempseat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
unreachable("confirm_weak_crypto_primitive "
|
unreachable("confirm_weak_crypto_primitive "
|
||||||
@ -263,7 +263,7 @@ static SeatPromptResult tempseat_confirm_weak_crypto_primitive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SeatPromptResult tempseat_confirm_weak_cached_hostkey(
|
static SeatPromptResult tempseat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
unreachable("confirm_weak_cached_hostkey "
|
unreachable("confirm_weak_cached_hostkey "
|
||||||
|
@ -32,20 +32,18 @@ void console_print_error_msg(const char *prefix, const char *msg)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_ssh_host_key(
|
/*
|
||||||
Seat *seat, const char *host, int port, const char *keytype,
|
* Helper function to print the message from a SeatDialogText. Returns
|
||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
* the final prompt to print on the input line, or NULL if a
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
* batch-mode abort is needed. In the latter case it will have printed
|
||||||
|
* the abort text already.
|
||||||
|
*/
|
||||||
|
static const char *console_print_seatdialogtext(SeatDialogText *text)
|
||||||
{
|
{
|
||||||
HANDLE hin;
|
|
||||||
DWORD savemode, i;
|
|
||||||
const char *prompt = NULL;
|
const char *prompt = NULL;
|
||||||
|
|
||||||
stdio_sink errsink[1];
|
stdio_sink errsink[1];
|
||||||
stdio_sink_init(errsink, stderr);
|
stdio_sink_init(errsink, stderr);
|
||||||
|
|
||||||
char line[32];
|
|
||||||
|
|
||||||
for (SeatDialogTextItem *item = text->items,
|
for (SeatDialogTextItem *item = text->items,
|
||||||
*end = item+text->nitems; item < end; item++) {
|
*end = item+text->nitems; item < end; item++) {
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
@ -65,7 +63,7 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
if (console_batch_mode) {
|
if (console_batch_mode) {
|
||||||
fprintf(stderr, "%s\n", item->text);
|
fprintf(stderr, "%s\n", item->text);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
return SPR_SW_ABORT("Cannot confirm a host key in batch mode");
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDT_PROMPT:
|
case SDT_PROMPT:
|
||||||
@ -76,6 +74,22 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(prompt); /* something in the SeatDialogText should have set this */
|
assert(prompt); /* something in the SeatDialogText should have set this */
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
SeatPromptResult console_confirm_ssh_host_key(
|
||||||
|
Seat *seat, const char *host, int port, const char *keytype,
|
||||||
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
|
{
|
||||||
|
HANDLE hin;
|
||||||
|
DWORD savemode, i;
|
||||||
|
|
||||||
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
|
if (!prompt)
|
||||||
|
return SPR_SW_ABORT("Cannot confirm a host key in batch mode");
|
||||||
|
|
||||||
|
char line[32];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -128,23 +142,20 @@ SeatPromptResult console_confirm_ssh_host_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_weak_crypto_primitive(
|
SeatPromptResult console_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
HANDLE hin;
|
HANDLE hin;
|
||||||
DWORD savemode, i;
|
DWORD savemode, i;
|
||||||
|
|
||||||
char line[32];
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
|
if (!prompt)
|
||||||
fprintf(stderr, weakcrypto_msg_common_fmt, algtype, algname);
|
|
||||||
|
|
||||||
if (console_batch_mode) {
|
|
||||||
fputs(console_abandoned_msg, stderr);
|
|
||||||
return SPR_SW_ABORT("Cannot confirm a weak crypto primitive "
|
return SPR_SW_ABORT("Cannot confirm a weak crypto primitive "
|
||||||
"in batch mode");
|
"in batch mode");
|
||||||
}
|
|
||||||
|
|
||||||
fputs(console_continue_prompt, stderr);
|
char line[32];
|
||||||
|
|
||||||
|
fprintf(stderr, "%s (y/n) ", prompt);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
@ -163,23 +174,20 @@ SeatPromptResult console_confirm_weak_crypto_primitive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult console_confirm_weak_cached_hostkey(
|
SeatPromptResult console_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
HANDLE hin;
|
HANDLE hin;
|
||||||
DWORD savemode, i;
|
DWORD savemode, i;
|
||||||
|
|
||||||
char line[32];
|
const char *prompt = console_print_seatdialogtext(text);
|
||||||
|
if (!prompt)
|
||||||
fprintf(stderr, weakhk_msg_common_fmt, algname, betteralgs);
|
|
||||||
|
|
||||||
if (console_batch_mode) {
|
|
||||||
fputs(console_abandoned_msg, stderr);
|
|
||||||
return SPR_SW_ABORT("Cannot confirm a weak cached host key "
|
return SPR_SW_ABORT("Cannot confirm a weak cached host key "
|
||||||
"in batch mode");
|
"in batch mode");
|
||||||
}
|
|
||||||
|
|
||||||
fputs(console_continue_prompt, stderr);
|
char line[32];
|
||||||
|
|
||||||
|
fprintf(stderr, "%s (y/n) ", prompt);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
112
windows/dialog.c
112
windows/dialog.c
@ -963,6 +963,39 @@ static INT_PTR HostKeyMoreInfoProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *process_seatdialogtext(
|
||||||
|
strbuf *dlg_text, const char **scary_heading, SeatDialogText *text)
|
||||||
|
{
|
||||||
|
const char *dlg_title = "";
|
||||||
|
|
||||||
|
for (SeatDialogTextItem *item = text->items,
|
||||||
|
*end = item + text->nitems; item < end; item++) {
|
||||||
|
switch (item->type) {
|
||||||
|
case SDT_PARA:
|
||||||
|
put_fmt(dlg_text, "%s\r\n\r\n", item->text);
|
||||||
|
break;
|
||||||
|
case SDT_DISPLAY:
|
||||||
|
put_fmt(dlg_text, "%s\r\n\r\n", item->text);
|
||||||
|
break;
|
||||||
|
case SDT_SCARY_HEADING:
|
||||||
|
assert(scary_heading != NULL && "only expect a scary heading if "
|
||||||
|
"the dialog has somewhere to put it");
|
||||||
|
*scary_heading = item->text;
|
||||||
|
break;
|
||||||
|
case SDT_TITLE:
|
||||||
|
dlg_title = item->text;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trim any trailing newlines */
|
||||||
|
while (strbuf_chomp(dlg_text, '\r') || strbuf_chomp(dlg_text, '\n'));
|
||||||
|
|
||||||
|
return dlg_title;
|
||||||
|
}
|
||||||
|
|
||||||
static INT_PTR HostKeyDialogProc(HWND hwnd, UINT msg,
|
static INT_PTR HostKeyDialogProc(HWND hwnd, UINT msg,
|
||||||
WPARAM wParam, LPARAM lParam, void *vctx)
|
WPARAM wParam, LPARAM lParam, void *vctx)
|
||||||
{
|
{
|
||||||
@ -971,32 +1004,15 @@ static INT_PTR HostKeyDialogProc(HWND hwnd, UINT msg,
|
|||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_INITDIALOG: {
|
case WM_INITDIALOG: {
|
||||||
strbuf *dlg_text = strbuf_new();
|
strbuf *dlg_text = strbuf_new();
|
||||||
const char *dlg_title = "";
|
const char *scary_heading = NULL;
|
||||||
ctx->has_title = false;
|
const char *dlg_title = process_seatdialogtext(
|
||||||
LPCTSTR iconid = IDI_QUESTION;
|
dlg_text, &scary_heading, ctx->text);
|
||||||
|
|
||||||
for (SeatDialogTextItem *item = ctx->text->items,
|
LPCTSTR iconid = IDI_QUESTION;
|
||||||
*end = item + ctx->text->nitems; item < end; item++) {
|
if (scary_heading) {
|
||||||
switch (item->type) {
|
SetDlgItemText(hwnd, IDC_HK_TITLE, scary_heading);
|
||||||
case SDT_PARA:
|
iconid = IDI_WARNING;
|
||||||
put_fmt(dlg_text, "%s\r\n\r\n", item->text);
|
|
||||||
break;
|
|
||||||
case SDT_DISPLAY:
|
|
||||||
put_fmt(dlg_text, "%s\r\n\r\n", item->text);
|
|
||||||
break;
|
|
||||||
case SDT_SCARY_HEADING:
|
|
||||||
SetDlgItemText(hwnd, IDC_HK_TITLE, item->text);
|
|
||||||
iconid = IDI_WARNING;
|
|
||||||
ctx->has_title = true;
|
|
||||||
break;
|
|
||||||
case SDT_TITLE:
|
|
||||||
dlg_title = item->text;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (strbuf_chomp(dlg_text, '\r') || strbuf_chomp(dlg_text, '\n'));
|
|
||||||
|
|
||||||
SetDlgItemText(hwnd, IDC_HK_TEXT, dlg_text->s);
|
SetDlgItemText(hwnd, IDC_HK_TEXT, dlg_text->s);
|
||||||
MakeDlgItemBorderless(hwnd, IDC_HK_TEXT);
|
MakeDlgItemBorderless(hwnd, IDC_HK_TEXT);
|
||||||
@ -1135,6 +1151,8 @@ const SeatDialogPromptDescriptions *win_seat_prompt_descriptions(Seat *seat)
|
|||||||
.hk_connect_once_action = "press \"Connect Once\"",
|
.hk_connect_once_action = "press \"Connect Once\"",
|
||||||
.hk_cancel_action = "press \"Cancel\"",
|
.hk_cancel_action = "press \"Cancel\"",
|
||||||
.hk_cancel_action_Participle = "Pressing \"Cancel\"",
|
.hk_cancel_action_Participle = "Pressing \"Cancel\"",
|
||||||
|
.weak_accept_action = "press \"Yes\"",
|
||||||
|
.weak_cancel_action = "press \"No\"",
|
||||||
};
|
};
|
||||||
return &descs;
|
return &descs;
|
||||||
}
|
}
|
||||||
@ -1169,25 +1187,17 @@ SeatPromptResult win_seat_confirm_ssh_host_key(
|
|||||||
* below the configured 'warn' threshold).
|
* below the configured 'warn' threshold).
|
||||||
*/
|
*/
|
||||||
SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
static const char mbtitle[] = "%s Security Alert";
|
strbuf *dlg_text = strbuf_new();
|
||||||
static const char msg[] =
|
const char *dlg_title = process_seatdialogtext(dlg_text, NULL, text);
|
||||||
"The first %s supported by the server\n"
|
|
||||||
"is %s, which is below the configured\n"
|
|
||||||
"warning threshold.\n"
|
|
||||||
"Do you want to continue with this connection?\n";
|
|
||||||
char *message, *title;
|
|
||||||
int mbret;
|
|
||||||
|
|
||||||
message = dupprintf(msg, algtype, algname);
|
int mbret = MessageBox(NULL, dlg_text->s, dlg_title,
|
||||||
title = dupprintf(mbtitle, appname);
|
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
||||||
mbret = MessageBox(NULL, message, title,
|
|
||||||
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
|
||||||
socket_reselect_all();
|
socket_reselect_all();
|
||||||
sfree(message);
|
strbuf_free(dlg_text);
|
||||||
sfree(title);
|
|
||||||
if (mbret == IDYES)
|
if (mbret == IDYES)
|
||||||
return SPR_OK;
|
return SPR_OK;
|
||||||
else
|
else
|
||||||
@ -1195,27 +1205,17 @@ SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SeatPromptResult win_seat_confirm_weak_cached_hostkey(
|
SeatPromptResult win_seat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx)
|
||||||
{
|
{
|
||||||
static const char mbtitle[] = "%s Security Alert";
|
strbuf *dlg_text = strbuf_new();
|
||||||
static const char msg[] =
|
const char *dlg_title = process_seatdialogtext(dlg_text, NULL, text);
|
||||||
"The first host key type we have stored for this server\n"
|
|
||||||
"is %s, which is below the configured warning threshold.\n"
|
|
||||||
"The server also provides the following types of host key\n"
|
|
||||||
"above the threshold, which we do not have stored:\n"
|
|
||||||
"%s\n"
|
|
||||||
"Do you want to continue with this connection?\n";
|
|
||||||
char *message, *title;
|
|
||||||
int mbret;
|
|
||||||
|
|
||||||
message = dupprintf(msg, algname, betteralgs);
|
int mbret = MessageBox(NULL, dlg_text->s, dlg_title,
|
||||||
title = dupprintf(mbtitle, appname);
|
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
||||||
mbret = MessageBox(NULL, message, title,
|
|
||||||
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
|
||||||
socket_reselect_all();
|
socket_reselect_all();
|
||||||
sfree(message);
|
strbuf_free(dlg_text);
|
||||||
sfree(title);
|
|
||||||
if (mbret == IDYES)
|
if (mbret == IDYES)
|
||||||
return SPR_OK;
|
return SPR_OK;
|
||||||
else
|
else
|
||||||
|
@ -237,10 +237,10 @@ SeatPromptResult win_seat_confirm_ssh_host_key(
|
|||||||
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
char *keystr, SeatDialogText *text, HelpCtx helpctx,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
SeatPromptResult win_seat_confirm_weak_crypto_primitive(
|
||||||
Seat *seat, const char *algtype, const char *algname,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
SeatPromptResult win_seat_confirm_weak_cached_hostkey(
|
SeatPromptResult win_seat_confirm_weak_cached_hostkey(
|
||||||
Seat *seat, const char *algname, const char *betteralgs,
|
Seat *seat, SeatDialogText *text,
|
||||||
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
|
||||||
const SeatDialogPromptDescriptions *win_seat_prompt_descriptions(Seat *seat);
|
const SeatDialogPromptDescriptions *win_seat_prompt_descriptions(Seat *seat);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user