diff --git a/plink.c b/plink.c index 7ada2d48..f9271519 100644 --- a/plink.c +++ b/plink.c @@ -539,7 +539,7 @@ int main(int argc, char **argv) int nodelay = cfg.tcp_nodelay && (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); - error = back->init(NULL, &backhandle, cfg.host, cfg.port, + error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost, nodelay); if (error) { fprintf(stderr, "Unable to open connection:\n%s", error); diff --git a/psftp.c b/psftp.c index f528c218..f8d1f799 100644 --- a/psftp.c +++ b/psftp.c @@ -1828,7 +1828,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber) back = &ssh_backend; - err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0); + err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0); if (err != NULL) { fprintf(stderr, "ssh_init: %s\n", err); return 1; diff --git a/putty.h b/putty.h index 19000fc7..65a99ebe 100644 --- a/putty.h +++ b/putty.h @@ -184,8 +184,10 @@ enum { }; struct backend_tag { - char *(*init) (void *frontend_handle, void **backend_handle, + char *(*init) (void *frontend_handle, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay); + /* back->reconfig() passes in a replacement configuration. */ + void (*reconfig) (void *handle, Config *cfg); /* back->send() returns the current amount of buffered data. */ int (*send) (void *handle, char *buf, int len); /* back->sendbuffer() does the same thing but without attempting a send */ diff --git a/raw.c b/raw.c index 0e6c1410..09903338 100644 --- a/raw.c +++ b/raw.c @@ -68,6 +68,7 @@ static void raw_sent(Plug plug, int bufsize) * freed by the caller. */ static char *raw_init(void *frontend_handle, void **backend_handle, + Config *cfg, char *host, int port, char **realhost, int nodelay) { static const struct plug_function_table fn_table = { @@ -121,6 +122,13 @@ static char *raw_init(void *frontend_handle, void **backend_handle, return NULL; } +/* + * Stub routine (we don't have any need to reconfigure this backend). + */ +static void raw_reconfig(void *handle, Config *cfg) +{ +} + /* * Called to send data down the raw connection. */ @@ -205,6 +213,7 @@ static int raw_exitcode(void *handle) Backend raw_backend = { raw_init, + raw_reconfig, raw_send, raw_sendbuffer, raw_size, diff --git a/rlogin.c b/rlogin.c index 9c249f27..afc3d2c3 100644 --- a/rlogin.c +++ b/rlogin.c @@ -98,6 +98,7 @@ static void rlogin_sent(Plug plug, int bufsize) * freed by the caller. */ static char *rlogin_init(void *frontend_handle, void **backend_handle, + Config *cfg, char *host, int port, char **realhost, int nodelay) { static const struct plug_function_table fn_table = { @@ -113,8 +114,8 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle, rlogin->fn = &fn_table; rlogin->s = NULL; rlogin->frontend = frontend_handle; - rlogin->term_width = cfg.width; - rlogin->term_height = cfg.height; + rlogin->term_width = cfg->width; + rlogin->term_height = cfg->height; *backend_handle = rlogin; /* @@ -158,20 +159,30 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle, char z = 0; char *p; sk_write(rlogin->s, &z, 1); - sk_write(rlogin->s, cfg.localusername, strlen(cfg.localusername)); + sk_write(rlogin->s, cfg->localusername, + strlen(cfg->localusername)); sk_write(rlogin->s, &z, 1); - sk_write(rlogin->s, cfg.username, strlen(cfg.username)); + sk_write(rlogin->s, cfg->username, + strlen(cfg->username)); sk_write(rlogin->s, &z, 1); - sk_write(rlogin->s, cfg.termtype, strlen(cfg.termtype)); + sk_write(rlogin->s, cfg->termtype, + strlen(cfg->termtype)); sk_write(rlogin->s, "/", 1); - for (p = cfg.termspeed; isdigit(*p); p++) continue; - sk_write(rlogin->s, cfg.termspeed, p - cfg.termspeed); + for (p = cfg->termspeed; isdigit(*p); p++) continue; + sk_write(rlogin->s, cfg->termspeed, p - cfg->termspeed); rlogin->bufsize = sk_write(rlogin->s, &z, 1); } return NULL; } +/* + * Stub routine (we don't have any need to reconfigure this backend). + */ +static void rlogin_reconfig(void *handle, Config *cfg) +{ +} + /* * Called to send data down the rlogin connection. */ @@ -270,6 +281,7 @@ static int rlogin_exitcode(void *handle) Backend rlogin_backend = { rlogin_init, + rlogin_reconfig, rlogin_send, rlogin_sendbuffer, rlogin_size, diff --git a/scp.c b/scp.c index 389799d1..20f97dd7 100644 --- a/scp.c +++ b/scp.c @@ -574,7 +574,7 @@ static void do_cmd(char *host, char *user, char *cmd) back = &ssh_backend; - err = back->init(NULL, &backhandle, cfg.host, cfg.port, &realhost, 0); + err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0); if (err != NULL) bump("ssh_init: %s", err); logctx = log_init(NULL); diff --git a/ssh.c b/ssh.c index a2e74c0e..70f3a069 100644 --- a/ssh.c +++ b/ssh.c @@ -620,6 +620,14 @@ struct ssh_tag { void (*protocol) (Ssh ssh, unsigned char *in, int inlen, int ispkt); int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen); + + /* + * We maintain a full _copy_ of a Config structure here, not + * merely a pointer to it. That way, when we're passed a new + * one for reconfiguration, we can check the differences and + * potentially reconfigure port forwardings etc in mid-session. + */ + Config cfg; }; #define logevent(s) logevent(ssh->frontend, s) @@ -1711,8 +1719,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) ssh->remote_bugs = 0; - if (cfg.sshbug_ignore1 == BUG_ON || - (cfg.sshbug_ignore1 == BUG_AUTO && + if (ssh->cfg.sshbug_ignore1 == BUG_ON || + (ssh->cfg.sshbug_ignore1 == BUG_AUTO && (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") || !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") || !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) { @@ -1725,8 +1733,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version has SSH1 ignore bug"); } - if (cfg.sshbug_plainpw1 == BUG_ON || - (cfg.sshbug_plainpw1 == BUG_AUTO && + if (ssh->cfg.sshbug_plainpw1 == BUG_ON || + (ssh->cfg.sshbug_plainpw1 == BUG_AUTO && (!strcmp(imp, "Cisco-1.25")))) { /* * These versions need a plain password sent; they can't @@ -1737,8 +1745,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version needs a plain SSH1 password"); } - if (cfg.sshbug_rsa1 == BUG_ON || - (cfg.sshbug_rsa1 == BUG_AUTO && + if (ssh->cfg.sshbug_rsa1 == BUG_ON || + (ssh->cfg.sshbug_rsa1 == BUG_AUTO && (!strcmp(imp, "Cisco-1.25")))) { /* * These versions apparently have no clue whatever about @@ -1749,8 +1757,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version can't handle RSA authentication"); } - if (cfg.sshbug_hmac2 == BUG_ON || - (cfg.sshbug_hmac2 == BUG_AUTO && + if (ssh->cfg.sshbug_hmac2 == BUG_ON || + (ssh->cfg.sshbug_hmac2 == BUG_AUTO && (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) || wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) || wc_match("2.1 *", imp)))) { @@ -1761,8 +1769,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version has SSH2 HMAC bug"); } - if (cfg.sshbug_derivekey2 == BUG_ON || - (cfg.sshbug_derivekey2 == BUG_AUTO && + if (ssh->cfg.sshbug_derivekey2 == BUG_ON || + (ssh->cfg.sshbug_derivekey2 == BUG_AUTO && (wc_match("2.0.0*", imp) || wc_match("2.0.1[01]*", imp) ))) { /* * These versions have the key-derivation bug (failing to @@ -1773,8 +1781,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version has SSH2 key-derivation bug"); } - if (cfg.sshbug_rsapad2 == BUG_ON || - (cfg.sshbug_rsapad2 == BUG_AUTO && + if (ssh->cfg.sshbug_rsapad2 == BUG_ON || + (ssh->cfg.sshbug_rsapad2 == BUG_AUTO && (wc_match("OpenSSH_2.[5-9]*", imp) || wc_match("OpenSSH_3.[0-2]*", imp)))) { /* @@ -1784,7 +1792,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring) logevent("We believe remote version has SSH2 RSA padding bug"); } - if (cfg.sshbug_dhgex2 == BUG_ON) { + if (ssh->cfg.sshbug_dhgex2 == BUG_ON) { /* * User specified the SSH2 DH GEX bug. */ @@ -1871,16 +1879,16 @@ static int do_ssh_init(Ssh ssh, unsigned char c) /* Anything greater or equal to "1.99" means protocol 2 is supported. */ s->proto2 = ssh_versioncmp(s->version, "1.99") >= 0; - if (cfg.sshprot == 0 && !s->proto1) { + if (ssh->cfg.sshprot == 0 && !s->proto1) { bombout((ssh,"SSH protocol version 1 required by user but not provided by server")); crReturn(0); } - if (cfg.sshprot == 3 && !s->proto2) { + if (ssh->cfg.sshprot == 3 && !s->proto2) { bombout((ssh,"SSH protocol version 2 required by user but not provided by server")); crReturn(0); } - if (s->proto2 && (cfg.sshprot >= 2 || !s->proto1)) { + if (s->proto2 && (ssh->cfg.sshprot >= 2 || !s->proto1)) { /* * Use v2 protocol. */ @@ -2315,7 +2323,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) char *cipher_string = NULL; int i; for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) { - int next_cipher = cfg.ssh_cipherlist[i]; + int next_cipher = ssh->cfg.ssh_cipherlist[i]; if (next_cipher == CIPHER_WARN) { /* If/when we choose a cipher, warn about it */ warn = 1; @@ -2394,7 +2402,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) fflush(stdout); { - if ((flags & FLAG_INTERACTIVE) && !*cfg.username) { + if ((flags & FLAG_INTERACTIVE) && !*ssh->cfg.username) { if (ssh_get_line && !ssh_getline_pw_only) { if (!ssh_get_line("login as: ", s->username, sizeof(s->username), FALSE)) { @@ -2421,7 +2429,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) c_write_str(ssh, "\r\n"); } } else { - strncpy(s->username, cfg.username, sizeof(s->username)); + strncpy(s->username, ssh->cfg.username, sizeof(s->username)); s->username[sizeof(s->username)-1] = '\0'; } @@ -2447,9 +2455,9 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->tried_publickey = s->tried_agent = 0; } s->tis_auth_refused = s->ccard_auth_refused = 0; - /* Load the public half of cfg.keyfile so we notice if it's in Pageant */ - if (*cfg.keyfile) { - if (!rsakey_pubblob(cfg.keyfile, + /* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */ + if (*ssh->cfg.keyfile) { + if (!rsakey_pubblob(ssh->cfg.keyfile, &s->publickey_blob, &s->publickey_bloblen)) s->publickey_blob = NULL; } else @@ -2577,10 +2585,10 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (s->authed) break; } - if (*cfg.keyfile && !s->tried_publickey) + if (*ssh->cfg.keyfile && !s->tried_publickey) s->pwpkt_type = SSH1_CMSG_AUTH_RSA; - if (cfg.try_tis_auth && + if (ssh->cfg.try_tis_auth && (s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) && !s->tis_auth_refused) { s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE; @@ -2607,7 +2615,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->prompt[(sizeof s->prompt) - 1] = '\0'; } } - if (cfg.try_tis_auth && + if (ssh->cfg.try_tis_auth && (s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) && !s->ccard_auth_refused) { s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE; @@ -2642,8 +2650,8 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) char msgbuf[256]; if (flags & FLAG_VERBOSE) c_write_str(ssh, "Trying public key authentication.\r\n"); - logeventf(ssh, "Trying public key \"%s\"", cfg.keyfile); - type = key_type(cfg.keyfile); + logeventf(ssh, "Trying public key \"%s\"", ssh->cfg.keyfile); + type = key_type(ssh->cfg.keyfile); if (type != SSH_KEYTYPE_SSH1) { sprintf(msgbuf, "Key is of wrong type (%s)", key_type_to_str(type)); @@ -2653,7 +2661,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->tried_publickey = 1; continue; } - if (!rsakey_encrypted(cfg.keyfile, &comment)) { + if (!rsakey_encrypted(ssh->cfg.keyfile, &comment)) { if (flags & FLAG_VERBOSE) c_write_str(ssh, "No passphrase required.\r\n"); goto tryauth; @@ -2709,10 +2717,10 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->tried_publickey = 1; { - int ret = loadrsakey(cfg.keyfile, &s->key, s->password); + int ret = loadrsakey(ssh->cfg.keyfile, &s->key, s->password); if (ret == 0) { c_write_str(ssh, "Couldn't load private key from "); - c_write_str(ssh, cfg.keyfile); + c_write_str(ssh, ssh->cfg.keyfile); c_write_str(ssh, ".\r\n"); continue; /* go and try password */ } @@ -2996,7 +3004,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (ssh->state == SSH_STATE_CLOSED) crReturnV; - if (cfg.agentfwd && agent_exists()) { + if (ssh->cfg.agentfwd && agent_exists()) { logevent("Requesting agent forwarding"); send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END); do { @@ -3014,16 +3022,16 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } - if (cfg.x11_forward) { + if (ssh->cfg.x11_forward) { char proto[20], data[64]; logevent("Requesting X11 forwarding"); ssh->x11auth = x11_invent_auth(proto, sizeof(proto), - data, sizeof(data), cfg.x11_auth); - x11_get_real_auth(ssh->x11auth, cfg.x11_display); + data, sizeof(data), ssh->cfg.x11_auth); + x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display); if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) { send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING, PKT_STR, proto, PKT_STR, data, - PKT_INT, x11_get_screen_number(cfg.x11_display), + PKT_INT, x11_get_screen_number(ssh->cfg.x11_display), PKT_END); } else { send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING, @@ -3052,7 +3060,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->rportfwds = newtree234(ssh_rportcmp_ssh1); /* Add port forwardings. */ - ssh->portfwd_strptr = cfg.portfwd; + ssh->portfwd_strptr = ssh->cfg.portfwd; while (*ssh->portfwd_strptr) { type = *ssh->portfwd_strptr++; saddr[0] = '\0'; @@ -3169,9 +3177,9 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } } - if (!cfg.nopty) { + if (!ssh->cfg.nopty) { send_packet(ssh, SSH1_CMSG_REQUEST_PTY, - PKT_STR, cfg.termtype, + PKT_STR, ssh->cfg.termtype, PKT_INT, ssh->term_height, PKT_INT, ssh->term_width, PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END); @@ -3192,7 +3200,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->editing = ssh->echoing = 1; } - if (cfg.compression) { + if (ssh->cfg.compression) { send_packet(ssh, SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END); do { crReturnV; @@ -3220,10 +3228,10 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) * exists, we fall straight back to that. */ { - char *cmd = cfg.remote_cmd_ptr; + char *cmd = ssh->cfg.remote_cmd_ptr; - if (cfg.ssh_subsys && cfg.remote_cmd_ptr2) { - cmd = cfg.remote_cmd_ptr2; + if (ssh->cfg.ssh_subsys && ssh->cfg.remote_cmd_ptr2) { + cmd = ssh->cfg.remote_cmd_ptr2; ssh->fallback_cmd = TRUE; } if (*cmd) @@ -3276,7 +3284,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) c = smalloc(sizeof(struct ssh_channel)); c->ssh = ssh; - if (x11_init(&c->u.x11.s, cfg.x11_display, c, + if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c, ssh->x11auth, NULL, -1) != NULL) { logevent("opening X11 forward connection failed"); sfree(c); @@ -3669,12 +3677,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) */ s->n_preferred_ciphers = 0; for (i = 0; i < CIPHER_MAX; i++) { - switch (cfg.ssh_cipherlist[i]) { + switch (ssh->cfg.ssh_cipherlist[i]) { case CIPHER_BLOWFISH: s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish; break; case CIPHER_DES: - if (cfg.ssh2_des_cbc) { + if (ssh->cfg.ssh2_des_cbc) { s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des; } break; @@ -3698,7 +3706,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Set up preferred compression. */ - if (cfg.compression) + if (ssh->cfg.compression) s->preferred_comp = &ssh_zlib; else s->preferred_comp = &ssh_comp_none; @@ -4313,13 +4321,13 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Get a username. */ - if (s->got_username && !cfg.change_username) { + if (s->got_username && !ssh->cfg.change_username) { /* * We got a username last time round this loop, and * with change_username turned off we don't try to get * it again. */ - } else if ((flags & FLAG_INTERACTIVE) && !*cfg.username) { + } else if ((flags & FLAG_INTERACTIVE) && !*ssh->cfg.username) { if (ssh_get_line && !ssh_getline_pw_only) { if (!ssh_get_line("login as: ", s->username, sizeof(s->username), FALSE)) { @@ -4347,7 +4355,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->username[strcspn(s->username, "\n\r")] = '\0'; } else { char *stuff; - strncpy(s->username, cfg.username, sizeof(s->username)); + strncpy(s->username, ssh->cfg.username, sizeof(s->username)); s->username[sizeof(s->username)-1] = '\0'; if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) { stuff = dupprintf("Using username \"%s\".\r\n", s->username); @@ -4377,21 +4385,21 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->tried_agent = FALSE; s->tried_keyb_inter = FALSE; s->kbd_inter_running = FALSE; - /* Load the pub half of cfg.keyfile so we notice if it's in Pageant */ - if (*cfg.keyfile) { + /* Load the pub half of ssh->cfg.keyfile so we notice if it's in Pageant */ + if (*ssh->cfg.keyfile) { int keytype; - logeventf(ssh, "Reading private key file \"%.150s\"", cfg.keyfile); - keytype = key_type(cfg.keyfile); + logeventf(ssh, "Reading private key file \"%.150s\"", ssh->cfg.keyfile); + keytype = key_type(ssh->cfg.keyfile); if (keytype == SSH_KEYTYPE_SSH2) { s->publickey_blob = - ssh2_userkey_loadpub(cfg.keyfile, NULL, + ssh2_userkey_loadpub(ssh->cfg.keyfile, NULL, &s->publickey_bloblen); } else { char *msgbuf; logeventf(ssh, "Unable to use this key file (%s)", key_type_to_str(keytype)); msgbuf = dupprintf("Unable to use key file \"%.150s\"" - " (%s)\r\n", cfg.keyfile, + " (%s)\r\n", ssh->cfg.keyfile, key_type_to_str(keytype)); c_write_str(ssh, msgbuf); sfree(msgbuf); @@ -4507,7 +4515,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) in_commasep_string("publickey", methods, methlen); s->can_passwd = in_commasep_string("password", methods, methlen); - s->can_keyb_inter = cfg.try_ki_auth && + s->can_keyb_inter = ssh->cfg.try_ki_auth && in_commasep_string("keyboard-interactive", methods, methlen); } @@ -4682,7 +4690,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * willing to accept it. */ pub_blob = - (unsigned char *)ssh2_userkey_loadpub(cfg.keyfile, + (unsigned char *)ssh2_userkey_loadpub(ssh->cfg.keyfile, &algorithm, &pub_blob_len); if (pub_blob) { @@ -4710,7 +4718,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * Actually attempt a serious authentication using * the key. */ - if (ssh2_userkey_encrypted(cfg.keyfile, &comment)) { + if (ssh2_userkey_encrypted(ssh->cfg.keyfile, &comment)) { sprintf(s->pwprompt, "Passphrase for key \"%.100s\": ", comment); @@ -4862,7 +4870,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) */ struct ssh2_userkey *key; - key = ssh2_load_userkey(cfg.keyfile, s->password); + key = ssh2_load_userkey(ssh->cfg.keyfile, s->password); if (key == SSH2_WRONG_PASSPHRASE || key == NULL) { if (key == SSH2_WRONG_PASSPHRASE) { c_write_str(ssh, "Wrong passphrase\r\n"); @@ -5064,12 +5072,12 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Potentially enable X11 forwarding. */ - if (cfg.x11_forward) { + if (ssh->cfg.x11_forward) { char proto[20], data[64]; logevent("Requesting X11 forwarding"); ssh->x11auth = x11_invent_auth(proto, sizeof(proto), - data, sizeof(data), cfg.x11_auth); - x11_get_real_auth(ssh->x11auth, cfg.x11_display); + data, sizeof(data), ssh->cfg.x11_auth); + x11_get_real_auth(ssh->x11auth, ssh->cfg.x11_display); ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); ssh2_pkt_addstring(ssh, "x11-req"); @@ -5077,7 +5085,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_pkt_addbool(ssh, 0); /* many connections */ ssh2_pkt_addstring(ssh, proto); ssh2_pkt_addstring(ssh, data); - ssh2_pkt_adduint32(ssh, x11_get_screen_number(cfg.x11_display)); + ssh2_pkt_adduint32(ssh, x11_get_screen_number(ssh->cfg.x11_display)); ssh2_pkt_send(ssh); do { @@ -5116,7 +5124,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->rportfwds = newtree234(ssh_rportcmp_ssh2); /* Add port forwardings. */ - ssh->portfwd_strptr = cfg.portfwd; + ssh->portfwd_strptr = ssh->cfg.portfwd; while (*ssh->portfwd_strptr) { type = *ssh->portfwd_strptr++; saddr[0] = '\0'; @@ -5214,7 +5222,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh2_pkt_addbool(ssh, 1);/* want reply */ if (*saddr) ssh2_pkt_addstring(ssh, saddr); - if (cfg.rport_acceptall) + if (ssh->cfg.rport_acceptall) ssh2_pkt_addstring(ssh, "0.0.0.0"); else ssh2_pkt_addstring(ssh, "127.0.0.1"); @@ -5253,7 +5261,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Potentially enable agent forwarding. */ - if (cfg.agentfwd && agent_exists()) { + if (ssh->cfg.agentfwd && agent_exists()) { logevent("Requesting OpenSSH-style agent forwarding"); ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); @@ -5289,12 +5297,12 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Now allocate a pty for the session. */ - if (!cfg.nopty) { + if (!ssh->cfg.nopty) { ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); /* recipient channel */ ssh2_pkt_addstring(ssh, "pty-req"); ssh2_pkt_addbool(ssh, 1); /* want reply */ - ssh2_pkt_addstring(ssh, cfg.termtype); + ssh2_pkt_addstring(ssh, ssh->cfg.termtype); ssh2_pkt_adduint32(ssh, ssh->term_width); ssh2_pkt_adduint32(ssh, ssh->term_height); ssh2_pkt_adduint32(ssh, 0); /* pixel width */ @@ -5341,11 +5349,11 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) char *cmd; if (ssh->fallback_cmd) { - subsys = cfg.ssh_subsys2; - cmd = cfg.remote_cmd_ptr2; + subsys = ssh->cfg.ssh_subsys2; + cmd = ssh->cfg.remote_cmd_ptr2; } else { - subsys = cfg.ssh_subsys; - cmd = cfg.remote_cmd_ptr; + subsys = ssh->cfg.ssh_subsys; + cmd = ssh->cfg.remote_cmd_ptr; } ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); @@ -5386,7 +5394,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * not, and if the fallback command exists, try falling * back to it before complaining. */ - if (!ssh->fallback_cmd && cfg.remote_cmd_ptr2 != NULL) { + if (!ssh->fallback_cmd && ssh->cfg.remote_cmd_ptr2 != NULL) { logevent("Primary command failed; attempting fallback"); ssh->fallback_cmd = TRUE; continue; @@ -5737,7 +5745,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (!ssh->X11_fwd_enabled) error = "X11 forwarding is not enabled"; - else if (x11_init(&c->u.x11.s, cfg.x11_display, c, + else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c, ssh->x11auth, addrstr, port) != NULL) { error = "Unable to open an X11 connection"; } else { @@ -5867,12 +5875,14 @@ static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) * Returns an error message, or NULL on success. */ static char *ssh_init(void *frontend_handle, void **backend_handle, + Config *cfg, char *host, int port, char **realhost, int nodelay) { char *p; Ssh ssh; ssh = smalloc(sizeof(*ssh)); + ssh->cfg = *cfg; /* STRUCTURE COPY */ ssh->s = NULL; ssh->cipher = NULL; ssh->v1_cipher_ctx = NULL; @@ -5933,8 +5943,8 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, #endif ssh->frontend = frontend_handle; - ssh->term_width = cfg.width; - ssh->term_height = cfg.height; + ssh->term_width = ssh->cfg.width; + ssh->term_height = ssh->cfg.height; ssh->send_ok = 0; ssh->editing = 0; @@ -5952,6 +5962,21 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, return NULL; } +/* + * Reconfigure the SSH backend. + * + * Currently, this function does nothing very useful. In future, + * however, we could do some handy things with it. For example, we + * could make the port forwarding configurer active in the Change + * Settings box, and this routine could close down existing + * forwardings and open up new ones in response to changes. + */ +static void ssh_reconfig(void *handle, Config *cfg) +{ + Ssh ssh = (Ssh) handle; + ssh->cfg = *cfg; /* STRUCTURE COPY */ +} + /* * Called to send data down the Telnet connection. */ @@ -6018,7 +6043,7 @@ static void ssh_size(void *handle, int width, int height) ssh->size_needed = TRUE; /* buffer for later */ break; case SSH_STATE_SESSION: - if (!cfg.nopty) { + if (!ssh->cfg.nopty) { if (ssh->version == 1) { send_packet(ssh, SSH1_CMSG_WINDOW_SIZE, PKT_INT, ssh->term_height, @@ -6209,6 +6234,7 @@ extern int ssh_fallback_cmd(void *handle) Backend ssh_backend = { ssh_init, + ssh_reconfig, ssh_send, ssh_sendbuffer, ssh_size, diff --git a/telnet.c b/telnet.c index f4ea82ba..2d87b310 100644 --- a/telnet.c +++ b/telnet.c @@ -217,6 +217,7 @@ typedef struct telnet_tag { SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR } state; + Config cfg; } *Telnet; #define TELNET_MAX_BACKLOG 4096 @@ -386,13 +387,13 @@ static void process_subneg(Telnet telnet) b[1] = SB; b[2] = TELOPT_TSPEED; b[3] = TELQUAL_IS; - strcpy((char *)(b + 4), cfg.termspeed); - n = 4 + strlen(cfg.termspeed); + strcpy((char *)(b + 4), telnet->cfg.termspeed); + n = 4 + strlen(telnet->cfg.termspeed); b[n] = IAC; b[n + 1] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n + 2); logevent(telnet->frontend, "server:\tSB TSPEED SEND"); - logbuf = dupprintf("client:\tSB TSPEED IS %s", cfg.termspeed); + logbuf = dupprintf("client:\tSB TSPEED IS %s", telnet->cfg.termspeed); logevent(telnet->frontend, logbuf); sfree(logbuf); } else @@ -405,11 +406,11 @@ static void process_subneg(Telnet telnet) b[1] = SB; b[2] = TELOPT_TTYPE; b[3] = TELQUAL_IS; - for (n = 0; cfg.termtype[n]; n++) - b[n + 4] = (cfg.termtype[n] >= 'a' - && cfg.termtype[n] <= - 'z' ? cfg.termtype[n] + 'A' - - 'a' : cfg.termtype[n]); + for (n = 0; telnet->cfg.termtype[n]; n++) + b[n + 4] = (telnet->cfg.termtype[n] >= 'a' + && telnet->cfg.termtype[n] <= + 'z' ? telnet->cfg.termtype[n] + 'A' - + 'a' : telnet->cfg.termtype[n]); b[n + 4] = IAC; b[n + 5] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n + 6); @@ -432,7 +433,7 @@ static void process_subneg(Telnet telnet) logevent(telnet->frontend, logbuf); sfree(logbuf); if (telnet->sb_opt == TELOPT_OLD_ENVIRON) { - if (cfg.rfc_environ) { + if (telnet->cfg.rfc_environ) { value = RFC_VALUE; var = RFC_VAR; } else { @@ -465,7 +466,7 @@ static void process_subneg(Telnet telnet) b[2] = telnet->sb_opt; b[3] = TELQUAL_IS; n = 4; - e = cfg.environmt; + e = telnet->cfg.environmt; while (*e) { b[n++] = var; while (*e && *e != '\t') @@ -477,14 +478,14 @@ static void process_subneg(Telnet telnet) b[n++] = *e++; e++; } - if (*cfg.username) { + if (*telnet->cfg.username) { b[n++] = var; b[n++] = 'U'; b[n++] = 'S'; b[n++] = 'E'; b[n++] = 'R'; b[n++] = value; - e = cfg.username; + e = telnet->cfg.username; while (*e) b[n++] = *e++; } @@ -652,6 +653,7 @@ static void telnet_sent(Plug plug, int bufsize) * freed by the caller. */ static char *telnet_init(void *frontend_handle, void **backend_handle, + Config *cfg, char *host, int port, char **realhost, int nodelay) { static const struct plug_function_table fn_table = { @@ -665,6 +667,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle, telnet = smalloc(sizeof(*telnet)); telnet->fn = &fn_table; + telnet->cfg = *cfg; /* STRUCTURE COPY */ telnet->s = NULL; telnet->echoing = TRUE; telnet->editing = TRUE; @@ -672,8 +675,8 @@ static char *telnet_init(void *frontend_handle, void **backend_handle, telnet->sb_buf = NULL; telnet->sb_size = 0; telnet->frontend = frontend_handle; - telnet->term_width = cfg.width; - telnet->term_height = cfg.height; + telnet->term_width = telnet->cfg.width; + telnet->term_height = telnet->cfg.height; telnet->state = TOP_LEVEL; *backend_handle = telnet; @@ -713,7 +716,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle, /* * Initialise option states. */ - if (cfg.passive_telnet) { + if (telnet->cfg.passive_telnet) { const struct Opt *const *o; for (o = opts; *o; o++) @@ -737,6 +740,17 @@ static char *telnet_init(void *frontend_handle, void **backend_handle, return NULL; } +/* + * Reconfigure the Telnet backend. There's no immediate action + * necessary, in this backend: we just save the fresh config for + * any subsequent negotiations. + */ +static void telnet_reconfig(void *handle, Config *cfg) +{ + Telnet telnet = (Telnet) handle; + telnet->cfg = *cfg; /* STRUCTURE COPY */ +} + /* * Called to send data down the Telnet connection. */ @@ -960,6 +974,7 @@ static int telnet_exitcode(void *handle) Backend telnet_backend = { telnet_init, + telnet_reconfig, telnet_send, telnet_sendbuffer, telnet_size, diff --git a/unix/pterm.c b/unix/pterm.c index dbcb5455..f0f71e83 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -2411,7 +2411,8 @@ int main(int argc, char **argv) term_provide_logctx(inst->term, inst->logctx); inst->back = &pty_backend; - inst->back->init((void *)inst->term, &inst->backhandle, NULL, 0, NULL, 0); + inst->back->init((void *)inst->term, &inst->backhandle, &cfg, + NULL, 0, NULL, 0); inst->back->provide_logctx(inst->backhandle, inst->logctx); term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle); diff --git a/unix/pty.c b/unix/pty.c index 0084e64a..1c213e86 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -389,7 +389,7 @@ void pty_pre_init(void) * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ -static char *pty_init(void *frontend, void **backend_handle, +static char *pty_init(void *frontend, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay) { int slavefd; @@ -398,8 +398,8 @@ static char *pty_init(void *frontend, void **backend_handle, pty_frontend = frontend; *backend_handle = NULL; /* we can't sensibly use this, sadly */ - pty_term_width = cfg.width; - pty_term_height = cfg.height; + pty_term_width = cfg->width; + pty_term_height = cfg->height; if (pty_master_fd < 0) pty_open_master(); @@ -411,7 +411,7 @@ static char *pty_init(void *frontend, void **backend_handle, { struct termios attrs; tcgetattr(pty_master_fd, &attrs); - attrs.c_cc[VERASE] = cfg.bksp_is_delete ? '\177' : '\010'; + attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010'; tcsetattr(pty_master_fd, TCSANOW, &attrs); } @@ -419,7 +419,7 @@ static char *pty_init(void *frontend, void **backend_handle, * Stamp utmp (that is, tell the utmp helper process to do so), * or not. */ - if (!cfg.stamp_utmp) + if (!cfg->stamp_utmp) close(pty_utmp_helper_pipe); /* just let the child process die */ else { char *location = get_x_display(pty_frontend); @@ -472,8 +472,8 @@ static char *pty_init(void *frontend, void **backend_handle, for (i = 3; i < 1024; i++) close(i); { - char term_env_var[10 + sizeof(cfg.termtype)]; - sprintf(term_env_var, "TERM=%s", cfg.termtype); + char term_env_var[10 + sizeof(cfg->termtype)]; + sprintf(term_env_var, "TERM=%s", cfg->termtype); putenv(term_env_var); } /* @@ -488,7 +488,7 @@ static char *pty_init(void *frontend, void **backend_handle, else { char *shell = getenv("SHELL"); char *shellname; - if (cfg.login_shell) { + if (cfg->login_shell) { char *p = strrchr(shell, '/'); shellname = smalloc(2+strlen(shell)); p = p ? p+1 : shell; @@ -511,6 +511,13 @@ static char *pty_init(void *frontend, void **backend_handle, return NULL; } +/* + * Stub routine (we don't have any need to reconfigure this backend). + */ +static void pty_reconfig(void *handle, Config *cfg) +{ +} + /* * Called to send data down the pty. */ @@ -617,6 +624,7 @@ static int pty_exitcode(void *handle) Backend pty_backend = { pty_init, + pty_reconfig, pty_send, pty_sendbuffer, pty_size, diff --git a/unix/uxplink.c b/unix/uxplink.c index 5ca5bb2c..295e80b3 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -551,7 +551,7 @@ int main(int argc, char **argv) /* nodelay is only useful if stdin is a terminal device */ int nodelay = cfg.tcp_nodelay && isatty(0); - error = back->init(NULL, &backhandle, cfg.host, cfg.port, + error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost, nodelay); if (error) { fprintf(stderr, "Unable to open connection:\n%s\n", error); diff --git a/window.c b/window.c index 272a5274..ebf554ea 100644 --- a/window.c +++ b/window.c @@ -615,7 +615,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) char msg[1024], *title; char *realhost; - error = back->init((void *)term, &backhandle, + error = back->init((void *)term, &backhandle, &cfg, cfg.host, cfg.port, &realhost, cfg.tcp_nodelay); back->provide_logctx(backhandle, logctx); if (error) { @@ -1782,6 +1782,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, /* Pass new config data to the terminal */ term_reconfig(term, &cfg); + /* Pass new config data to the back end */ + back->reconfig(back, &cfg); + /* Screen size changed ? */ if (cfg.height != prev_cfg.height || cfg.width != prev_cfg.width ||