diff options
author | Dimitrij <kvarkas@gmail.com> | 2022-10-31 00:45:23 +0300 |
---|---|---|
committer | Dimitrij <kvarkas@gmail.com> | 2022-10-31 00:45:23 +0300 |
commit | 302fb2e8ddea1c993552c9a30c02f41d01ca54a9 (patch) | |
tree | d6cf1b32664296ef2cecda33caeafbe39e6695c1 /config.c | |
parent | 59105d9b26363e47f00676bd365b2ac8d4cb536a (diff) | |
parent | 4ff82ab29a22936b78510c68f544a99e677efed3 (diff) |
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 605 |
1 files changed, 369 insertions, 236 deletions
@@ -9,13 +9,14 @@ #include "putty.h" #include "dialog.h" #include "storage.h" +#include "tree234.h" #define PRINTER_DISABLED_STRING "None (printing disabled)" #define HOST_BOX_TITLE "Host Name (or IP address)" #define PORT_BOX_TITLE "Port" -void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg, +void conf_radiobutton_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { int button; @@ -28,7 +29,7 @@ void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg, * is the one selected. */ if (event == EVENT_REFRESH) { - int val = conf_get_int(conf, ctrl->radio.context.i); + int val = conf_get_int(conf, ctrl->context.i); for (button = 0; button < ctrl->radio.nbuttons; button++) if (val == ctrl->radio.buttondata[button].i) break; @@ -38,12 +39,12 @@ void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg, } else if (event == EVENT_VALCHANGE) { button = dlg_radiobutton_get(ctrl, dlg); assert(button >= 0 && button < ctrl->radio.nbuttons); - conf_set_int(conf, ctrl->radio.context.i, + conf_set_int(conf, ctrl->context.i, ctrl->radio.buttondata[button].i); } } -void conf_radiobutton_bool_handler(union control *ctrl, dlgparam *dlg, +void conf_radiobutton_bool_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { int button; @@ -55,7 +56,7 @@ void conf_radiobutton_bool_handler(union control *ctrl, dlgparam *dlg, * config option. */ if (event == EVENT_REFRESH) { - int val = conf_get_bool(conf, ctrl->radio.context.i); + int val = conf_get_bool(conf, ctrl->context.i); for (button = 0; button < ctrl->radio.nbuttons; button++) if (val == ctrl->radio.buttondata[button].i) break; @@ -65,13 +66,13 @@ void conf_radiobutton_bool_handler(union control *ctrl, dlgparam *dlg, } else if (event == EVENT_VALCHANGE) { button = dlg_radiobutton_get(ctrl, dlg); assert(button >= 0 && button < ctrl->radio.nbuttons); - conf_set_bool(conf, ctrl->radio.context.i, + conf_set_bool(conf, ctrl->context.i, ctrl->radio.buttondata[button].i); } } #define CHECKBOX_INVERT (1<<30) -void conf_checkbox_handler(union control *ctrl, dlgparam *dlg, +void conf_checkbox_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { int key; @@ -82,7 +83,7 @@ void conf_checkbox_handler(union control *ctrl, dlgparam *dlg, * For a standard checkbox, the context parameter gives the * primary key (CONF_foo), optionally ORed with CHECKBOX_INVERT. */ - key = ctrl->checkbox.context.i; + key = ctrl->context.i; if (key & CHECKBOX_INVERT) { key &= ~CHECKBOX_INVERT; invert = true; @@ -103,27 +104,23 @@ void conf_checkbox_handler(union control *ctrl, dlgparam *dlg, } } -void conf_editbox_handler(union control *ctrl, dlgparam *dlg, +const struct conf_editbox_handler_type conf_editbox_str = {.type = EDIT_STR}; +const struct conf_editbox_handler_type conf_editbox_int = {.type = EDIT_INT}; + +void conf_editbox_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { /* - * The standard edit-box handler expects the main `context' - * field to contain the primary key. The secondary `context2' - * field indicates the type of this field: - * - * - if context2 > 0, the field is a string. - * - if context2 == -1, the field is an int and the edit box - * is numeric. - * - if context2 < -1, the field is an int and the edit box is - * _floating_, and (-context2) gives the scale. (E.g. if - * context2 == -1000, then typing 1.2 into the box will set - * the field to 1200.) + * The standard edit-box handler expects the main `context' field + * to contain the primary key. The secondary `context2' field is a + * pointer to the struct conf_editbox_handler_type defined in + * putty.h. */ - int key = ctrl->editbox.context.i; - int length = ctrl->editbox.context2.i; + int key = ctrl->context.i; + const struct conf_editbox_handler_type *type = ctrl->context2.cp; Conf *conf = (Conf *)data; - if (length > 0) { + if (type->type == EDIT_STR) { if (event == EVENT_REFRESH) { char *field = conf_get_str(conf, key); dlg_editbox_set(ctrl, dlg, field); @@ -132,30 +129,30 @@ void conf_editbox_handler(union control *ctrl, dlgparam *dlg, conf_set_str(conf, key, field); sfree(field); } - } else if (length < 0) { + } else { if (event == EVENT_REFRESH) { char str[80]; int value = conf_get_int(conf, key); - if (length == -1) + if (type->type == EDIT_INT) sprintf(str, "%d", value); else - sprintf(str, "%g", (double)value / (double)(-length)); + sprintf(str, "%g", (double)value / type->denominator); dlg_editbox_set(ctrl, dlg, str); } else if (event == EVENT_VALCHANGE) { char *str = dlg_editbox_get(ctrl, dlg); - if (length == -1) + if (type->type == EDIT_INT) conf_set_int(conf, key, atoi(str)); else - conf_set_int(conf, key, (int)((-length) * atof(str))); + conf_set_int(conf, key, (int)(type->denominator * atof(str))); sfree(str); } } } -void conf_filesel_handler(union control *ctrl, dlgparam *dlg, +void conf_filesel_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { - int key = ctrl->fileselect.context.i; + int key = ctrl->context.i; Conf *conf = (Conf *)data; if (event == EVENT_REFRESH) { @@ -168,10 +165,10 @@ void conf_filesel_handler(union control *ctrl, dlgparam *dlg, } } -void conf_fontsel_handler(union control *ctrl, dlgparam *dlg, +void conf_fontsel_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { - int key = ctrl->fontselect.context.i; + int key = ctrl->context.i; Conf *conf = (Conf *)data; if (event == EVENT_REFRESH) { @@ -184,7 +181,7 @@ void conf_fontsel_handler(union control *ctrl, dlgparam *dlg, } } -static void config_host_handler(union control *ctrl, dlgparam *dlg, +static void config_host_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -216,7 +213,7 @@ static void config_host_handler(union control *ctrl, dlgparam *dlg, } } -static void config_port_handler(union control *ctrl, dlgparam *dlg, +static void config_port_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -257,7 +254,7 @@ static void config_port_handler(union control *ctrl, dlgparam *dlg, } struct hostport { - union control *host, *port, *protradio, *protlist; + dlgcontrol *host, *port, *protradio, *protlist; bool mid_refresh; }; @@ -268,12 +265,12 @@ struct hostport { * and refreshes both host and port boxes when switching to/from the * serial backend. */ -static void config_protocols_handler(union control *ctrl, dlgparam *dlg, +static void config_protocols_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; int curproto = conf_get_int(conf, CONF_protocol); - struct hostport *hp = (struct hostport *)ctrl->generic.context.p; + struct hostport *hp = (struct hostport *)ctrl->context.p; if (event == EVENT_REFRESH) { /* @@ -312,7 +309,7 @@ static void config_protocols_handler(union control *ctrl, dlgparam *dlg, for (size_t i = n_ui_backends; i < PROTOCOL_LIMIT && backends[i]; i++) { dlg_listbox_addwithid(ctrl, dlg, - backends[i]->displayname, + backends[i]->displayname_tc, backends[i]->protocol); if (backends[i]->protocol == curproto) curentry = i - n_ui_backends; @@ -421,7 +418,7 @@ static void config_protocols_handler(union control *ctrl, dlgparam *dlg, } } -static void loggingbuttons_handler(union control *ctrl, dlgparam *dlg, +static void loggingbuttons_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { int button; @@ -450,7 +447,7 @@ static void loggingbuttons_handler(union control *ctrl, dlgparam *dlg, } } -static void numeric_keypad_handler(union control *ctrl, dlgparam *dlg, +static void numeric_keypad_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { int button; @@ -481,7 +478,7 @@ static void numeric_keypad_handler(union control *ctrl, dlgparam *dlg, } } -static void cipherlist_handler(union control *ctrl, dlgparam *dlg, +static void cipherlist_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -490,6 +487,7 @@ static void cipherlist_handler(union control *ctrl, dlgparam *dlg, static const struct { const char *s; int c; } ciphers[] = { { "ChaCha20 (SSH-2 only)", CIPHER_CHACHA20 }, + { "AES-GCM (SSH-2 only)", CIPHER_AESGCM }, { "3DES", CIPHER_3DES }, { "Blowfish", CIPHER_BLOWFISH }, { "DES", CIPHER_DES }, @@ -527,7 +525,7 @@ static void cipherlist_handler(union control *ctrl, dlgparam *dlg, } #ifndef NO_GSSAPI -static void gsslist_handler(union control *ctrl, dlgparam *dlg, +static void gsslist_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -554,7 +552,7 @@ static void gsslist_handler(union control *ctrl, dlgparam *dlg, } #endif -static void kexlist_handler(union control *ctrl, dlgparam *dlg, +static void kexlist_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -562,12 +560,17 @@ static void kexlist_handler(union control *ctrl, dlgparam *dlg, int i; static const struct { const char *s; int k; } kexes[] = { - { "Diffie-Hellman group 1", KEX_DHGROUP1 }, - { "Diffie-Hellman group 14", KEX_DHGROUP14 }, - { "Diffie-Hellman group exchange", KEX_DHGEX }, - { "RSA-based key exchange", KEX_RSA }, - { "ECDH key exchange", KEX_ECDH }, - { "-- warn below here --", KEX_WARN } + { "Diffie-Hellman group 1 (1024-bit)", KEX_DHGROUP1 }, + { "Diffie-Hellman group 14 (2048-bit)", KEX_DHGROUP14 }, + { "Diffie-Hellman group 15 (3072-bit)", KEX_DHGROUP15 }, + { "Diffie-Hellman group 16 (4096-bit)", KEX_DHGROUP16 }, + { "Diffie-Hellman group 17 (6144-bit)", KEX_DHGROUP17 }, + { "Diffie-Hellman group 18 (8192-bit)", KEX_DHGROUP18 }, + { "Diffie-Hellman group exchange", KEX_DHGEX }, + { "RSA-based key exchange", KEX_RSA }, + { "ECDH key exchange", KEX_ECDH }, + { "NTRU Prime / Curve25519 hybrid kex", KEX_NTRU_HYBRID }, + { "-- warn below here --", KEX_WARN } }; /* Set up the "kex preference" box. */ @@ -598,8 +601,8 @@ static void kexlist_handler(union control *ctrl, dlgparam *dlg, } } -static void hklist_handler(union control *ctrl, dlgparam *dlg, - void *data, int event) +static void hklist_handler(dlgcontrol *ctrl, dlgparam *dlg, + void *data, int event) { Conf *conf = (Conf *)data; if (event == EVENT_REFRESH) { @@ -642,7 +645,7 @@ static void hklist_handler(union control *ctrl, dlgparam *dlg, } } -static void printerbox_handler(union control *ctrl, dlgparam *dlg, +static void printerbox_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -678,7 +681,7 @@ static void printerbox_handler(union control *ctrl, dlgparam *dlg, } } -static void codepage_handler(union control *ctrl, dlgparam *dlg, +static void codepage_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -702,7 +705,7 @@ static void codepage_handler(union control *ctrl, dlgparam *dlg, } } -static void sshbug_handler(union control *ctrl, dlgparam *dlg, +static void sshbug_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; @@ -713,7 +716,7 @@ static void sshbug_handler(union control *ctrl, dlgparam *dlg, * spurious SELCHANGE we trigger in the process will overwrite * the value we wanted to keep. */ - int oldconf = conf_get_int(conf, ctrl->listbox.context.i); + int oldconf = conf_get_int(conf, ctrl->context.i); dlg_update_start(ctrl, dlg); dlg_listbox_clear(ctrl, dlg); dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO); @@ -731,13 +734,44 @@ static void sshbug_handler(union control *ctrl, dlgparam *dlg, i = AUTO; else i = dlg_listbox_getid(ctrl, dlg, i); - conf_set_int(conf, ctrl->listbox.context.i, i); + conf_set_int(conf, ctrl->context.i, i); + } +} + +static void sshbug_handler_manual_only(dlgcontrol *ctrl, dlgparam *dlg, + void *data, int event) +{ + /* + * This is just like sshbug_handler, except that there's no 'Auto' + * option. Used for bug workaround flags that can't be + * autodetected, and have to be manually enabled if they're to be + * used at all. + */ + Conf *conf = (Conf *)data; + if (event == EVENT_REFRESH) { + int oldconf = conf_get_int(conf, ctrl->context.i); + dlg_update_start(ctrl, dlg); + dlg_listbox_clear(ctrl, dlg); + dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF); + dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON); + switch (oldconf) { + case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 0); break; + case FORCE_ON: dlg_listbox_select(ctrl, dlg, 1); break; + } + dlg_update_done(ctrl, dlg); + } else if (event == EVENT_SELCHANGE) { + int i = dlg_listbox_index(ctrl, dlg); + if (i < 0) + i = FORCE_OFF; + else + i = dlg_listbox_getid(ctrl, dlg, i); + conf_set_int(conf, ctrl->context.i, i); } } struct sessionsaver_data { - union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton; - union control *okbutton, *cancelbutton; + dlgcontrol *editbox, *listbox, *loadbutton, *savebutton, *delbutton; + dlgcontrol *okbutton, *cancelbutton; struct sesslist sesslist; bool midsession; char *savedsession; /* the current contents of ssd->editbox */ @@ -779,12 +813,12 @@ static bool load_selected_session( return true; } -static void sessionsaver_handler(union control *ctrl, dlgparam *dlg, +static void sessionsaver_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct sessionsaver_data *ssd = - (struct sessionsaver_data *)ctrl->generic.context.p; + (struct sessionsaver_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == ssd->editbox) { @@ -917,15 +951,15 @@ static void sessionsaver_handler(union control *ctrl, dlgparam *dlg, } struct charclass_data { - union control *listbox, *editbox, *button; + dlgcontrol *listbox, *editbox, *button; }; -static void charclass_handler(union control *ctrl, dlgparam *dlg, +static void charclass_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct charclass_data *ccd = - (struct charclass_data *)ctrl->generic.context.p; + (struct charclass_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == ccd->listbox) { @@ -958,7 +992,7 @@ static void charclass_handler(union control *ctrl, dlgparam *dlg, } struct colour_data { - union control *listbox, *redit, *gedit, *bedit, *button; + dlgcontrol *listbox, *redit, *gedit, *bedit, *button; }; /* Array of the user-visible colour names defined in the list macro in @@ -969,12 +1003,12 @@ static const char *const colours[] = { #undef CONF_COLOUR_NAME_DECL }; -static void colour_handler(union control *ctrl, dlgparam *dlg, +static void colour_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct colour_data *cd = - (struct colour_data *)ctrl->generic.context.p; + (struct colour_data *)ctrl->context.p; bool update = false, clear = false; int r, g, b; @@ -1075,15 +1109,15 @@ static void colour_handler(union control *ctrl, dlgparam *dlg, } struct ttymodes_data { - union control *valradio, *valbox, *setbutton, *listbox; + dlgcontrol *valradio, *valbox, *setbutton, *listbox; }; -static void ttymodes_handler(union control *ctrl, dlgparam *dlg, +static void ttymodes_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct ttymodes_data *td = - (struct ttymodes_data *)ctrl->generic.context.p; + (struct ttymodes_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == td->listbox) { @@ -1160,15 +1194,15 @@ static void ttymodes_handler(union control *ctrl, dlgparam *dlg, } struct environ_data { - union control *varbox, *valbox, *addbutton, *rembutton, *listbox; + dlgcontrol *varbox, *valbox, *addbutton, *rembutton, *listbox; }; -static void environ_handler(union control *ctrl, dlgparam *dlg, +static void environ_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct environ_data *ed = - (struct environ_data *)ctrl->generic.context.p; + (struct environ_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == ed->listbox) { @@ -1232,19 +1266,19 @@ static void environ_handler(union control *ctrl, dlgparam *dlg, } struct portfwd_data { - union control *addbutton, *rembutton, *listbox; - union control *sourcebox, *destbox, *direction; + dlgcontrol *addbutton, *rembutton, *listbox; + dlgcontrol *sourcebox, *destbox, *direction; #ifndef NO_IPV6 - union control *addressfamily; + dlgcontrol *addressfamily; #endif }; -static void portfwd_handler(union control *ctrl, dlgparam *dlg, +static void portfwd_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct portfwd_data *pfd = - (struct portfwd_data *)ctrl->generic.context.p; + (struct portfwd_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == pfd->listbox) { @@ -1400,15 +1434,15 @@ static void portfwd_handler(union control *ctrl, dlgparam *dlg, } struct manual_hostkey_data { - union control *addbutton, *rembutton, *listbox, *keybox; + dlgcontrol *addbutton, *rembutton, *listbox, *keybox; }; -static void manual_hostkey_handler(union control *ctrl, dlgparam *dlg, +static void manual_hostkey_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; struct manual_hostkey_data *mh = - (struct manual_hostkey_data *)ctrl->generic.context.p; + (struct manual_hostkey_data *)ctrl->context.p; if (event == EVENT_REFRESH) { if (ctrl == mh->listbox) { @@ -1466,13 +1500,13 @@ static void manual_hostkey_handler(union control *ctrl, dlgparam *dlg, } } -static void clipboard_selector_handler(union control *ctrl, dlgparam *dlg, +static void clipboard_selector_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { Conf *conf = (Conf *)data; - int setting = ctrl->generic.context.i; + int setting = ctrl->context.i; #ifdef NAMED_CLIPBOARDS - int strsetting = ctrl->editbox.context2.i; + int strsetting = ctrl->context2.i; #endif static const struct { @@ -1554,7 +1588,7 @@ static void clipboard_selector_handler(union control *ctrl, dlgparam *dlg, } static void clipboard_control(struct controlset *s, const char *label, - char shortcut, int percentage, intorptr helpctx, + char shortcut, int percentage, HelpCtx helpctx, int setting, int strsetting) { #ifdef NAMED_CLIPBOARDS @@ -1567,7 +1601,7 @@ static void clipboard_control(struct controlset *s, const char *label, #endif } -static void serial_parity_handler(union control *ctrl, dlgparam *dlg, +static void serial_parity_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { static const struct { @@ -1580,7 +1614,7 @@ static void serial_parity_handler(union control *ctrl, dlgparam *dlg, {"Mark", SER_PAR_MARK}, {"Space", SER_PAR_SPACE}, }; - int mask = ctrl->listbox.context.i; + int mask = ctrl->context.i; int i, j; Conf *conf = (Conf *)data; @@ -1622,7 +1656,7 @@ static void serial_parity_handler(union control *ctrl, dlgparam *dlg, } } -static void serial_flow_handler(union control *ctrl, dlgparam *dlg, +static void serial_flow_handler(dlgcontrol *ctrl, dlgparam *dlg, void *data, int event) { static const struct { @@ -1634,7 +1668,7 @@ static void serial_flow_handler(union control *ctrl, dlgparam *dlg, {"RTS/CTS", SER_FLOW_RTSCTS}, {"DSR/DTR", SER_FLOW_DSRDTR}, }; - int mask = ctrl->listbox.context.i; + int mask = ctrl->context.i; int i, j; Conf *conf = (Conf *)data; @@ -1675,6 +1709,67 @@ static void serial_flow_handler(union control *ctrl, dlgparam *dlg, } } +void proxy_type_handler(dlgcontrol *ctrl, dlgparam *dlg, + void *data, int event) +{ + Conf *conf = (Conf *)data; + if (event == EVENT_REFRESH) { + /* + * We must fetch the previously configured value from the Conf + * before we start modifying the drop-down list, otherwise the + * spurious SELCHANGE we trigger in the process will overwrite + * the value we wanted to keep. + */ + int proxy_type = conf_get_int(conf, CONF_proxy_type); + + dlg_update_start(ctrl, dlg); + dlg_listbox_clear(ctrl, dlg); + + int index_to_select = 0, current_index = 0; + +#define ADD(id, title) do { \ + dlg_listbox_addwithid(ctrl, dlg, title, id); \ + if (id == proxy_type) \ + index_to_select = current_index; \ + current_index++; \ + } while (0) + + ADD(PROXY_NONE, "None"); + ADD(PROXY_SOCKS5, "SOCKS 5"); + ADD(PROXY_SOCKS4, "SOCKS 4"); + ADD(PROXY_HTTP, "HTTP CONNECT"); + if (ssh_proxy_supported) { + ADD(PROXY_SSH_TCPIP, "SSH to proxy and use port forwarding"); + ADD(PROXY_SSH_EXEC, "SSH to proxy and execute a command"); + ADD(PROXY_SSH_SUBSYSTEM, "SSH to proxy and invoke a subsystem"); + } + if (ctrl->context.i & PROXY_UI_FLAG_LOCAL) { + ADD(PROXY_CMD, "Local (run a subprogram to connect)"); + } + ADD(PROXY_TELNET, "'Telnet' (send an ad-hoc command)"); + +#undef ADD + + dlg_listbox_select(ctrl, dlg, index_to_select); + + dlg_update_done(ctrl, dlg); + } else if (event == EVENT_SELCHANGE) { + int i = dlg_listbox_index(ctrl, dlg); + if (i < 0) + i = AUTO; + else + i = dlg_listbox_getid(ctrl, dlg, i); + conf_set_int(conf, CONF_proxy_type, i); + } +} + +static void host_ca_button_handler(dlgcontrol *ctrl, dlgparam *dp, + void *data, int event) +{ + if (event == EVENT_ACTION) + show_ca_config_box(dp); +} + void setup_config_box(struct controlbox *b, bool midsession, int protocol, int protcfginfo) { @@ -1687,7 +1782,7 @@ void setup_config_box(struct controlbox *b, bool midsession, struct environ_data *ed; struct portfwd_data *pfd; struct manual_hostkey_data *mh; - union control *c; + dlgcontrol *c; bool resize_forbidden = false; char *str; @@ -1710,11 +1805,11 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(no_help), sessionsaver_handler, P(ssd)); ssd->okbutton->button.isdefault = true; - ssd->okbutton->generic.column = 3; + ssd->okbutton->column = 3; ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help), sessionsaver_handler, P(ssd)); ssd->cancelbutton->button.iscancel = true; - ssd->cancelbutton->generic.column = 4; + ssd->cancelbutton->column = 4; /* We carefully don't close the 5-column part, so that platform- * specific add-ons can put extra buttons alongside Open and Cancel. */ @@ -1736,12 +1831,12 @@ void setup_config_box(struct controlbox *b, bool midsession, c = ctrl_editbox(s, HOST_BOX_TITLE, 'n', 100, HELPCTX(session_hostname), config_host_handler, I(0), I(0)); - c->generic.column = 0; + c->column = 0; hp->host = c; c = ctrl_editbox(s, PORT_BOX_TITLE, 'p', 100, HELPCTX(session_hostname), config_port_handler, I(0), I(0)); - c->generic.column = 1; + c->column = 1; hp->port = c; ctrl_columns(s, 1, 100); @@ -1749,8 +1844,8 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_columns(s, 2, 62, 38); c = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3, HELPCTX(session_hostname), - config_protocols_handler, P(hp), NULL); - c->generic.column = 0; + config_protocols_handler, P(hp)); + c->column = 0; hp->protradio = c; c->radio.buttons = sresize(c->radio.buttons, PROTOCOL_LIMIT, char *); c->radio.shortcuts = sresize(c->radio.shortcuts, PROTOCOL_LIMIT, char); @@ -1762,7 +1857,7 @@ void setup_config_box(struct controlbox *b, bool midsession, for (size_t i = 0; i < n_ui_backends; i++) { assert(backends[i]); c->radio.buttons[c->radio.nbuttons] = - dupstr(backends[i]->displayname); + dupstr(backends[i]->displayname_tc); c->radio.shortcuts[c->radio.nbuttons] = (backends[i]->protocol == PROT_SSH ? 's' : backends[i]->protocol == PROT_SERIAL ? 'r' : @@ -1785,10 +1880,10 @@ void setup_config_box(struct controlbox *b, bool midsession, config_protocols_handler, P(hp)); hp->protlist = c; /* droplist is populated in config_protocols_handler */ - c->generic.column = 1; + c->column = 1; /* Vertically centre the two protocol controls w.r.t. each other */ - hp->protlist->generic.align_next_to = hp->protradio; + hp->protlist->align_next_to = hp->protradio; ctrl_columns(s, 1, 100); } @@ -1804,7 +1899,7 @@ void setup_config_box(struct controlbox *b, bool midsession, ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100, HELPCTX(session_saved), sessionsaver_handler, P(ssd), P(NULL)); - ssd->editbox->generic.column = 0; + ssd->editbox->column = 0; /* Reset columns so that the buttons are alongside the list, rather * than alongside that edit box. */ ctrl_columns(s, 1, 100); @@ -1812,13 +1907,13 @@ void setup_config_box(struct controlbox *b, bool midsession, ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(session_saved), sessionsaver_handler, P(ssd)); - ssd->listbox->generic.column = 0; + ssd->listbox->column = 0; ssd->listbox->listbox.height = 7; if (!midsession) { ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l', HELPCTX(session_saved), sessionsaver_handler, P(ssd)); - ssd->loadbutton->generic.column = 1; + ssd->loadbutton->column = 1; } else { /* We can't offer the Load button mid-session, as it would allow the * user to load and subsequently save settings they can't see. (And @@ -1830,12 +1925,12 @@ void setup_config_box(struct controlbox *b, bool midsession, ssd->savebutton = ctrl_pushbutton(s, "Save", 'v', HELPCTX(session_saved), sessionsaver_handler, P(ssd)); - ssd->savebutton->generic.column = 1; + ssd->savebutton->column = 1; if (!midsession) { ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd', HELPCTX(session_saved), sessionsaver_handler, P(ssd)); - ssd->delbutton->generic.column = 1; + ssd->delbutton->column = 1; } else { /* Disable the Delete button mid-session too, for UI consistency. */ ssd->delbutton = NULL; @@ -1849,7 +1944,7 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_close_on_exit), "Always", I(FORCE_ON), "Never", I(FORCE_OFF), - "Only on clean exit", I(AUTO), NULL); + "Only on clean exit", I(AUTO)); /* * The Session/Logging panel. @@ -1879,8 +1974,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Printable output", 'p', I(LGTYP_ASCII), "All session output", 'l', I(LGTYP_DEBUG), sshlogname, 's', I(LGTYP_PACKETS), - sshrawlogname, 'r', I(LGTYP_SSHRAW), - NULL); + sshrawlogname, 'r', I(LGTYP_SSHRAW)); } ctrl_filesel(s, "Log file name:", 'f', NULL, true, "Select session log file name", @@ -1894,13 +1988,13 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_handler, I(CONF_logxfovr), "Always overwrite it", I(LGXF_OVR), "Always append to the end of it", I(LGXF_APN), - "Ask the user every time", I(LGXF_ASK), NULL); + "Ask the user every time", I(LGXF_ASK)); ctrl_checkbox(s, "Flush log file frequently", 'u', - HELPCTX(logging_flush), - conf_checkbox_handler, I(CONF_logflush)); + HELPCTX(logging_flush), + conf_checkbox_handler, I(CONF_logflush)); ctrl_checkbox(s, "Include header", 'i', - HELPCTX(logging_header), - conf_checkbox_handler, I(CONF_logheader)); + HELPCTX(logging_header), + conf_checkbox_handler, I(CONF_logheader)); if ((midsession && protocol == PROT_SSH) || (!midsession && backend_vt_from_proto(PROT_SSH))) { @@ -1940,7 +2034,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_checkbox_handler, I(CONF_blinktext)); ctrl_editbox(s, "Answerback to ^E:", 's', 100, HELPCTX(terminal_answerback), - conf_editbox_handler, I(CONF_answerback), I(1)); + conf_editbox_handler, I(CONF_answerback), ED_STR); s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options"); ctrl_radiobuttons(s, "Local echo:", 'l', 3, @@ -1948,13 +2042,13 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_handler,I(CONF_localecho), "Auto", I(AUTO), "Force on", I(FORCE_ON), - "Force off", I(FORCE_OFF), NULL); + "Force off", I(FORCE_OFF)); ctrl_radiobuttons(s, "Local line editing:", 't', 3, HELPCTX(terminal_localedit), conf_radiobutton_handler,I(CONF_localedit), "Auto", I(AUTO), "Force on", I(FORCE_ON), - "Force off", I(FORCE_OFF), NULL); + "Force off", I(FORCE_OFF)); s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing"); ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100, @@ -1973,18 +2067,29 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(keyboard_backspace), conf_radiobutton_bool_handler, I(CONF_bksp_is_delete), - "Control-H", I(0), "Control-? (127)", I(1), NULL); + "Control-H", I(0), "Control-? (127)", I(1)); ctrl_radiobuttons(s, "The Home and End keys", 'e', 2, HELPCTX(keyboard_homeend), conf_radiobutton_bool_handler, I(CONF_rxvt_homeend), - "Standard", I(false), "rxvt", I(true), NULL); - ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 3, + "Standard", I(false), "rxvt", I(true)); + ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 4, HELPCTX(keyboard_funkeys), conf_radiobutton_handler, I(CONF_funky_type), - "ESC[n~", I(0), "Linux", I(1), "Xterm R6", I(2), - "VT400", I(3), "VT100+", I(4), "SCO", I(5), NULL); + "ESC[n~", I(FUNKY_TILDE), + "Linux", I(FUNKY_LINUX), + "Xterm R6", I(FUNKY_XTERM), + "VT400", I(FUNKY_VT400), + "VT100+", I(FUNKY_VT100P), + "SCO", I(FUNKY_SCO), + "Xterm 216+", I(FUNKY_XTERM_216)); + ctrl_radiobuttons(s, "Shift/Ctrl/Alt with the arrow keys", 'w', 2, + HELPCTX(keyboard_sharrow), + conf_radiobutton_handler, + I(CONF_sharrow_type), + "Ctrl toggles app mode", I(SHARROW_APPLICATION), + "xterm-style bitmap", I(SHARROW_BITMAP)); s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad", "Application keypad settings:"); @@ -1992,12 +2097,11 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(keyboard_appcursor), conf_radiobutton_bool_handler, I(CONF_app_cursor), - "Normal", I(0), "Application", I(1), NULL); + "Normal", I(0), "Application", I(1)); ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3, HELPCTX(keyboard_appkeypad), numeric_keypad_handler, P(NULL), - "Normal", I(0), "Application", I(1), "NetHack", I(2), - NULL); + "Normal", I(0), "Application", I(1), "NetHack", I(2)); /* * The Terminal/Bell panel. @@ -2011,7 +2115,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_handler, I(CONF_beep), "None (bell disabled)", I(BELL_DISABLED), "Make default system alert sound", I(BELL_DEFAULT), - "Visual bell (flash window)", I(BELL_VISUAL), NULL); + "Visual bell (flash window)", I(BELL_VISUAL)); s = ctrl_getset(b, "Terminal/Bell", "overload", "Control the bell overload behaviour"); @@ -2020,17 +2124,21 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_checkbox_handler, I(CONF_bellovl)); ctrl_editbox(s, "Over-use means this many bells...", 'm', 20, HELPCTX(bell_overload), - conf_editbox_handler, I(CONF_bellovl_n), I(-1)); + conf_editbox_handler, I(CONF_bellovl_n), ED_INT); + + static const struct conf_editbox_handler_type conf_editbox_tickspersec = { + .type = EDIT_FIXEDPOINT, .denominator = TICKSPERSEC}; + ctrl_editbox(s, "... in this many seconds", 't', 20, HELPCTX(bell_overload), conf_editbox_handler, I(CONF_bellovl_t), - I(-TICKSPERSEC)); + CP(&conf_editbox_tickspersec)); ctrl_text(s, "The bell is re-enabled after a few seconds of silence.", HELPCTX(bell_overload)); ctrl_editbox(s, "Seconds of silence required", 's', 20, HELPCTX(bell_overload), conf_editbox_handler, I(CONF_bellovl_s), - I(-TICKSPERSEC)); + CP(&conf_editbox_tickspersec)); /* * The Terminal/Features panel. @@ -2065,7 +2173,7 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_remote_qtitle_action), "None", I(TITLE_NONE), "Empty string", I(TITLE_EMPTY), - "Window title", I(TITLE_REAL), NULL); + "Window title", I(TITLE_REAL)); ctrl_checkbox(s, "Disable remote-controlled clearing of scrollback", 'e', HELPCTX(features_clearscroll), conf_checkbox_handler, @@ -2099,12 +2207,12 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_columns(s, 2, 50, 50); c = ctrl_editbox(s, "Columns", 'm', 100, HELPCTX(window_size), - conf_editbox_handler, I(CONF_width), I(-1)); - c->generic.column = 0; + conf_editbox_handler, I(CONF_width), ED_INT); + c->column = 0; c = ctrl_editbox(s, "Rows", 'r', 100, HELPCTX(window_size), - conf_editbox_handler, I(CONF_height),I(-1)); - c->generic.column = 1; + conf_editbox_handler, I(CONF_height),ED_INT); + c->column = 1; ctrl_columns(s, 1, 100); } @@ -2112,7 +2220,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Control the scrollback in the window"); ctrl_editbox(s, "Lines of scrollback", 's', 50, HELPCTX(window_scrollback), - conf_editbox_handler, I(CONF_savelines), I(-1)); + conf_editbox_handler, I(CONF_savelines), ED_INT); ctrl_checkbox(s, "Display scrollbar", 'd', HELPCTX(window_scrollback), conf_checkbox_handler, I(CONF_scrollbar)); @@ -2142,7 +2250,7 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_cursor_type), "Block", 'l', I(0), "Underline", 'u', I(1), - "Vertical line", 'v', I(2), NULL); + "Vertical line", 'v', I(2)); ctrl_checkbox(s, "Cursor blinks", 'b', HELPCTX(appearance_cursor), conf_checkbox_handler, I(CONF_blink_cur)); @@ -2164,7 +2272,7 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_editbox(s, "Gap between text and window edge:", 'e', 20, HELPCTX(appearance_border), conf_editbox_handler, - I(CONF_window_border), I(-1)); + I(CONF_window_border), ED_INT); /* * The Window/Behaviour panel. @@ -2177,7 +2285,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Adjust the behaviour of the window title"); ctrl_editbox(s, "Window title:", 't', 100, HELPCTX(appearance_title), - conf_editbox_handler, I(CONF_wintitle), I(1)); + conf_editbox_handler, I(CONF_wintitle), ED_STR); ctrl_checkbox(s, "Separate window and icon titles", 'i', HELPCTX(appearance_title), conf_checkbox_handler, @@ -2208,13 +2316,12 @@ void setup_config_box(struct controlbox *b, bool midsession, str = dupprintf("Adjust how %s handles line drawing characters", appname); s = ctrl_getset(b, "Window/Translation", "linedraw", str); sfree(str); - ctrl_radiobuttons(s, "Handling of line drawing characters:", NO_SHORTCUT,1, - HELPCTX(translation_linedraw), - conf_radiobutton_handler, - I(CONF_vtmode), - "Use Unicode line drawing code points",'u',I(VT_UNICODE), - "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN), - NULL); + ctrl_radiobuttons( + s, "Handling of line drawing characters:", NO_SHORTCUT,1, + HELPCTX(translation_linedraw), + conf_radiobutton_handler, I(CONF_vtmode), + "Use Unicode line drawing code points",'u',I(VT_UNICODE), + "Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN)); ctrl_checkbox(s, "Copy and paste line drawing characters as lqqqk",'d', HELPCTX(selection_linedraw), conf_checkbox_handler, I(CONF_rawcnp)); @@ -2239,7 +2346,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_bool_handler, I(CONF_rect_select), "Normal", 'n', I(false), - "Rectangular block", 'r', I(true), NULL); + "Rectangular block", 'r', I(true)); s = ctrl_getset(b, "Window/Selection", "clipboards", "Assign copy/paste actions to clipboards"); @@ -2287,11 +2394,11 @@ void setup_config_box(struct controlbox *b, bool midsession, ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50, HELPCTX(copy_charclasses), charclass_handler, P(ccd), P(NULL)); - ccd->editbox->generic.column = 0; + ccd->editbox->column = 0; ccd->button = ctrl_pushbutton(s, "Set", 's', HELPCTX(copy_charclasses), charclass_handler, P(ccd)); - ccd->button->generic.column = 1; + ccd->button->column = 1; ctrl_columns(s, 1, 100); /* @@ -2315,8 +2422,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_handler, I(CONF_bold_style), "The font", I(1), "The colour", I(2), - "Both", I(3), - NULL); + "Both", I(3)); str = dupprintf("Adjust the precise colours %s displays", appname); s = ctrl_getset(b, "Window/Colours", "adjust", str); @@ -2328,22 +2434,22 @@ void setup_config_box(struct controlbox *b, bool midsession, cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data)); cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u', HELPCTX(colours_config), colour_handler, P(cd)); - cd->listbox->generic.column = 0; + cd->listbox->column = 0; cd->listbox->listbox.height = 7; c = ctrl_text(s, "RGB value:", HELPCTX(colours_config)); - c->generic.column = 1; + c->column = 1; cd->redit = ctrl_editbox(s, "Red", 'r', 50, HELPCTX(colours_config), colour_handler, P(cd), P(NULL)); - cd->redit->generic.column = 1; + cd->redit->column = 1; cd->gedit = ctrl_editbox(s, "Green", 'n', 50, HELPCTX(colours_config), colour_handler, P(cd), P(NULL)); - cd->gedit->generic.column = 1; + cd->gedit->column = 1; cd->bedit = ctrl_editbox(s, "Blue", 'e', 50, HELPCTX(colours_config), colour_handler, P(cd), P(NULL)); - cd->bedit->generic.column = 1; + cd->bedit->column = 1; cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config), colour_handler, P(cd)); - cd->button->generic.column = 1; + cd->button->column = 1; ctrl_columns(s, 1, 100); /* @@ -2358,8 +2464,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Sending of null packets to keep session active"); ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20, HELPCTX(connection_keepalive), - conf_editbox_handler, I(CONF_ping_interval), - I(-1)); + conf_editbox_handler, I(CONF_ping_interval), ED_INT); if (!midsession) { s = ctrl_getset(b, "Connection", "tcp", @@ -2374,15 +2479,14 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_tcp_keepalives)); #ifndef NO_IPV6 s = ctrl_getset(b, "Connection", "ipversion", - "Internet protocol version"); + "Internet protocol version"); ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3, - HELPCTX(connection_ipversion), - conf_radiobutton_handler, - I(CONF_addressfamily), - "Auto", 'u', I(ADDRTYPE_UNSPEC), - "IPv4", '4', I(ADDRTYPE_IPV4), - "IPv6", '6', I(ADDRTYPE_IPV6), - NULL); + HELPCTX(connection_ipversion), + conf_radiobutton_handler, + I(CONF_addressfamily), + "Auto", 'u', I(ADDRTYPE_UNSPEC), + "IPv4", '4', I(ADDRTYPE_IPV4), + "IPv6", '6', I(ADDRTYPE_IPV6)); #endif { @@ -2393,7 +2497,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Logical name of remote host"); ctrl_editbox(s, label, 'm', 100, HELPCTX(connection_loghost), - conf_editbox_handler, I(CONF_loghost), I(1)); + conf_editbox_handler, I(CONF_loghost), ED_STR); } } @@ -2408,7 +2512,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Login details"); ctrl_editbox(s, "Auto-login username", 'u', 50, HELPCTX(connection_username), - conf_editbox_handler, I(CONF_username), I(1)); + conf_editbox_handler, I(CONF_username), ED_STR); { /* We assume the local username is sufficiently stable * to include on the dialog box. */ @@ -2421,8 +2525,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_bool_handler, I(CONF_username_from_env), "Prompt", I(false), - userlabel, I(true), - NULL); + userlabel, I(true)); sfree(userlabel); } @@ -2430,10 +2533,10 @@ void setup_config_box(struct controlbox *b, bool midsession, "Terminal details"); ctrl_editbox(s, "Terminal-type string", 't', 50, HELPCTX(connection_termtype), - conf_editbox_handler, I(CONF_termtype), I(1)); + conf_editbox_handler, I(CONF_termtype), ED_STR); ctrl_editbox(s, "Terminal speeds", 's', 50, HELPCTX(connection_termspeed), - conf_editbox_handler, I(CONF_termspeed), I(1)); + conf_editbox_handler, I(CONF_termspeed), ED_STR); s = ctrl_getset(b, "Connection/Data", "env", "Environment variables"); @@ -2443,19 +2546,19 @@ void setup_config_box(struct controlbox *b, bool midsession, ed->varbox = ctrl_editbox(s, "Variable", 'v', 60, HELPCTX(telnet_environ), environ_handler, P(ed), P(NULL)); - ed->varbox->generic.column = 0; + ed->varbox->column = 0; ed->valbox = ctrl_editbox(s, "Value", 'l', 60, HELPCTX(telnet_environ), environ_handler, P(ed), P(NULL)); - ed->valbox->generic.column = 0; + ed->valbox->column = 0; ed->addbutton = ctrl_pushbutton(s, "Add", 'd', HELPCTX(telnet_environ), environ_handler, P(ed)); - ed->addbutton->generic.column = 1; + ed->addbutton->column = 1; ed->rembutton = ctrl_pushbutton(s, "Remove", 'r', HELPCTX(telnet_environ), environ_handler, P(ed)); - ed->rembutton->generic.column = 1; + ed->rembutton->column = 1; ctrl_columns(s, 1, 100); ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(telnet_environ), @@ -2477,33 +2580,25 @@ void setup_config_box(struct controlbox *b, bool midsession, "Options controlling proxy usage"); s = ctrl_getset(b, "Connection/Proxy", "basics", NULL); - ctrl_radiobuttons(s, "Proxy type:", 't', 3, - HELPCTX(proxy_type), - conf_radiobutton_handler, - I(CONF_proxy_type), - "None", I(PROXY_NONE), - "SOCKS 4", I(PROXY_SOCKS4), - "SOCKS 5", I(PROXY_SOCKS5), - "HTTP", I(PROXY_HTTP), - "Telnet", I(PROXY_TELNET), - NULL); + c = ctrl_droplist(s, "Proxy type:", 't', 70, + HELPCTX(proxy_type), proxy_type_handler, I(0)); ctrl_columns(s, 2, 80, 20); c = ctrl_editbox(s, "Proxy hostname", 'y', 100, HELPCTX(proxy_main), conf_editbox_handler, - I(CONF_proxy_host), I(1)); - c->generic.column = 0; + I(CONF_proxy_host), ED_STR); + c->column = 0; c = ctrl_editbox(s, "Port", 'p', 100, HELPCTX(proxy_main), conf_editbox_handler, I(CONF_proxy_port), - I(-1)); - c->generic.column = 1; + ED_INT); + c->column = 1; ctrl_columns(s, 1, 100); ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100, HELPCTX(proxy_exclude), conf_editbox_handler, - I(CONF_proxy_exclude_list), I(1)); + I(CONF_proxy_exclude_list), ED_STR); ctrl_checkbox(s, "Consider proxying local host connections", 'x', HELPCTX(proxy_exclude), conf_checkbox_handler, @@ -2514,20 +2609,20 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_proxy_dns), "No", I(FORCE_OFF), "Auto", I(AUTO), - "Yes", I(FORCE_ON), NULL); + "Yes", I(FORCE_ON)); ctrl_editbox(s, "Username", 'u', 60, HELPCTX(proxy_auth), conf_editbox_handler, - I(CONF_proxy_username), I(1)); + I(CONF_proxy_username), ED_STR); c = ctrl_editbox(s, "Password", 'w', 60, HELPCTX(proxy_auth), conf_editbox_handler, - I(CONF_proxy_password), I(1)); + I(CONF_proxy_password), ED_STR); c->editbox.password = true; - ctrl_editbox(s, "Telnet command", 'm', 100, + ctrl_editbox(s, "Command to send to proxy (for some types)", 'm', 100, HELPCTX(proxy_command), conf_editbox_handler, - I(CONF_proxy_telnet_command), I(1)); + I(CONF_proxy_telnet_command), ED_STR); ctrl_radiobuttons(s, "Print proxy diagnostics " "in the terminal window", 'r', 5, @@ -2536,7 +2631,7 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_proxy_log_to_term), "No", I(FORCE_OFF), "Yes", I(FORCE_ON), - "Only until session starts", I(AUTO), NULL); + "Only until session starts", I(AUTO)); } /* @@ -2577,7 +2672,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Data to send to the server"); ctrl_editbox(s, "Remote command:", 'r', 100, HELPCTX(ssh_command), - conf_editbox_handler, I(CONF_remote_cmd), I(1)); + conf_editbox_handler, I(CONF_remote_cmd), ED_STR); s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options"); ctrl_checkbox(s, "Don't start a shell or command at all", 'n', @@ -2623,7 +2718,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_handler, I(CONF_sshprot), "2", '2', I(3), - "1 (INSECURE)", '1', I(0), NULL); + "1 (INSECURE)", '1', I(0)); } /* @@ -2656,19 +2751,19 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(ssh_kex_repeat), conf_editbox_handler, I(CONF_ssh_rekey_time), - I(-1)); + ED_INT); #ifndef NO_GSSAPI ctrl_editbox(s, "Minutes between GSS checks (0 for never)", NO_SHORTCUT, 20, HELPCTX(ssh_kex_repeat), conf_editbox_handler, I(CONF_gssapirekey), - I(-1)); + ED_INT); #endif ctrl_editbox(s, "Max data before rekey (0 for no limit)", 'x', 20, HELPCTX(ssh_kex_repeat), conf_editbox_handler, I(CONF_ssh_rekey_data), - I(16)); + ED_STR); ctrl_text(s, "(Use 1M for 1 megabyte, 1G for 1 gigabyte etc)", HELPCTX(ssh_kex_repeat)); } @@ -2704,7 +2799,7 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_columns(s, 2, 75, 25); c = ctrl_text(s, "Host keys or fingerprints to accept:", HELPCTX(ssh_kex_manual_hostkeys)); - c->generic.column = 0; + c->column = 0; /* You want to select from the list, _then_ hit Remove. So * tab order should be that way round. */ mh = (struct manual_hostkey_data *) @@ -2712,8 +2807,8 @@ void setup_config_box(struct controlbox *b, bool midsession, mh->rembutton = ctrl_pushbutton(s, "Remove", 'r', HELPCTX(ssh_kex_manual_hostkeys), manual_hostkey_handler, P(mh)); - mh->rembutton->generic.column = 1; - mh->rembutton->generic.tabdelay = true; + mh->rembutton->column = 1; + mh->rembutton->delay_taborder = true; mh->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(ssh_kex_manual_hostkeys), manual_hostkey_handler, P(mh)); @@ -2727,14 +2822,25 @@ void setup_config_box(struct controlbox *b, bool midsession, mh->keybox = ctrl_editbox(s, "Key", 'k', 80, HELPCTX(ssh_kex_manual_hostkeys), manual_hostkey_handler, P(mh), P(NULL)); - mh->keybox->generic.column = 0; + mh->keybox->column = 0; mh->addbutton = ctrl_pushbutton(s, "Add key", 'y', HELPCTX(ssh_kex_manual_hostkeys), manual_hostkey_handler, P(mh)); - mh->addbutton->generic.column = 1; + mh->addbutton->column = 1; ctrl_columns(s, 1, 100); } + /* + * But there's no reason not to forbid access to the host CA + * configuration box, which is common across sessions in any + * case. + */ + s = ctrl_getset(b, "Connection/SSH/Host keys", "ca", + "Configure trusted certification authorities"); + c = ctrl_pushbutton(s, "Configure host CAs", NO_SHORTCUT, + HELPCTX(ssh_kex_cert), + host_ca_button_handler, I(0)); + if (!midsession || !(protcfginfo == 1 || protcfginfo == -1)) { /* * The Connection/SSH/Cipher panel. @@ -2792,8 +2898,8 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_checkbox_handler, I(CONF_try_ki_auth)); - s = ctrl_getset(b, "Connection/SSH/Auth", "params", - "Authentication parameters"); + s = ctrl_getset(b, "Connection/SSH/Auth", "aux", + "Other authentication-related options"); ctrl_checkbox(s, "Allow agent forwarding", 'f', HELPCTX(ssh_auth_agentfwd), conf_checkbox_handler, I(CONF_agentfwd)); @@ -2801,11 +2907,26 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(ssh_auth_changeuser), conf_checkbox_handler, I(CONF_change_username)); + + ctrl_settitle(b, "Connection/SSH/Auth/Credentials", + "Credentials to authenticate with"); + + s = ctrl_getset(b, "Connection/SSH/Auth/Credentials", "publickey", + "Public-key authentication"); ctrl_filesel(s, "Private key file for authentication:", 'k', FILTER_KEY_FILES, false, "Select private key file", HELPCTX(ssh_auth_privkey), conf_filesel_handler, I(CONF_keyfile)); - + ctrl_filesel(s, "Certificate to use with the private key:", 'e', + NULL, false, "Select certificate file", + HELPCTX(ssh_auth_cert), + conf_filesel_handler, I(CONF_detached_cert)); + + s = ctrl_getset(b, "Connection/SSH/Auth/Credentials", "plugin", + "Plugin to provide authentication responses"); + ctrl_editbox(s, "Plugin command to run", NO_SHORTCUT, 100, + HELPCTX(ssh_auth_plugin), + conf_editbox_handler, I(CONF_auth_plugin), ED_STR); #ifndef NO_GSSAPI /* * Connection/SSH/Auth/GSSAPI, which sadly won't fit on @@ -2894,12 +3015,12 @@ void setup_config_box(struct controlbox *b, bool midsession, td->listbox->listbox.percentages[1] = 60; ctrl_columns(s, 2, 75, 25); c = ctrl_text(s, "For selected mode, send:", HELPCTX(ssh_ttymodes)); - c->generic.column = 0; + c->column = 0; td->setbutton = ctrl_pushbutton(s, "Set", 's', HELPCTX(ssh_ttymodes), ttymodes_handler, P(td)); - td->setbutton->generic.column = 1; - td->setbutton->generic.tabdelay = true; + td->setbutton->column = 1; + td->setbutton->delay_taborder = true; ctrl_columns(s, 1, 100); /* column break */ /* Bit of a hack to get the value radio buttons and * edit-box on the same row. */ @@ -2909,14 +3030,13 @@ void setup_config_box(struct controlbox *b, bool midsession, ttymodes_handler, P(td), "Auto", NO_SHORTCUT, P(NULL), "Nothing", NO_SHORTCUT, P(NULL), - "This:", NO_SHORTCUT, P(NULL), - NULL); - td->valradio->generic.column = 0; + "This:", NO_SHORTCUT, P(NULL)); + td->valradio->column = 0; td->valbox = ctrl_editbox(s, NULL, NO_SHORTCUT, 100, HELPCTX(ssh_ttymodes), ttymodes_handler, P(td), P(NULL)); - td->valbox->generic.column = 1; - td->valbox->generic.align_next_to = td->valradio; + td->valbox->column = 1; + td->valbox->align_next_to = td->valradio; ctrl_tabdelay(s, td->setbutton); } @@ -2933,13 +3053,13 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_checkbox_handler,I(CONF_x11_forward)); ctrl_editbox(s, "X display location", 'x', 50, HELPCTX(ssh_tunnels_x11), - conf_editbox_handler, I(CONF_x11_display), I(1)); + conf_editbox_handler, I(CONF_x11_display), ED_STR); ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2, HELPCTX(ssh_tunnels_x11auth), conf_radiobutton_handler, I(CONF_x11_auth), "MIT-Magic-Cookie-1", I(X11_MIT), - "XDM-Authorization-1", I(X11_XDM), NULL); + "XDM-Authorization-1", I(X11_XDM)); } /* @@ -2961,15 +3081,15 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_columns(s, 3, 55, 20, 25); c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd)); - c->generic.column = COLUMN_FIELD(0,2); + c->column = COLUMN_FIELD(0,2); /* You want to select from the list, _then_ hit Remove. So tab order * should be that way round. */ pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data)); pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r', HELPCTX(ssh_tunnels_portfwd), portfwd_handler, P(pfd)); - pfd->rembutton->generic.column = 2; - pfd->rembutton->generic.tabdelay = true; + pfd->rembutton->column = 2; + pfd->rembutton->delay_taborder = true; pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(ssh_tunnels_portfwd), portfwd_handler, P(pfd)); @@ -2985,12 +3105,12 @@ void setup_config_box(struct controlbox *b, bool midsession, pfd->addbutton = ctrl_pushbutton(s, "Add", 'd', HELPCTX(ssh_tunnels_portfwd), portfwd_handler, P(pfd)); - pfd->addbutton->generic.column = 2; - pfd->addbutton->generic.tabdelay = true; + pfd->addbutton->column = 2; + pfd->addbutton->delay_taborder = true; pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40, HELPCTX(ssh_tunnels_portfwd), portfwd_handler, P(pfd), P(NULL)); - pfd->sourcebox->generic.column = 0; + pfd->sourcebox->column = 0; pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67, HELPCTX(ssh_tunnels_portfwd), portfwd_handler, P(pfd), P(NULL)); @@ -2999,8 +3119,7 @@ void setup_config_box(struct controlbox *b, bool midsession, portfwd_handler, P(pfd), "Local", 'l', P(NULL), "Remote", 'm', P(NULL), - "Dynamic", 'y', P(NULL), - NULL); + "Dynamic", 'y', P(NULL)); #ifndef NO_IPV6 pfd->addressfamily = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3, @@ -3008,8 +3127,7 @@ void setup_config_box(struct controlbox *b, bool midsession, portfwd_handler, P(pfd), "Auto", 'u', I(ADDRTYPE_UNSPEC), "IPv4", '4', I(ADDRTYPE_IPV4), - "IPv6", '6', I(ADDRTYPE_IPV6), - NULL); + "IPv6", '6', I(ADDRTYPE_IPV6)); #endif ctrl_tabdelay(s, pfd->addbutton); ctrl_columns(s, 1, 100); @@ -3039,6 +3157,17 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(ssh_bugs_maxpkt2), sshbug_handler, I(CONF_sshbug_maxpkt2)); + s = ctrl_getset(b, "Connection/SSH/Bugs", "manual", + "Manually enabled workarounds"); + ctrl_droplist(s, "Discards data sent before its greeting", 'd', 20, + HELPCTX(ssh_bugs_dropstart), + sshbug_handler_manual_only, + I(CONF_sshbug_dropstart)); + ctrl_droplist(s, "Chokes on PuTTY's full KEXINIT", 'p', 20, + HELPCTX(ssh_bugs_filter_kexinit), + sshbug_handler_manual_only, + I(CONF_sshbug_filter_kexinit)); + ctrl_settitle(b, "Connection/SSH/More bugs", "Further workarounds for SSH server bugs"); @@ -3090,22 +3219,26 @@ void setup_config_box(struct controlbox *b, bool midsession, "Select a serial line"); ctrl_editbox(s, "Serial line to connect to", 'l', 40, HELPCTX(serial_line), - conf_editbox_handler, I(CONF_serline), I(1)); + conf_editbox_handler, I(CONF_serline), ED_STR); } s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line"); ctrl_editbox(s, "Speed (baud)", 's', 40, HELPCTX(serial_speed), - conf_editbox_handler, I(CONF_serspeed), I(-1)); + conf_editbox_handler, I(CONF_serspeed), ED_INT); ctrl_editbox(s, "Data bits", 'b', 40, HELPCTX(serial_databits), - conf_editbox_handler, I(CONF_serdatabits), I(-1)); + conf_editbox_handler, I(CONF_serdatabits), ED_INT); /* * Stop bits come in units of one half. */ + static const struct conf_editbox_handler_type conf_editbox_stopbits = { + .type = EDIT_FIXEDPOINT, .denominator = 2}; + ctrl_editbox(s, "Stop bits", 't', 40, HELPCTX(serial_stopbits), - conf_editbox_handler, I(CONF_serstopbits), I(-2)); + conf_editbox_handler, I(CONF_serstopbits), + CP(&conf_editbox_stopbits)); ctrl_droplist(s, "Parity", 'p', 40, HELPCTX(serial_parity), serial_parity_handler, I(ser_vt->serial_parity_mask)); @@ -3131,12 +3264,12 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_radiobutton_bool_handler, I(CONF_rfc_environ), "BSD (commonplace)", 'b', I(false), - "RFC 1408 (unusual)", 'f', I(true), NULL); + "RFC 1408 (unusual)", 'f', I(true)); ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2, HELPCTX(telnet_passive), conf_radiobutton_bool_handler, I(CONF_passive_telnet), - "Passive", I(true), "Active", I(false), NULL); + "Passive", I(true), "Active", I(false)); } ctrl_checkbox(s, "Keyboard sends Telnet special commands", 'k', HELPCTX(telnet_specialkeys), @@ -3159,7 +3292,7 @@ void setup_config_box(struct controlbox *b, bool midsession, "Data to send to the server"); ctrl_editbox(s, "Local username:", 'l', 50, HELPCTX(rlogin_localuser), - conf_editbox_handler, I(CONF_localusername), I(1)); + conf_editbox_handler, I(CONF_localusername), ED_STR); } @@ -3175,7 +3308,7 @@ void setup_config_box(struct controlbox *b, bool midsession, ctrl_editbox(s, "Location string", 'l', 70, HELPCTX(supdup_location), conf_editbox_handler, I(CONF_supdup_location), - I(1)); + ED_STR); ctrl_radiobuttons(s, "Extended ASCII Character set:", 'e', 4, HELPCTX(supdup_ascii), @@ -3183,7 +3316,7 @@ void setup_config_box(struct controlbox *b, bool midsession, I(CONF_supdup_ascii_set), "None", I(SUPDUP_CHARSET_ASCII), "ITS", I(SUPDUP_CHARSET_ITS), - "WAITS", I(SUPDUP_CHARSET_WAITS), NULL); + "WAITS", I(SUPDUP_CHARSET_WAITS)); ctrl_checkbox(s, "**MORE** processing", 'm', HELPCTX(supdup_more), |