}
}
+#ifndef NO_GSSAPI
+static void gsslist_handler(union control *ctrl, void *dlg,
+ void *data, int event)
+{
+ Config *cfg = (Config *)data;
+ if (event == EVENT_REFRESH) {
+ int i;
+
+ dlg_update_start(ctrl, dlg);
+ dlg_listbox_clear(ctrl, dlg);
+ for (i = 0; i < ngsslibs; i++) {
+ int id = cfg->ssh_gsslist[i];
+ assert(id >= 0 && id < ngsslibs);
+ dlg_listbox_addwithid(ctrl, dlg, gsslibnames[id], id);
+ }
+ dlg_update_done(ctrl, dlg);
+
+ } else if (event == EVENT_VALCHANGE) {
+ int i;
+
+ /* Update array to match the list box. */
+ for (i=0; i < ngsslibs; i++)
+ cfg->ssh_gsslist[i] = dlg_listbox_getid(ctrl, dlg, i);
+ }
+}
+#endif
+
static void kexlist_handler(union control *ctrl, void *dlg,
void *data, int event)
{
Config *cfg = (Config *)data;
if (event == EVENT_REFRESH) {
int i;
- const char *cp;
+ const char *cp, *thiscp;
dlg_update_start(ctrl, dlg);
- strcpy(cfg->line_codepage,
- cp_name(decode_codepage(cfg->line_codepage)));
+ thiscp = cp_name(decode_codepage(cfg->line_codepage));
dlg_listbox_clear(ctrl, dlg);
for (i = 0; (cp = cp_enumerate(i)) != NULL; i++)
dlg_listbox_add(ctrl, dlg, cp);
- dlg_editbox_set(ctrl, dlg, cfg->line_codepage);
+ dlg_editbox_set(ctrl, dlg, thiscp);
+ strcpy(cfg->line_codepage, thiscp);
dlg_update_done(ctrl, dlg);
} else if (event == EVENT_VALCHANGE) {
dlg_editbox_get(ctrl, dlg, cfg->line_codepage,
Config *cfg = (Config *)data;
struct colour_data *cd =
(struct colour_data *)ctrl->generic.context.p;
- int update = FALSE, r, g, b;
+ int update = FALSE, clear = FALSE, r, g, b;
if (event == EVENT_REFRESH) {
if (ctrl == cd->listbox) {
for (i = 0; i < lenof(colours); i++)
dlg_listbox_add(ctrl, dlg, colours[i]);
dlg_update_done(ctrl, dlg);
- dlg_editbox_set(cd->redit, dlg, "");
- dlg_editbox_set(cd->gedit, dlg, "");
- dlg_editbox_set(cd->bedit, dlg, "");
+ clear = TRUE;
+ update = TRUE;
}
} else if (event == EVENT_SELCHANGE) {
if (ctrl == cd->listbox) {
/* The user has selected a colour. Update the RGB text. */
int i = dlg_listbox_index(ctrl, dlg);
if (i < 0) {
- dlg_beep(dlg);
- return;
+ clear = TRUE;
+ } else {
+ clear = FALSE;
+ r = cfg->colours[i][0];
+ g = cfg->colours[i][1];
+ b = cfg->colours[i][2];
}
- r = cfg->colours[i][0];
- g = cfg->colours[i][1];
- b = cfg->colours[i][2];
update = TRUE;
}
} else if (event == EVENT_VALCHANGE) {
cfg->colours[i][0] = r;
cfg->colours[i][1] = g;
cfg->colours[i][2] = b;
+ clear = FALSE;
update = TRUE;
}
}
}
if (update) {
- char buf[40];
- sprintf(buf, "%d", r); dlg_editbox_set(cd->redit, dlg, buf);
- sprintf(buf, "%d", g); dlg_editbox_set(cd->gedit, dlg, buf);
- sprintf(buf, "%d", b); dlg_editbox_set(cd->bedit, dlg, buf);
+ if (clear) {
+ dlg_editbox_set(cd->redit, dlg, "");
+ dlg_editbox_set(cd->gedit, dlg, "");
+ dlg_editbox_set(cd->bedit, dlg, "");
+ } else {
+ char buf[40];
+ sprintf(buf, "%d", r); dlg_editbox_set(cd->redit, dlg, buf);
+ sprintf(buf, "%d", g); dlg_editbox_set(cd->gedit, dlg, buf);
+ sprintf(buf, "%d", b); dlg_editbox_set(cd->bedit, dlg, buf);
+ }
}
}
*p = '\0';
p = cfg->portfwd;
while (*p) {
+ if (strcmp(p,str) == 0) {
+ dlg_error_msg(dlg, "Specified forwarding already exists");
+ break;
+ }
while (*p)
p++;
p++;
}
- if ((p - cfg->portfwd) + strlen(str) + 2 <=
- sizeof(cfg->portfwd)) {
- strcpy(p, str);
- p[strlen(str) + 1] = '\0';
- dlg_listbox_add(pfd->listbox, dlg, str);
- dlg_editbox_set(pfd->sourcebox, dlg, "");
- dlg_editbox_set(pfd->destbox, dlg, "");
- } else {
- dlg_error_msg(dlg, "Too many forwardings");
+ if (!*p) {
+ if ((p - cfg->portfwd) + strlen(str) + 2 <=
+ sizeof(cfg->portfwd)) {
+ strcpy(p, str);
+ p[strlen(str) + 1] = '\0';
+ dlg_listbox_add(pfd->listbox, dlg, str);
+ dlg_editbox_set(pfd->sourcebox, dlg, "");
+ dlg_editbox_set(pfd->destbox, dlg, "");
+ } else {
+ dlg_error_msg(dlg, "Too many forwardings");
+ }
}
} else if (ctrl == pfd->rembutton) {
int i = dlg_listbox_index(pfd->listbox, dlg);
{
static const char *const afs = "A46";
char *afp = strchr(afs, *p);
+#ifndef NO_IPV6
int idx = afp ? afp-afs : 0;
+#endif
if (afp)
p++;
#ifndef NO_IPV6
ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 3,
HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp),
- "Raw", 'r', I(PROT_RAW),
+ "Raw", 'w', I(PROT_RAW),
"Telnet", 't', I(PROT_TELNET),
"Rlogin", 'i', I(PROT_RLOGIN),
NULL);
ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 4,
HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp),
- "Raw", 'r', I(PROT_RAW),
+ "Raw", 'w', I(PROT_RAW),
"Telnet", 't', I(PROT_TELNET),
"Rlogin", 'i', I(PROT_RLOGIN),
"SSH", 's', I(PROT_SSH),
ctrl_columns(s, 1, 100);
s = ctrl_getset(b, "Session", "otheropts", NULL);
- c = ctrl_radiobuttons(s, "Close window on exit:", 'w', 4,
+ c = ctrl_radiobuttons(s, "Close window on exit:", 'x', 4,
HELPCTX(session_coe),
dlg_stdradiobutton_handler,
I(offsetof(Config, close_on_exit)),
"Options controlling character set translation");
s = ctrl_getset(b, "Window/Translation", "trans",
- "Character set translation on received data");
- ctrl_combobox(s, "Received data assumed to be in which character set:",
+ "Character set translation");
+ ctrl_combobox(s, "Remote character set:",
'r', 100, HELPCTX(translation_codepage),
codepage_handler, P(NULL), P(NULL));
"IPv6", '6', I(ADDRTYPE_IPV6),
NULL);
#endif
+
+ {
+ char *label = backend_from_proto(PROT_SSH) ?
+ "Logical name of remote host (e.g. for SSH key lookup):" :
+ "Logical name of remote host:";
+ s = ctrl_getset(b, "Connection", "identity",
+ "Logical name of remote host");
+ ctrl_editbox(s, label, 'm', 100,
+ HELPCTX(connection_loghost),
+ dlg_stdeditbox_handler, I(offsetof(Config,loghost)),
+ I(sizeof(((Config *)0)->loghost)));
+ }
}
/*
HELPCTX(connection_username),
dlg_stdeditbox_handler, I(offsetof(Config,username)),
I(sizeof(((Config *)0)->username)));
+ {
+ /* We assume the local username is sufficiently stable
+ * to include on the dialog box. */
+ char *user = get_username();
+ char *userlabel = dupprintf("Use system username (%s)",
+ user ? user : "");
+ sfree(user);
+ ctrl_radiobuttons(s, "When username is not specified:", 'n', 4,
+ HELPCTX(connection_username_from_env),
+ dlg_stdradiobutton_handler,
+ I(offsetof(Config, username_from_env)),
+ "Prompt", I(FALSE),
+ userlabel, I(TRUE),
+ NULL);
+ sfree(userlabel);
+ }
s = ctrl_getset(b, "Connection/Data", "term",
"Terminal details");
HELPCTX(ssh_auth_bypass),
dlg_stdcheckbox_handler,
I(offsetof(Config,ssh_no_userauth)));
+ ctrl_checkbox(s, "Display pre-authentication banner (SSH-2 only)",
+ 'd', HELPCTX(ssh_auth_banner),
+ dlg_stdcheckbox_handler,
+ I(offsetof(Config,ssh_show_banner)));
s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
"Authentication methods");
ctrl_checkbox(s, "Allow agent forwarding", 'f',
HELPCTX(ssh_auth_agentfwd),
dlg_stdcheckbox_handler, I(offsetof(Config,agentfwd)));
- ctrl_checkbox(s, "Allow attempted changes of username in SSH-2", 'u',
+ ctrl_checkbox(s, "Allow attempted changes of username in SSH-2", NO_SHORTCUT,
HELPCTX(ssh_auth_changeuser),
dlg_stdcheckbox_handler,
I(offsetof(Config,change_username)));
FILTER_KEY_FILES, FALSE, "Select private key file",
HELPCTX(ssh_auth_privkey),
dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
+
+#ifndef NO_GSSAPI
+ /*
+ * Connection/SSH/Auth/GSSAPI, which sadly won't fit on
+ * the main Auth panel.
+ */
+ ctrl_settitle(b, "Connection/SSH/Auth/GSSAPI",
+ "Options controlling GSSAPI authentication");
+ s = ctrl_getset(b, "Connection/SSH/Auth/GSSAPI", "gssapi", NULL);
+
+ ctrl_checkbox(s, "Attempt GSSAPI authentication (SSH-2 only)",
+ 't', HELPCTX(ssh_gssapi),
+ dlg_stdcheckbox_handler,
+ I(offsetof(Config,try_gssapi_auth)));
+
+ ctrl_checkbox(s, "Allow GSSAPI credential delegation", 'l',
+ HELPCTX(ssh_gssapi_delegation),
+ dlg_stdcheckbox_handler,
+ I(offsetof(Config,gssapifwd)));
+
+ /*
+ * GSSAPI library selection.
+ */
+ if (ngsslibs > 1) {
+ c = ctrl_draglist(s, "Preference order for GSSAPI libraries:",
+ 'p', HELPCTX(ssh_gssapi_libraries),
+ gsslist_handler, P(NULL));
+ c->listbox.height = ngsslibs;
+
+ /*
+ * I currently assume that if more than one GSS
+ * library option is available, then one of them is
+ * 'user-supplied' and so we should present the
+ * following file selector. This is at least half-
+ * reasonable, because if we're using statically
+ * linked GSSAPI then there will only be one option
+ * and no way to load from a user-supplied library,
+ * whereas if we're using dynamic libraries then
+ * there will almost certainly be some default
+ * option in addition to a user-supplied path. If
+ * anyone ever ports PuTTY to a system on which
+ * dynamic-library GSSAPI is available but there is
+ * absolutely no consensus on where to keep the
+ * libraries, there'll need to be a flag alongside
+ * ngsslibs to control whether the file selector is
+ * displayed.
+ */
+
+ ctrl_filesel(s, "User-supplied GSSAPI library path:", 's',
+ FILTER_DYNLIB_FILES, FALSE, "Select library file",
+ HELPCTX(ssh_gssapi_libraries),
+ dlg_stdfilesel_handler,
+ I(offsetof(Config, ssh_gss_custom)));
+ }
+#endif
}
if (!midsession) {
ctrl_droplist(s, "Chokes on SSH-1 RSA authentication", 'r', 20,
HELPCTX(ssh_bugs_rsa1),
sshbug_handler, I(offsetof(Config,sshbug_rsa1)));
+ ctrl_droplist(s, "Chokes on SSH-2 ignore messages", '2', 20,
+ HELPCTX(ssh_bugs_ignore2),
+ sshbug_handler, I(offsetof(Config,sshbug_ignore2)));
ctrl_droplist(s, "Miscomputes SSH-2 HMAC keys", 'm', 20,
HELPCTX(ssh_bugs_hmac2),
sshbug_handler, I(offsetof(Config,sshbug_hmac2)));
ctrl_droplist(s, "Handles SSH-2 key re-exchange badly", 'k', 20,
HELPCTX(ssh_bugs_rekey2),
sshbug_handler, I(offsetof(Config,sshbug_rekey2)));
+ ctrl_droplist(s, "Ignores SSH-2 maximum packet size", 'x', 20,
+ HELPCTX(ssh_bugs_maxpkt2),
+ sshbug_handler, I(offsetof(Config,sshbug_maxpkt2)));
}
}
}