X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/1ddda1ca78c0458141b45197544597c566184b6f..3d5040f8f85f049cbb072a827a6184b4b4314b08:/macosx/osxdlg.m diff --git a/macosx/osxdlg.m b/macosx/osxdlg.m index 5bc13a43..295b6755 100644 --- a/macosx/osxdlg.m +++ b/macosx/osxdlg.m @@ -123,12 +123,10 @@ int hmin = 0; int panelht = 0; - get_sesslist(&sl, TRUE); - ctrlbox = ctrl_new_box(); - setup_config_box(ctrlbox, &sl, FALSE /*midsession*/, aCfg.protocol, + setup_config_box(ctrlbox, FALSE /*midsession*/, aCfg.protocol, 0 /* protcfginfo */); - unix_setup_config_box(ctrlbox, FALSE /*midsession*/); + unix_setup_config_box(ctrlbox, FALSE /*midsession*/, aCfg.protocol); cfg = aCfg; /* structure copy */ @@ -306,21 +304,148 @@ * Various special-purpose dialog boxes. */ -int askappend(void *frontend, Filename filename) +struct appendstate { + void (*callback)(void *ctx, int result); + void *ctx; +}; + +static void askappend_callback(void *ctx, int result) +{ + struct appendstate *state = (struct appendstate *)ctx; + + state->callback(state->ctx, (result == NSAlertFirstButtonReturn ? 2 : + result == NSAlertSecondButtonReturn ? 1 : 0)); + sfree(state); +} + +int askappend(void *frontend, Filename filename, + void (*callback)(void *ctx, int result), void *ctx) +{ + static const char msgtemplate[] = + "The session log file \"%s\" already exists. " + "You can overwrite it with a new session log, " + "append your session log to the end of it, " + "or disable session logging for this session."; + + char *text; + SessionWindow *win = (SessionWindow *)frontend; + struct appendstate *state; + NSAlert *alert; + + text = dupprintf(msgtemplate, filename.path); + + state = snew(struct appendstate); + state->callback = callback; + state->ctx = ctx; + + alert = [[NSAlert alloc] init]; + [alert setInformativeText:[NSString stringWithCString:text]]; + [alert addButtonWithTitle:@"Overwrite"]; + [alert addButtonWithTitle:@"Append"]; + [alert addButtonWithTitle:@"Disable"]; + [win startAlert:alert withCallback:askappend_callback andCtx:state]; + + return -1; +} + +struct algstate { + void (*callback)(void *ctx, int result); + void *ctx; +}; + +static void askalg_callback(void *ctx, int result) +{ + struct algstate *state = (struct algstate *)ctx; + + state->callback(state->ctx, result == NSAlertFirstButtonReturn); + sfree(state); +} + +int askalg(void *frontend, const char *algtype, const char *algname, + void (*callback)(void *ctx, int result), void *ctx) { - return 0; /* FIXME */ + 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] init]; + [alert setInformativeText:[NSString stringWithCString:text]]; + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + [win startAlert:alert withCallback:askalg_callback andCtx:state]; + + return -1; } -void askalg(void *frontend, const char *algtype, const char *algname) +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) { - fatalbox("Cipher algorithm dialog box not supported yet"); - return; /* FIXME */ + 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); } -void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, - char *keystr, char *fingerprint) +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 +453,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; - - /* - * 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"); + return 1; + + 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) @@ -361,7 +483,27 @@ void old_keyfile_warning(void) */ } -void about_box(void *window) +static void connection_fatal_callback(void *ctx, int result) +{ + SessionWindow *win = (SessionWindow *)ctx; + + [win endSession:FALSE]; +} + +void connection_fatal(void *frontend, char *p, ...) { - /* FIXME */ + SessionWindow *win = (SessionWindow *)frontend; + va_list ap; + char *msg; + NSAlert *alert; + + va_start(ap, p); + msg = dupvprintf(p, ap); + va_end(ap); + + alert = [[NSAlert alloc] init]; + [alert setInformativeText:[NSString stringWithCString:msg]]; + [alert addButtonWithTitle:@"Proceed"]; + [win startAlert:alert withCallback:connection_fatal_callback + andCtx:win]; }