int proxy_http_negotiate (ProxySocket *p, int change) { if (p->state == PROXY_STATE_NEW) { /* we are just beginning the proxy negotiate process, * so we'll send off the initial bits of the request. * for this proxy method, it's just a simple HTTP * request */ char *buf, dest[512]; char *username, *password; sk_getaddr(p->remote_addr, dest, lenof(dest)); buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n", dest, p->remote_port, dest, p->remote_port); sk_write(p->sub_socket, buf, strlen(buf)); sfree(buf); username = conf_get_str(p->conf, CONF_proxy_username); password = conf_get_str(p->conf, CONF_proxy_password); if (username[0] || password[0]) { char *buf, *buf2; int i, j, len; buf = dupprintf("%s:%s", username, password); len = strlen(buf); buf2 = snewn(len * 4 / 3 + 100, char); sprintf(buf2, "Proxy-Authorization: Basic "); for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4) base64_encode_atom((unsigned char *)(buf+i), (len-i > 3 ? 3 : len-i), buf2+j); strcpy(buf2+j, "\r\n"); sk_write(p->sub_socket, buf2, strlen(buf2)); sfree(buf); sfree(buf2); }
static int adb_receive(Plug plug, int urgent, char *data, int len) { Adb adb = (Adb) plug; if (adb->state == STATE_SENT_HELLO) { if (data[0]=='O') { // OKAY sk_write(adb->s,"0006shell:",10); adb->state = STATE_ASKED_FOR_SHELL; // wait for shell start response } else { if (data[0]=='F') { handle_fail(adb, data, len); } else { connection_fatal(adb->frontend, "Bad response after initial send"); } return 0; } } else if (adb->state == STATE_ASKED_FOR_SHELL) { if (data[0]=='O') { //OKAY adb->state = STATE_CONNECTED; // shell started, switch to terminal mode } else { if (data[0]=='F') { handle_fail(adb, data, len); } else { connection_fatal(adb->frontend, "Bad response waiting for shell start"); } return 0; } } else if (adb->state == STATE_WAITING_FOR_ERROR_MESSAGE) { do_fatal(adb, data, len); } else { c_write(adb, data, len); } return 1; }
/* * Called to send data down the rlogin connection. */ static int rlogin_send(void *handle, char *buf, int len) { Rlogin rlogin = (Rlogin) handle; if (rlogin->s == NULL) return 0; 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; }
int main(int argc, char *argv[]) { if (argc < 2) { usage(); } else { /* Version command */ if (argv[1][0] == 'v') { printf("%s\n", programVersion); return 1; } if (argc > 2) { /* Cmd Read / Write / version */ switch (argv[2][0]) { case 'r': case 'R': sk_read(argc, argv); break; case 'w': case 'W': sk_write(argc, argv); break; } } } return 1; }
int proxy_socks5_selectchap(Proxy_Socket p) { if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) { char chapbuf[514]; int ulen; chapbuf[0] = '\x01'; /* Version */ chapbuf[1] = '\x02'; /* Number of attributes sent */ chapbuf[2] = '\x11'; /* First attribute - algorithms list */ chapbuf[3] = '\x01'; /* Only one CHAP algorithm */ chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */ chapbuf[5] = '\x02'; /* Second attribute - username */ ulen = strlen(p->cfg.proxy_username); if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1; chapbuf[6] = ulen; memcpy(chapbuf+7, p->cfg.proxy_username, ulen); sk_write(p->sub_socket, chapbuf, ulen + 7); p->chap_num_attributes = 0; p->chap_num_attributes_processed = 0; p->chap_current_attribute = -1; p->chap_current_datalen = 0; p->state = 8; } else plug_closing(p->plug, "Proxy error: Server chose " "CHAP authentication but we didn't offer it!", PROXY_ERROR_GENERAL, 0); return 1; }
static void process_subneg(Telnet telnet) { unsigned char *b, *p, *q; int var, value, n, bsize; char *e, *eval, *ekey, *user; switch (telnet->sb_opt) { case TELOPT_TSPEED: if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { char *logbuf; char *termspeed = conf_get_str(telnet->conf, CONF_termspeed); b = snewn(20 + strlen(termspeed), unsigned char); b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED; b[3] = TELQUAL_IS; strcpy((char *)(b + 4), termspeed); n = 4 + strlen(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", termspeed); logevent(telnet->frontend, logbuf); sfree(logbuf); sfree(b); } else
/* * Called to send data down the raw connection. */ static int raw_send(char *buf, int len) { if (s == NULL) return 0; raw_bufsize = sk_write(s, buf, len); return raw_bufsize; }
static int sk_proxy_write(Socket s, const char *data, int len) { Proxy_Socket ps = (Proxy_Socket) s; if (ps->state != PROXY_STATE_ACTIVE) { bufchain_add(&ps->pending_output_data, data, len); return bufchain_size(&ps->pending_output_data); } return sk_write(ps->sub_socket, data, len); }
static int sk_proxy_write (Socket s, const void *data, int len) { ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt); if (ps->state != PROXY_STATE_ACTIVE) { bufchain_add(&ps->pending_output_data, data, len); return bufchain_size(&ps->pending_output_data); } return sk_write(ps->sub_socket, data, len); }
static void send_opt(Telnet telnet, int cmd, int option) { unsigned char b[3]; b[0] = IAC; b[1] = cmd; b[2] = option; telnet->bufsize = sk_write(telnet->s, (char *)b, 3); log_option(telnet, "client", cmd, option); }
static size_t sk_proxy_write (Socket *s, const void *data, size_t len) { ProxySocket *ps = container_of(s, ProxySocket, sock); if (ps->state != PROXY_STATE_ACTIVE) { bufchain_add(&ps->pending_output_data, data, len); return bufchain_size(&ps->pending_output_data); } return sk_write(ps->sub_socket, data, len); }
/* * Called to send data down the adb connection. */ static int adb_send(void *handle, char *buf, int len) { Adb adb = (Adb) handle; if (adb->s == NULL) return 0; adb->bufsize = sk_write(adb->s, buf, len); return adb->bufsize; }
/* * Called to send data down the rlogin connection. */ static int rlogin_send(void *handle, char *buf, int len) { Rlogin rlogin = (Rlogin) handle; if (rlogin->s == NULL) return 0; rlogin->bufsize = sk_write(rlogin->s, buf, len); return rlogin->bufsize; }
/* * Call this when proxy negotiation is complete, so that this * socket can begin working normally. */ void proxy_activate(Proxy_Socket p) { void *data; int len; long output_before, output_after; p->state = PROXY_STATE_ACTIVE; /* we want to ignore new receive events until we have sent * all of our buffered receive data. */ sk_set_frozen(p->sub_socket, 1); /* how many bytes of output have we buffered? */ output_before = bufchain_size(&p->pending_oob_output_data) + bufchain_size(&p->pending_output_data); /* and keep track of how many bytes do not get sent. */ output_after = 0; /* send buffered OOB writes */ while (bufchain_size(&p->pending_oob_output_data) > 0) { bufchain_prefix(&p->pending_oob_output_data, &data, &len); output_after += sk_write_oob(p->sub_socket, data, len); bufchain_consume(&p->pending_oob_output_data, len); } /* send buffered normal writes */ while (bufchain_size(&p->pending_output_data) > 0) { bufchain_prefix(&p->pending_output_data, &data, &len); output_after += sk_write(p->sub_socket, data, len); bufchain_consume(&p->pending_output_data, len); } /* if we managed to send any data, let the higher levels know. */ if (output_after < output_before) plug_sent(p->plug, output_after); /* if we were asked to flush the output during * the proxy negotiation process, do so now. */ if (p->pending_flush) sk_flush(p->sub_socket); /* if we have a pending EOF to send, send it */ if (p->pending_eof) sk_write_eof(p->sub_socket); /* if the backend wanted the socket unfrozen, try to unfreeze. * our set_frozen handler will flush buffered receive data before * unfreezing the actual underlying socket. */ if (!p->freeze) sk_set_frozen((Socket)p, 0); }
/* * Called to send data down the raw connection. */ static int raw_send(void *handle, char *buf, int len) { Raw raw = (Raw) handle; if (raw->s == NULL) return 0; raw->bufsize = sk_write(raw->s, buf, len); return raw->bufsize; }
void pfd_confirm(Socket s) { struct PFwdPrivate *pr; if (s == NULL) return; pr = (struct PFwdPrivate *) sk_get_private_ptr(s); pr->ready = 1; sk_set_frozen(s, 0); sk_write(s, NULL, 0); }
/* * Called to set the size of the window */ static void rlogin_size(void) { char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 }; if (s == NULL) return; b[6] = cols >> 8; b[7] = cols & 0xFF; b[4] = rows >> 8; b[5] = rows & 0xFF; rlogin_bufsize = sk_write(s, b, 12); return; }
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; }
static void rlogin_startup(Rlogin rlogin, const char *ruser) { char z = 0; char *p; sk_write(rlogin->s, &z, 1); p = conf_get_str(rlogin->conf, CONF_localusername); sk_write(rlogin->s, p, strlen(p)); sk_write(rlogin->s, &z, 1); sk_write(rlogin->s, ruser, strlen(ruser)); sk_write(rlogin->s, &z, 1); p = conf_get_str(rlogin->conf, CONF_termtype); sk_write(rlogin->s, p, strlen(p)); sk_write(rlogin->s, "/", 1); p = conf_get_str(rlogin->conf, CONF_termspeed); sk_write(rlogin->s, p, strspn(p, "0123456789")); rlogin->bufsize = sk_write(rlogin->s, &z, 1); rlogin->prompt = NULL; }
/* * Called to set the size of the window */ static void rlogin_size(void *handle, int width, int height) { Rlogin rlogin = (Rlogin) handle; char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 }; rlogin->term_width = width; rlogin->term_height = height; if (rlogin->s == NULL || !rlogin->cansize) return; b[6] = rlogin->term_width >> 8; b[7] = rlogin->term_width & 0xFF; b[4] = rlogin->term_height >> 8; b[5] = rlogin->term_height & 0xFF; rlogin->bufsize = sk_write(rlogin->s, b, 12); return; }
static int adb_receive(Plug plug, int urgent, char *data, int len) { Adb adb = (Adb) plug; if (adb->state==1) { if (data[0]=='O') { // OKAY sk_write(adb->s,"0006shell:",10); adb->state=2; // wait for shell start response } else { if (data[0]=='F') { char* d = (char*)smalloc(len+1); memcpy(d,data,len); d[len]='\0'; connection_fatal(adb->frontend, "%s", d+8); sfree(d); } else { connection_fatal(adb->frontend, "Bad response"); } return 0; } } else if (adb->state==2) { if (data[0]=='O') { //OKAY adb->state=3; // shell started, switch to terminal mode } else { if (data[0]=='F') { char* d = (char*)smalloc(len+1); memcpy(d,data,len); d[len]='\0'; connection_fatal(adb->frontend, "%s", d+8); sfree(d); } else { connection_fatal(adb->frontend, "Bad response"); } return 0; } } else { c_write((Raw)adb, data, len); } return 1; }
static int cygterm_send(void *handle, char *buf, int len) { Local local = handle; cygterm_debug("frontend -> pty %u", len); // dmemdump(buf, len); #if 0 /* HACK */ { int i; for (i = 0; i < len - 1; i++) if (buf[i] == 033 && !(buf[i+1]&0x80)) { memmove(buf + i, buf + i + 1, --len - i); buf[i] |= 0x80; } } #endif if (local->s != 0) local->bufsize = sk_write(local->s, buf, len); cygterm_debug("OK"); return local->bufsize; }
static void process_subneg(Telnet telnet) { unsigned char b[2048], *p, *q; int var, value, n; char *e; switch (telnet->sb_opt) { case TELOPT_TSPEED: if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { char *logbuf; b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED; b[3] = TELQUAL_IS; 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", telnet->cfg.termspeed); logevent(telnet->frontend, logbuf); sfree(logbuf); } else logevent(telnet->frontend, "server:\tSB TSPEED <something weird>"); break; case TELOPT_TTYPE: if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { char *logbuf; b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE; b[3] = TELQUAL_IS; 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); b[n + 4] = 0; logevent(telnet->frontend, "server:\tSB TTYPE SEND"); logbuf = dupprintf("client:\tSB TTYPE IS %s", b + 4); logevent(telnet->frontend, logbuf); sfree(logbuf); } else logevent(telnet->frontend, "server:\tSB TTYPE <something weird>\r\n"); break; case TELOPT_OLD_ENVIRON: case TELOPT_NEW_ENVIRON: p = telnet->sb_buf; q = p + telnet->sb_len; if (p < q && *p == TELQUAL_SEND) { char *logbuf; p++; logbuf = dupprintf("server:\tSB %s SEND", telopt(telnet->sb_opt)); logevent(telnet->frontend, logbuf); sfree(logbuf); if (telnet->sb_opt == TELOPT_OLD_ENVIRON) { if (telnet->cfg.rfc_environ) { value = RFC_VALUE; var = RFC_VAR; } else { value = BSD_VALUE; var = BSD_VAR; } /* * Try to guess the sense of VAR and VALUE. */ while (p < q) { if (*p == RFC_VAR) { value = RFC_VALUE; var = RFC_VAR; } else if (*p == BSD_VAR) { value = BSD_VALUE; var = BSD_VAR; } p++; } } else { /* * With NEW_ENVIRON, the sense of VAR and VALUE * isn't in doubt. */ value = RFC_VALUE; var = RFC_VAR; } b[0] = IAC; b[1] = SB; b[2] = telnet->sb_opt; b[3] = TELQUAL_IS; n = 4; e = telnet->cfg.environmt; while (*e) { b[n++] = var; while (*e && *e != '\t') b[n++] = *e++; if (*e == '\t') e++; b[n++] = value; while (*e) b[n++] = *e++; e++; } if (*telnet->cfg.username) { b[n++] = var; b[n++] = 'U'; b[n++] = 'S'; b[n++] = 'E'; b[n++] = 'R'; b[n++] = value; e = telnet->cfg.username; while (*e) b[n++] = *e++; } b[n++] = IAC; b[n++] = SE; telnet->bufsize = sk_write(telnet->s, (char *)b, n); logbuf = dupprintf("client:\tSB %s IS %s%s%s%s", telopt(telnet->sb_opt), *telnet->cfg.username ? "USER="******"", telnet->cfg.username, *telnet->cfg.username ? " " : "", n == 6 ? "<nothing>" : (*telnet->cfg.environmt ? "<stuff>" : "")); logevent(telnet->frontend, logbuf); sfree(logbuf); } break; } }
int proxy_socks5_handlechap(Proxy_Socket p) { /* CHAP authentication reply format: * version number (1 bytes) = 1 * number of commands (1 byte) * * For each command: * command identifier (1 byte) * data length (1 byte) */ unsigned char data[260]; unsigned char outbuf[20]; while (p->chap_num_attributes == 0 || p->chap_num_attributes_processed < p->chap_num_attributes) { if (p->chap_num_attributes == 0 || p->chap_current_attribute == -1) { /* CHAP normally reads in two bytes, either at the * beginning or for each attribute/value pair. But if * we're waiting for the value's data, we might not want * to read 2 bytes. */ if (bufchain_size(&p->pending_input_data) < 2) return 1; /* not got anything yet */ /* get the response */ bufchain_fetch(&p->pending_input_data, data, 2); bufchain_consume(&p->pending_input_data, 2); } if (p->chap_num_attributes == 0) { /* If there are no attributes, this is our first msg * with the server, where we negotiate version and * number of attributes */ if (data[0] != 0x01) { plug_closing(p->plug, "Proxy error: SOCKS proxy wants" " a different CHAP version", PROXY_ERROR_GENERAL, 0); return 1; } if (data[1] == 0x00) { plug_closing(p->plug, "Proxy error: SOCKS proxy won't" " negotiate CHAP with us", PROXY_ERROR_GENERAL, 0); return 1; } p->chap_num_attributes = data[1]; } else { if (p->chap_current_attribute == -1) { /* We have to read in each attribute/value pair - * those we don't understand can be ignored, but * there are a few we'll need to handle. */ p->chap_current_attribute = data[0]; p->chap_current_datalen = data[1]; } if (bufchain_size(&p->pending_input_data) < p->chap_current_datalen) return 1; /* not got everything yet */ /* get the response */ bufchain_fetch(&p->pending_input_data, data, p->chap_current_datalen); bufchain_consume(&p->pending_input_data, p->chap_current_datalen); switch (p->chap_current_attribute) { case 0x00: /* Successful authentication */ if (data[0] == 0x00) p->state = 2; else { plug_closing(p->plug, "Proxy error: SOCKS proxy" " refused CHAP authentication", PROXY_ERROR_GENERAL, 0); return 1; } break; case 0x03: outbuf[0] = 0x01; /* Version */ outbuf[1] = 0x01; /* One attribute */ outbuf[2] = 0x04; /* Response */ outbuf[3] = 0x10; /* Length */ hmacmd5_chap(data, p->chap_current_datalen, conf_get_str(p->conf, CONF_proxy_password), &outbuf[4]); sk_write(p->sub_socket, (char *)outbuf, 20); break; case 0x11: /* Chose a protocol */ if (data[0] != 0x85) { plug_closing(p->plug, "Proxy error: Server chose " "CHAP of other than HMAC-MD5 but we " "didn't offer it!", PROXY_ERROR_GENERAL, 0); return 1; } break; } p->chap_current_attribute = -1; p->chap_num_attributes_processed++; } if (p->state == 8 && p->chap_num_attributes_processed >= p->chap_num_attributes) { p->chap_num_attributes = 0; p->chap_num_attributes_processed = 0; p->chap_current_datalen = 0; } } return 0; }
/* * Called to set up the adb connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *adb_init(void *frontend_handle, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay, int keepalive) { static const struct plug_function_table fn_table = { adb_log, adb_closing, adb_receive, adb_sent }; SockAddr addr; const char *err; Adb adb; adb = snew(struct adb_backend_data); adb->fn = &fn_table; adb->s = NULL; adb->state = 0; *backend_handle = adb; adb->frontend = frontend_handle; /* * Try to find host. */ { char *buf; buf = dupprintf("Looking up host \"%s\"%s", "localhost", (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(adb->frontend, buf); sfree(buf); } addr = name_lookup("localhost", port, realhost, cfg, cfg->addressfamily); if ((err = sk_addr_error(addr)) != NULL) { sk_addr_free(addr); return err; } if (port < 0) port = 5037; /* default adb port */ /* * Open socket. */ adb->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive, (Plug) adb, cfg); if ((err = sk_socket_error(adb->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 initial data to adb server */ #define ADB_SHELL_DEFAULT_STR "0012" "host:transport-usb" #define ADB_SHELL_DEFAULT_STR_LEN (sizeof(ADB_SHELL_DEFAULT_STR)-1) #define ADB_SHELL_SERIAL_PREFIX "host:transport:" #define ADB_SHELL_SERIAL_PREFIX_LEN (sizeof(ADB_SHELL_SERIAL_PREFIX)-1) do { size_t len = strlen(host); if (len == 0) { sk_write(adb->s, ADB_SHELL_DEFAULT_STR, ADB_SHELL_DEFAULT_STR_LEN); } else { char sendbuf[512]; #define ADB_SHELL_HOST_MAX_LEN \ (sizeof(sendbuf)-4-ADB_SHELL_SERIAL_PREFIX_LEN-1) if (len > ADB_SHELL_HOST_MAX_LEN) len = ADB_SHELL_HOST_MAX_LEN; sprintf(sendbuf,"%04x" ADB_SHELL_SERIAL_PREFIX, len+ADB_SHELL_SERIAL_PREFIX_LEN); memcpy(sendbuf+4+ADB_SHELL_SERIAL_PREFIX_LEN, host, len); sk_write(adb->s,sendbuf,len+4+ADB_SHELL_SERIAL_PREFIX_LEN); } } while (0); sk_flush(adb->s); adb->state = 1; return NULL; }
/* * Called to send data down the raw connection. */ int pfd_send(Socket s, char *data, int len) { if (s == NULL) return 0; return sk_write(s, data, len); }
/* * Called to set up the rlogin connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static char *rlogin_init(char *host, int port, char **realhost, int nodelay) { static struct plug_function_table fn_table = { rlogin_closing, rlogin_receive, rlogin_sent }, *fn_table_ptr = &fn_table; SockAddr addr; char *err; /* * Try to find host. */ { char buf[200]; sprintf(buf, "Looking up host \"%.170s\"", host); logevent(buf); } addr = sk_namelookup(host, realhost); if ((err = sk_addr_error(addr))) return err; if (port < 0) port = 513; /* default rlogin port */ /* * Open socket. */ { char buf[200], addrbuf[100]; sk_getaddr(addr, addrbuf, 100); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); logevent(buf); } s = sk_new(addr, port, 1, 0, nodelay, &fn_table_ptr); if ((err = sk_socket_error(s))) return err; sk_addr_free(addr); /* * Send local username, remote username, terminal/speed */ { char z = 0; char *p; sk_write(s, &z, 1); sk_write(s, cfg.localusername, strlen(cfg.localusername)); sk_write(s, &z, 1); sk_write(s, cfg.username, strlen(cfg.username)); sk_write(s, &z, 1); sk_write(s, cfg.termtype, strlen(cfg.termtype)); sk_write(s, "/", 1); for (p = cfg.termspeed; isdigit(*p); p++); sk_write(s, cfg.termspeed, p - cfg.termspeed); rlogin_bufsize = sk_write(s, &z, 1); } return NULL; }
/* * Called to set up the rlogin connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *rlogin_init(void *frontend_handle, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay, int keepalive) { static const struct plug_function_table fn_table = { rlogin_log, rlogin_closing, rlogin_receive, rlogin_sent }; SockAddr addr; const char *err; Rlogin rlogin; rlogin = snew(struct rlogin_tag); rlogin->fn = &fn_table; rlogin->s = NULL; rlogin->frontend = frontend_handle; rlogin->term_width = cfg->width; rlogin->term_height = cfg->height; rlogin->firstbyte = 1; rlogin->cansize = 0; *backend_handle = rlogin; /* * Try to find host. */ { char *buf; buf = dupprintf("Looking up host \"%s\"%s", host, (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(rlogin->frontend, buf); sfree(buf); } addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily); if ((err = sk_addr_error(addr)) != NULL) { sk_addr_free(addr); return err; } if (port < 0) port = 513; /* default rlogin port */ /* * Open socket. */ rlogin->s = new_connection(addr, *realhost, port, 1, 0, nodelay, keepalive, (Plug) rlogin, cfg); if ((err = sk_socket_error(rlogin->s)) != NULL) return err; /* * Send local username, remote username, terminal/speed */ { 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); } return NULL; }