1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05:00

Revamp interface to verify_ssh_host_key() and askalg(). Each of them

now returns an integer: 0 means cancel the SSH connection and 1
means continue with it. Additionally, they can return -1, which
means `front end has set an asynchronous alert box in motion, please
wait to be called back with the result', and each one is passed a
callback function pointer and context for this purpose.

I have not yet done the same to askappend() yet, because it will
take a certain amount of reorganisation of logging.c.

Importantly, this checkin means the host key dialog box now works on
OS X.

[originally from svn r5330]
This commit is contained in:
Simon Tatham
2005-02-17 18:34:24 +00:00
parent 92ccb964a2
commit 8574822b9b
11 changed files with 456 additions and 140 deletions

View File

@ -16,13 +16,6 @@ version of the port decides to look somewhere completely different
for the data and therefore loses them all. If that happens, don't
say you weren't warned!
Even more importantly, the alert box that confirms host keys is not
yet implemented, and the application will bomb out and exit if it
should be needed. This means you cannot make an SSH connection to a
new host using the GUI PuTTY in this port: you must first run
`plink' (which should be exactly identical to the version in the
Unix port) and tell it to confirm the host key.
Other ways in which the port is currently unfinished include:
- terminal display is horribly slow

View File

@ -40,6 +40,8 @@ extern AppController *controller;
void *ldisc;
Backend *back;
void *backhandle;
void (*alert_callback)(void *, int);
void *alert_ctx;
}
- (id)initWithConfig:(Config)cfg;
- (void)drawStartFinish:(BOOL)start;
@ -48,6 +50,8 @@ extern AppController *controller;
- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
attr:(unsigned long)attr lattr:(int)lattr;
- (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr;
- (void)startAlert:(NSAlert *)alert
withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx;
@end
/*

View File

@ -311,16 +311,104 @@ int askappend(void *frontend, Filename filename)
return 0; /* FIXME */
}
void askalg(void *frontend, const char *algtype, const char *algname)
struct algstate {
void (*callback)(void *ctx, int result);
void *ctx;
};
static void askalg_callback(void *ctx, int result)
{
fatalbox("Cipher algorithm dialog box not supported yet");
return; /* FIXME */
struct algstate *state = (struct algstate *)ctx;
state->callback(state->ctx, result == 0);
sfree(state);
}
void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
char *keystr, char *fingerprint)
int askalg(void *frontend, const char *algtype, const char *algname,
void (*callback)(void *ctx, int 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;
SessionWindow *win = (SessionWindow *)frontend;
struct algstate *state;
NSAlert *alert;
text = dupprintf(msg, algtype, algname);
state = snew(struct algstate);
state->callback = callback;
state->ctx = ctx;
alert = [NSAlert alloc];
[alert setInformativeText:[NSString stringWithCString:text]];
[alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"];
[win startAlert:alert withCallback:askalg_callback andCtx:state];
return -1;
}
struct hostkeystate {
char *host, *keytype, *keystr;
int port;
void (*callback)(void *ctx, int result);
void *ctx;
};
static void verify_ssh_host_key_callback(void *ctx, int result)
{
struct hostkeystate *state = (struct hostkeystate *)ctx;
if (result == NSAlertThirdButtonReturn) /* `Accept' */
store_host_key(state->host, state->port,
state->keytype, state->keystr);
state->callback(state->ctx, result != NSAlertFirstButtonReturn);
sfree(state->host);
sfree(state->keytype);
sfree(state->keystr);
sfree(state);
}
int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
char *keystr, char *fingerprint,
void (*callback)(void *ctx, int result), void *ctx)
{
static const char absenttxt[] =
"The server's host key is not cached. You have no guarantee "
"that the server is the computer you think it is.\n"
"The server's %s key fingerprint is:\n"
"%s\n"
"If you trust this host, press \"Accept\" to add the key to "
"PuTTY's cache and carry on connecting.\n"
"If you want to carry on connecting just once, without "
"adding the key to the cache, press \"Connect Once\".\n"
"If you do not trust this host, press \"Cancel\" to abandon the "
"connection.";
static const char wrongtxt[] =
"WARNING - POTENTIAL SECURITY BREACH!\n"
"The server's host key does not match the one PuTTY has "
"cached. This means that either the server administrator "
"has changed the host key, or you have actually connected "
"to another computer pretending to be the server.\n"
"The new %s key fingerprint is:\n"
"%s\n"
"If you were expecting this change and trust the new key, "
"press \"Accept\" to update PuTTY's cache and continue connecting.\n"
"If you want to carry on connecting but without updating "
"the cache, press \"Connect Once\".\n"
"If you want to abandon the connection completely, press "
"\"Cancel\" to cancel. Pressing \"Cancel\" is the ONLY guaranteed "
"safe choice.";
int ret;
char *text;
SessionWindow *win = (SessionWindow *)frontend;
struct hostkeystate *state;
NSAlert *alert;
/*
* Verify the key.
@ -328,30 +416,27 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
ret = verify_host_key(host, port, keytype, keystr);
if (ret == 0)
return;
return 1;
/*
* FIXME FIXME FIXME. I currently lack any sensible means of
* asking the user for a verification non-application-modally,
* _or_ any means of closing just this connection if the answer
* is no (the Unix and Windows ports just exit() in this
* situation since they're one-connection-per-process).
*
* What I need to do is to make this function optionally-
* asynchronous, much like the interface to agent_query(). It
* can either run modally and return a result directly, _or_ it
* can kick off a non-modal dialog, return a `please wait'
* status, and the dialog can call the backend back when the
* result comes in. Also, in either case, the aye/nay result
* wants to be passed to the backend so that it can tear down
* the connection if the answer was nay.
*
* For the moment, I simply bomb out if we have an unrecognised
* host key. This makes this port safe but not very useful: you
* can only use it at all if you already have a host key cache
* set up by running the Unix port.
*/
fatalbox("Host key dialog box not supported yet");
text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, fingerprint);
state = snew(struct hostkeystate);
state->callback = callback;
state->ctx = ctx;
state->host = dupstr(host);
state->port = port;
state->keytype = dupstr(keytype);
state->keystr = dupstr(keystr);
alert = [[NSAlert alloc] init];
[alert setInformativeText:[NSString stringWithCString:text]];
[alert addButtonWithTitle:@"Cancel"];
[alert addButtonWithTitle:@"Connect Once"];
[alert addButtonWithTitle:@"Accept"];
[win startAlert:alert withCallback:verify_ssh_host_key_callback
andCtx:state];
return -1;
}
void old_keyfile_warning(void)

View File

@ -207,6 +207,8 @@
{
NSRect rect = { {0,0}, {0,0} };
alert_ctx = NULL;
cfg = aCfg; /* structure copy */
init_ucs(&ucsdata, cfg.line_codepage, cfg.utf8_override,
@ -307,6 +309,7 @@
* terminal, the backend, the ldisc, the logctx, you name it.
* Do so.
*/
sfree(alert_ctx);
[super dealloc];
}
@ -778,6 +781,23 @@ printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
return term_data(term, is_stderr, data, len);
}
- (void)startAlert:(NSAlert *)alert
withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx
{
alert_callback = callback;
alert_ctx = ctx; /* NB this is assumed to need freeing! */
[alert beginSheetModalForWindow:self modalDelegate:self
didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
contextInfo:NULL];
}
- (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
contextInfo:(void *)contextInfo
{
alert_callback(alert_ctx, returnCode); /* transfers ownership of ctx */
alert_ctx = NULL;
}
@end
int from_backend(void *frontend, int is_stderr, const char *data, int len)