X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/7555d6a50b05d96de39b5e95cf11a8f05f0c4fd9..d87d258a8f5d8fc9c43e73cc59ff4258b3755485:/rlogin.c diff --git a/rlogin.c b/rlogin.c index a6dad0e4..6841fc6e 100644 --- a/rlogin.c +++ b/rlogin.c @@ -1,3 +1,7 @@ +/* + * Rlogin backend. + */ + #include #include #include @@ -20,8 +24,14 @@ typedef struct rlogin_tag { Socket s; int bufsize; int firstbyte; + int cansize; int term_width, term_height; void *frontend; + + Config cfg; + + /* In case we need to read a username from the terminal before starting */ + prompts_t *prompt; } *Rlogin; static void rlogin_size(void *handle, int width, int height); @@ -73,8 +83,10 @@ static int rlogin_receive(Plug plug, int urgent, char *data, int len) c = *data++; len--; - if (c == '\x80') + if (c == '\x80') { + rlogin->cansize = 1; rlogin_size(rlogin, rlogin->term_width, rlogin->term_height); + } /* * We should flush everything (aka Telnet SYNCH) if we see * 0x02, and we should turn off and on _local_ flow control @@ -106,6 +118,27 @@ static void rlogin_sent(Plug plug, int bufsize) rlogin->bufsize = bufsize; } +static void rlogin_startup(Rlogin rlogin, const char *ruser) +{ + char z = 0; + char *p; + sk_write(rlogin->s, &z, 1); + sk_write(rlogin->s, rlogin->cfg.localusername, + strlen(rlogin->cfg.localusername)); + sk_write(rlogin->s, &z, 1); + sk_write(rlogin->s, ruser, + strlen(ruser)); + sk_write(rlogin->s, &z, 1); + sk_write(rlogin->s, rlogin->cfg.termtype, + strlen(rlogin->cfg.termtype)); + sk_write(rlogin->s, "/", 1); + for (p = rlogin->cfg.termspeed; isdigit((unsigned char)*p); p++) continue; + sk_write(rlogin->s, rlogin->cfg.termspeed, p - rlogin->cfg.termspeed); + rlogin->bufsize = sk_write(rlogin->s, &z, 1); + + rlogin->prompt = NULL; +} + /* * Called to set up the rlogin connection. * @@ -128,6 +161,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle, SockAddr addr; const char *err; Rlogin rlogin; + char ruser[sizeof(cfg->username)]; rlogin = snew(struct rlogin_tag); rlogin->fn = &fn_table; @@ -136,6 +170,9 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle, rlogin->term_width = cfg->width; rlogin->term_height = cfg->height; rlogin->firstbyte = 1; + rlogin->cansize = 0; + rlogin->prompt = NULL; + rlogin->cfg = *cfg; /* STRUCTURE COPY */ *backend_handle = rlogin; /* @@ -167,26 +204,42 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle, if ((err = sk_socket_error(rlogin->s)) != NULL) return err; + if (*cfg->loghost) { + char *colon; + + sfree(*realhost); + *realhost = dupstr(cfg->loghost); + colon = strrchr(*realhost, ':'); + if (colon) { + /* + * FIXME: if we ever update this aspect of ssh.c for + * IPv6 literal management, this should change in line + * with it. + */ + *colon++ = '\0'; + } + } + /* - * Send local username, remote username, terminal/speed + * Send local username, remote username, terminal type and + * terminal speed - unless we don't have the remote username yet, + * in which case we prompt for it and may end up deferring doing + * anything else until the local prompt mechanism returns. */ - - { - char z = 0; - char *p; - sk_write(rlogin->s, &z, 1); - 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, &z, 1); - sk_write(rlogin->s, cfg->termtype, - strlen(cfg->termtype)); - sk_write(rlogin->s, "/", 1); - for (p = cfg->termspeed; isdigit((unsigned char)*p); p++) continue; - sk_write(rlogin->s, cfg->termspeed, p - cfg->termspeed); - rlogin->bufsize = sk_write(rlogin->s, &z, 1); + if (get_remote_username(cfg, ruser, sizeof(ruser))) { + rlogin_startup(rlogin, ruser); + } else { + int ret; + + rlogin->prompt = new_prompts(rlogin->frontend); + rlogin->prompt->to_server = TRUE; + rlogin->prompt->name = dupstr("Rlogin login name"); + add_prompt(rlogin->prompt, dupstr("rlogin username: "), TRUE, + sizeof(cfg->username)); + ret = get_userpass_input(rlogin->prompt, NULL, 0); + if (ret >= 0) { + rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result); + } } return NULL; @@ -196,6 +249,8 @@ static void rlogin_free(void *handle) { Rlogin rlogin = (Rlogin) handle; + if (rlogin->prompt) + free_prompts(rlogin->prompt); if (rlogin->s) sk_close(rlogin->s); sfree(rlogin); @@ -218,7 +273,21 @@ static int rlogin_send(void *handle, char *buf, int len) if (rlogin->s == NULL) return 0; - rlogin->bufsize = sk_write(rlogin->s, buf, len); + if (rlogin->prompt) { + /* + * We're still prompting for a username, and aren't talking + * directly to the network connection yet. + */ + int ret = get_userpass_input(rlogin->prompt, + (unsigned char *)buf, len); + if (ret >= 0) { + rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result); + /* that nulls out rlogin->prompt, so then we'll start sending + * data down the wire in the obvious way */ + } + } else { + rlogin->bufsize = sk_write(rlogin->s, buf, len); + } return rlogin->bufsize; } @@ -243,7 +312,7 @@ static void rlogin_size(void *handle, int width, int height) rlogin->term_width = width; rlogin->term_height = height; - if (rlogin->s == NULL) + if (rlogin->s == NULL || !rlogin->cansize) return; b[6] = rlogin->term_width >> 8; @@ -272,10 +341,10 @@ static const struct telnet_special *rlogin_get_specials(void *handle) return NULL; } -static Socket rlogin_socket(void *handle) +static int rlogin_connected(void *handle) { Rlogin rlogin = (Rlogin) handle; - return rlogin->s; + return rlogin->s != NULL; } static int rlogin_sendok(void *handle) @@ -333,7 +402,7 @@ Backend rlogin_backend = { rlogin_size, rlogin_special, rlogin_get_specials, - rlogin_socket, + rlogin_connected, rlogin_exitcode, rlogin_sendok, rlogin_ldisc, @@ -341,5 +410,7 @@ Backend rlogin_backend = { rlogin_provide_logctx, rlogin_unthrottle, rlogin_cfg_info, - 1 + "rlogin", + PROT_RLOGIN, + 513 };