static void sk_proxy_close(Socket s) { Proxy_Socket ps = (Proxy_Socket) s; sk_close(ps->sub_socket); sk_addr_free(ps->remote_addr); sfree(ps); }
static void sk_proxy_close (Socket s) { ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt); sk_close(ps->sub_socket); sk_addr_free(ps->remote_addr); sfree(ps); }
static void sk_proxy_close (Socket *s) { ProxySocket *ps = container_of(s, ProxySocket, sock); sk_close(ps->sub_socket); sk_addr_free(ps->remote_addr); sfree(ps); }
/* * Called to set up the raw 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 *raw_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 = { raw_log, raw_closing, raw_receive, raw_sent }; SockAddr addr; const char *err; Raw raw; raw = snew(struct raw_backend_data); raw->fn = &fn_table; raw->s = NULL; *backend_handle = raw; raw->frontend = frontend_handle; /* * 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(raw->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 = 23; /* default telnet port */ /* * Open socket. */ raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive, (Plug) raw, cfg); if ((err = sk_socket_error(raw->s)) != NULL) return err; return NULL; }
/* * Called to set up the raw 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 *raw_init(char *host, int port, char **realhost, int nodelay) { static struct plug_function_table fn_table = { raw_closing, raw_receive, raw_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 = 23; /* default telnet 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 = new_connection(addr, *realhost, port, 0, 1, nodelay, &fn_table_ptr); if ((err = sk_socket_error(s))) return err; sk_addr_free(addr); return NULL; }
/* * Called when receiving a PORT OPEN from the server */ char *pfd_newconnect(Socket *s, char *hostname, int port, void *c) { static struct plug_function_table fn_table = { pfd_closing, pfd_receive, pfd_sent, NULL }; SockAddr addr; char *err, *dummy_realhost; struct PFwdPrivate *pr; /* * Try to find host. */ addr = sk_namelookup(hostname, &dummy_realhost); if ((err = sk_addr_error(addr))) return err; /* * Open socket. */ pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate)); pr->fn = &fn_table; pr->throttled = pr->throttle_override = 0; pr->ready = 1; pr->c = c; pr->s = *s = sk_new(addr, port, 0, 1, 0, (Plug) pr); if ((err = sk_socket_error(*s))) { sfree(pr); return err; } sk_set_private_ptr(*s, pr); sk_addr_free(addr); return NULL; }
/* * 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 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, Conf *conf, 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, NULL }; SockAddr addr; const char *err; Rlogin rlogin; char *ruser; int addressfamily; char *loghost; rlogin = snew(struct rlogin_tag); rlogin->fn = &fn_table; rlogin->s = NULL; rlogin->closed_on_socket_error = FALSE; rlogin->frontend = frontend_handle; rlogin->term_width = conf_get_int(conf, CONF_width); rlogin->term_height = conf_get_int(conf, CONF_height); rlogin->firstbyte = 1; rlogin->cansize = 0; rlogin->prompt = NULL; rlogin->conf = conf_copy(conf); *backend_handle = rlogin; addressfamily = conf_get_int(conf, CONF_addressfamily); /* * Try to find host. */ { char *buf; buf = dupprintf("Looking up host \"%s\"%s", host, (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(rlogin->frontend, buf); sfree(buf); } addr = name_lookup(host, port, realhost, conf, 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, conf); if ((err = sk_socket_error(rlogin->s)) != NULL) return err; loghost = conf_get_str(conf, CONF_loghost); if (*loghost) { char *colon; sfree(*realhost); *realhost = dupstr(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 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. */ if ((ruser = get_remote_username(conf)) != NULL) { rlogin_startup(rlogin, ruser); sfree(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); ret = get_userpass_input(rlogin->prompt, NULL, 0); if (ret >= 0) { rlogin_startup(rlogin, rlogin->prompt->prompts[0]->result); } } return NULL; }
Socket *new_connection(SockAddr *addr, const char *hostname, int port, bool privport, bool oobinline, bool nodelay, bool keepalive, Plug *plug, Conf *conf) { if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE && proxy_for_destination(addr, hostname, port, conf)) { ProxySocket *ret; SockAddr *proxy_addr; char *proxy_canonical_name; const char *proxy_type; Socket *sret; int type; if ((sret = platform_new_connection(addr, hostname, port, privport, oobinline, nodelay, keepalive, plug, conf)) != NULL) return sret; ret = snew(ProxySocket); ret->sock.vt = &ProxySocket_sockvt; ret->plugimpl.vt = &ProxySocket_plugvt; ret->conf = conf_copy(conf); ret->plug = plug; ret->remote_addr = addr; /* will need to be freed on close */ ret->remote_port = port; ret->error = NULL; ret->pending_flush = false; ret->pending_eof = false; ret->freeze = false; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_oob_output_data); ret->sub_socket = NULL; ret->state = PROXY_STATE_NEW; ret->negotiate = NULL; type = conf_get_int(conf, CONF_proxy_type); if (type == PROXY_HTTP) { ret->negotiate = proxy_http_negotiate; proxy_type = "HTTP"; } else if (type == PROXY_SOCKS4) { ret->negotiate = proxy_socks4_negotiate; proxy_type = "SOCKS 4"; } else if (type == PROXY_SOCKS5) { ret->negotiate = proxy_socks5_negotiate; proxy_type = "SOCKS 5"; } else if (type == PROXY_TELNET) { ret->negotiate = proxy_telnet_negotiate; proxy_type = "Telnet"; } else { ret->error = "Proxy error: Unknown proxy method"; return &ret->sock; } { char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect" " to %s:%d", proxy_type, conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_proxy_port), hostname, port); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } { char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_addressfamily), "proxy"); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* look-up proxy */ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host), &proxy_canonical_name, conf_get_int(conf, CONF_addressfamily)); if (sk_addr_error(proxy_addr) != NULL) { ret->error = "Proxy error: Unable to resolve proxy host name"; sk_addr_free(proxy_addr); return &ret->sock; } sfree(proxy_canonical_name); { char addrbuf[256], *logmsg; sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf)); logmsg = dupprintf("Connecting to %s proxy at %s port %d", proxy_type, addrbuf, conf_get_int(conf, CONF_proxy_port)); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the actual socket we will be using, * connected to our proxy server and port. */ ret->sub_socket = sk_new(proxy_addr, conf_get_int(conf, CONF_proxy_port), privport, oobinline, nodelay, keepalive, &ret->plugimpl); if (sk_socket_error(ret->sub_socket) != NULL) return &ret->sock; /* start the proxy negotiation process... */ sk_set_frozen(ret->sub_socket, 0); ret->negotiate(ret, PROXY_CHANGE_NEW); return &ret->sock; } /* no proxy, so just return the direct socket */ return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug); }
/* * 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; }
struct X11Display *x11_setup_display(char *display, int authtype, Conf *conf) { struct X11Display *disp = snew(struct X11Display); char *localcopy; int i; if (!display || !*display) { localcopy = platform_get_x_display(); if (!localcopy || !*localcopy) { sfree(localcopy); localcopy = dupstr(":0"); /* plausible default for any platform */ } } else localcopy = dupstr(display); /* * Parse the display name. * * We expect this to have one of the following forms: * * - the standard X format which looks like * [ [ protocol '/' ] host ] ':' displaynumber [ '.' screennumber ] * (X11 also permits a double colon to indicate DECnet, but * that's not our problem, thankfully!) * * - only seen in the wild on MacOS (so far): a pathname to a * Unix-domain socket, which will typically and confusingly * end in ":0", and which I'm currently distinguishing from * the standard scheme by noting that it starts with '/'. */ if (localcopy[0] == '/') { disp->unixsocketpath = localcopy; disp->unixdomain = TRUE; disp->hostname = NULL; disp->displaynum = -1; disp->screennum = 0; disp->addr = NULL; } else { char *colon, *dot, *slash; char *protocol, *hostname; colon = strrchr(localcopy, ':'); if (!colon) { sfree(disp); sfree(localcopy); return NULL; /* FIXME: report a specific error? */ } *colon++ = '\0'; dot = strchr(colon, '.'); if (dot) *dot++ = '\0'; disp->displaynum = atoi(colon); if (dot) disp->screennum = atoi(dot); else disp->screennum = 0; protocol = NULL; hostname = localcopy; if (colon > localcopy) { slash = strchr(localcopy, '/'); if (slash) { *slash++ = '\0'; protocol = localcopy; hostname = slash; } } disp->hostname = *hostname ? dupstr(hostname) : NULL; if (protocol) disp->unixdomain = (!strcmp(protocol, "local") || !strcmp(protocol, "unix")); else if (!*hostname || !strcmp(hostname, "unix")) disp->unixdomain = platform_uses_x11_unix_by_default; else disp->unixdomain = FALSE; if (!disp->hostname && !disp->unixdomain) disp->hostname = dupstr("localhost"); disp->unixsocketpath = NULL; disp->addr = NULL; sfree(localcopy); } /* * Look up the display hostname, if we need to. */ if (!disp->unixdomain) { const char *err; disp->port = 6000 + disp->displaynum; disp->addr = name_lookup(disp->hostname, disp->port, &disp->realhost, conf, ADDRTYPE_UNSPEC); if ((err = sk_addr_error(disp->addr)) != NULL) { sk_addr_free(disp->addr); sfree(disp->hostname); sfree(disp->unixsocketpath); sfree(disp); return NULL; /* FIXME: report an error */ } } /* * Try upgrading an IP-style localhost display to a Unix-socket * display (as the standard X connection libraries do). */ if (!disp->unixdomain && sk_address_is_local(disp->addr)) { SockAddr ux = platform_get_x11_unix_address(NULL, disp->displaynum); const char *err = sk_addr_error(ux); if (!err) { /* Create trial connection to see if there is a useful Unix-domain * socket */ const struct plug_function_table *dummy = &dummy_plug; Socket s = putty_sk_new(sk_addr_dup(ux), 0, 0, 0, 0, 0, (Plug)&dummy #ifdef MPEXT , 0, 0 #endif ); err = sk_socket_error(s); sk_close(s); } if (err) { sk_addr_free(ux); } else { sk_addr_free(disp->addr); disp->unixdomain = TRUE; disp->addr = ux; /* Fill in the rest in a moment */ } } if (disp->unixdomain) { if (!disp->addr) disp->addr = platform_get_x11_unix_address(disp->unixsocketpath, disp->displaynum); if (disp->unixsocketpath) disp->realhost = dupstr(disp->unixsocketpath); else disp->realhost = dupprintf("unix:%d", disp->displaynum); disp->port = 0; } /* * Invent the remote authorisation details. */ if (authtype == X11_MIT) { disp->remoteauthproto = X11_MIT; /* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */ disp->remoteauthdata = snewn(16, unsigned char); for (i = 0; i < 16; i++) disp->remoteauthdata[i] = random_byte(); disp->remoteauthdatalen = 16; disp->xdmseen = NULL; } else {
int platform_make_x11_server(Plug *plug, const char *progname, int mindisp, const char *screen_number_suffix, ptrlen authproto, ptrlen authdata, Socket **sockets, Conf *conf) { char *tmpdir; char *authfilename = NULL; strbuf *authfiledata = NULL; char *unix_path = NULL; SockAddr *a_tcp = NULL, *a_unix = NULL; int authfd; FILE *authfp; int displayno; authfiledata = strbuf_new_nm(); int nsockets = 0; /* * Look for a free TCP port to run our server on. */ for (displayno = mindisp;; displayno++) { const char *err; int tcp_port = displayno + 6000; int addrtype = ADDRTYPE_IPV4; sockets[nsockets] = new_listener( NULL, tcp_port, plug, false, conf, addrtype); err = sk_socket_error(sockets[nsockets]); if (!err) { char *hostname = get_hostname(); if (hostname) { char *canonicalname = NULL; a_tcp = name_lookup(hostname, tcp_port, &canonicalname, conf, addrtype, NULL, ""); sfree(canonicalname); } sfree(hostname); nsockets++; break; /* success! */ } else { sk_close(sockets[nsockets]); } if (!strcmp(err, strerror(EADDRINUSE))) /* yuck! */ goto out; } if (a_tcp) { x11_format_auth_for_authfile( BinarySink_UPCAST(authfiledata), a_tcp, displayno, authproto, authdata); } /* * Try to establish the Unix-domain analogue. That may or may not * work - file permissions in /tmp may prevent it, for example - * but it's worth a try, and we don't consider it a fatal error if * it doesn't work. */ unix_path = dupprintf("/tmp/.X11-unix/X%d", displayno); a_unix = unix_sock_addr(unix_path); sockets[nsockets] = new_unix_listener(a_unix, plug); if (!sk_socket_error(sockets[nsockets])) { x11_format_auth_for_authfile( BinarySink_UPCAST(authfiledata), a_unix, displayno, authproto, authdata); nsockets++; } else { sk_close(sockets[nsockets]); sfree(unix_path); unix_path = NULL; } /* * Decide where the authority data will be written. */ tmpdir = getenv("TMPDIR"); if (!tmpdir || !*tmpdir) tmpdir = "/tmp"; authfilename = dupcat(tmpdir, "/", progname, "-Xauthority-XXXXXX", NULL); { int oldumask = umask(077); authfd = mkstemp(authfilename); umask(oldumask); } if (authfd < 0) { while (nsockets-- > 0) sk_close(sockets[nsockets]); goto out; } /* * Spawn a subprocess which will try to reliably delete our * auth file when we terminate, in case we die unexpectedly. */ { int cleanup_pipe[2]; pid_t pid; /* Don't worry if pipe or fork fails; it's not _that_ critical. */ if (!pipe(cleanup_pipe)) { if ((pid = fork()) == 0) { int buf[1024]; /* * Our parent process holds the writing end of * this pipe, and writes nothing to it. Hence, * we expect read() to return EOF as soon as * that process terminates. */ close(0); close(1); close(2); setpgid(0, 0); close(cleanup_pipe[1]); close(authfd); while (read(cleanup_pipe[0], buf, sizeof(buf)) > 0); unlink(authfilename); if (unix_path) unlink(unix_path); _exit(0); } else if (pid < 0) { close(cleanup_pipe[0]); close(cleanup_pipe[1]); } else { close(cleanup_pipe[0]); cloexec(cleanup_pipe[1]); } } } authfp = fdopen(authfd, "wb"); fwrite(authfiledata->u, 1, authfiledata->len, authfp); fclose(authfp); { char *display = dupprintf(":%d%s", displayno, screen_number_suffix); conf_set_str_str(conf, CONF_environmt, "DISPLAY", display); sfree(display); } conf_set_str_str(conf, CONF_environmt, "XAUTHORITY", authfilename); /* * FIXME: return at least the DISPLAY and XAUTHORITY env settings, * and perhaps also the display number */ out: if (a_tcp) sk_addr_free(a_tcp); /* a_unix doesn't need freeing, because new_unix_listener took it over */ sfree(authfilename); strbuf_free(authfiledata); sfree(unix_path); return nsockets; }
/* * 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, Conf *conf, 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, NULL }; SockAddr addr; const char *err; Adb adb; adb = snew(struct adb_backend_data); adb->fn = &fn_table; adb->s = NULL; adb->state = STATE_WARMING_UP; *backend_handle = adb; adb->frontend = frontend_handle; /* * Try to find host. */ { char *buf; buf = dupprintf("Looking up host \"%s\"%s", "localhost", (conf_get_int(conf, CONF_addressfamily) == ADDRTYPE_IPV4 ? " (IPv4)" : (conf_get_int(conf, CONF_addressfamily) == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(adb->frontend, buf); sfree(buf); } addr = name_lookup("localhost", port, realhost, conf, conf_get_int(conf, CONF_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, conf); if ((err = sk_socket_error(adb->s)) != NULL) return err; if (*conf_get_str(conf, CONF_loghost)) { char *colon; sfree(*realhost); *realhost = conf_get_str(conf, CONF_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-any" #define ADB_SHELL_DEFAULT_STR_LEN (sizeof(ADB_SHELL_DEFAULT_STR)-1) #define ADB_SHELL_USB_STR "0012" "host:transport-usb" #define ADB_SHELL_USB_STR_LEN (sizeof(ADB_SHELL_USB_STR)-1) #define ADB_SHELL_LOCAL_STR "0015" "host:transport-local" #define ADB_SHELL_LOCAL_STR_LEN (sizeof(ADB_SHELL_LOCAL_STR)-1) #define ADB_SHELL_SERIAL_PREFIX "host:transport:" #define ADB_SHELL_SERIAL_PREFIX_LEN (sizeof(ADB_SHELL_SERIAL_PREFIX)-1) # define write_hello(str, len) \ sk_write(adb->s, str, len); \ sk_flush(adb->s); \ adb->state = STATE_SENT_HELLO; do { size_t len; if (host[0] == ':') ++host; len = strlen(host); if (len == 0 || !strcmp("-a", host) || !strcmp(host, "transport-any")) { write_hello(ADB_SHELL_DEFAULT_STR, ADB_SHELL_DEFAULT_STR_LEN); } else if (!strcmp("-d", host) || !strcmp(host, "transport-usb")) { write_hello(ADB_SHELL_USB_STR, ADB_SHELL_USB_STR_LEN); } else if (!strcmp("-e", host) || !strcmp(host, "transport-local")) { write_hello(ADB_SHELL_LOCAL_STR, ADB_SHELL_LOCAL_STR_LEN); } else { char sendbuf[512]; # define ADB_SHELL_HOST_MAX_LEN (sizeof(sendbuf)-4-ADB_SHELL_SERIAL_PREFIX_LEN) if (len > ADB_SHELL_HOST_MAX_LEN) len = ADB_SHELL_HOST_MAX_LEN; sprintf(sendbuf,"%04lx" ADB_SHELL_SERIAL_PREFIX, (unsigned long)(len+ADB_SHELL_SERIAL_PREFIX_LEN)); memcpy(sendbuf+4+ADB_SHELL_SERIAL_PREFIX_LEN, host, len); write_hello(sendbuf, len+4+ADB_SHELL_SERIAL_PREFIX_LEN); } } while (0); return NULL; }
Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, const Config *cfg) { char *cmd; static const struct socket_function_table socket_fn_table = { sk_localproxy_plug, sk_localproxy_close, sk_localproxy_write, sk_localproxy_write_oob, sk_localproxy_flush, sk_localproxy_set_private_ptr, sk_localproxy_get_private_ptr, sk_localproxy_set_frozen, sk_localproxy_socket_error }; Local_Proxy_Socket ret; HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (cfg->proxy_type != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, cfg); { char *msg = dupprintf("Starting local proxy command: %s", cmd); /* We're allowed to pass NULL here, because we're part of the Windows * front end so we know logevent doesn't expect any data. */ logevent(NULL, msg); sfree(msg); } ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { ret->error = dupprintf("Unable to create pipes for proxy command"); return (Socket)ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); ret->error = dupprintf("Unable to create pipes for proxy command"); return (Socket)ret; } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = NULL; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); ret->to_cmd_H = us_to_cmd; ret->from_cmd_H = us_from_cmd; ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, ret, 0); ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata, ret, 0); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
Socket new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { static const struct socket_function_table socket_fn_table = { sk_proxy_plug, sk_proxy_close, sk_proxy_write, sk_proxy_write_oob, sk_proxy_write_eof, sk_proxy_flush, sk_proxy_set_frozen, sk_proxy_socket_error, NULL, /* peer_info */ }; static const struct plug_function_table plug_fn_table = { plug_proxy_log, plug_proxy_closing, plug_proxy_receive, plug_proxy_sent, plug_proxy_accepting}; if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE && proxy_for_destination(addr, hostname, port, conf)) { Proxy_Socket ret; Proxy_Plug pplug; SockAddr proxy_addr; char *proxy_canonical_name; const char *proxy_type; Socket sret; int type; if ((sret = platform_new_connection(addr, hostname, port, privport, oobinline, nodelay, keepalive, plug, conf)) != NULL) return sret; ret = snew(struct Socket_proxy_tag); ret->fn = &socket_fn_table; ret->conf = conf_copy(conf); ret->plug = plug; ret->remote_addr = addr; /* will need to be freed on close */ ret->remote_port = port; ret->error = NULL; ret->pending_flush = 0; ret->pending_eof = 0; ret->freeze = 0; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_oob_output_data); ret->sub_socket = NULL; ret->state = PROXY_STATE_NEW; ret->negotiate = NULL; type = conf_get_int(conf, CONF_proxy_type); if (type == PROXY_HTTP) { ret->negotiate = proxy_http_negotiate; proxy_type = "HTTP"; } else if (type == PROXY_SOCKS4) { ret->negotiate = proxy_socks4_negotiate; proxy_type = "SOCKS 4"; } else if (type == PROXY_SOCKS5) { ret->negotiate = proxy_socks5_negotiate; proxy_type = "SOCKS 5"; } else if (type == PROXY_TELNET) { ret->negotiate = proxy_telnet_negotiate; proxy_type = "Telnet"; } else { ret->error = "Proxy error: Unknown proxy method"; return (Socket)ret; } { char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect" " to %s:%d", proxy_type, conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_proxy_port), hostname, port); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the proxy plug to map calls from the actual * socket into our proxy socket layer */ pplug = snew(struct Plug_proxy_tag); pplug->fn = &plug_fn_table; pplug->proxy_socket = ret; { char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_addressfamily), "proxy"); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* look-up proxy */ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host), &proxy_canonical_name, conf_get_int(conf, CONF_addressfamily)); if (sk_addr_error(proxy_addr) != NULL) { ret->error = "Proxy error: Unable to resolve proxy host name"; sfree(pplug); sk_addr_free(proxy_addr); return (Socket)ret; } sfree(proxy_canonical_name); { char addrbuf[256], *logmsg; sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf)); logmsg = dupprintf("Connecting to %s proxy at %s port %d", proxy_type, addrbuf, conf_get_int(conf, CONF_proxy_port)); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the actual socket we will be using, * connected to our proxy server and port. */ ret->sub_socket = sk_new(proxy_addr, conf_get_int(conf, CONF_proxy_port), privport, oobinline, nodelay, keepalive, (Plug)pplug); if (sk_socket_error(ret->sub_socket) != NULL) return (Socket)ret; /* start the proxy negotiation process... */ sk_set_frozen(ret->sub_socket, 0); ret->negotiate(ret, PROXY_CHANGE_NEW); return (Socket)ret; }
/* * Called to set up the raw 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 *raw_init(void *frontend_handle, void **backend_handle, Conf *conf, const char *host, int port, char **realhost, int nodelay, int keepalive) { static const struct plug_function_table fn_table = { raw_log, raw_closing, raw_receive, raw_sent }; SockAddr addr; const char *err; Raw raw; int addressfamily; char *loghost; raw = snew(struct raw_backend_data); raw->fn = &fn_table; raw->s = NULL; raw->closed_on_socket_error = FALSE; *backend_handle = raw; raw->sent_console_eof = raw->sent_socket_eof = FALSE; raw->bufsize = 0; raw->session_started = FALSE; raw->conf = conf_copy(conf); raw->frontend = frontend_handle; addressfamily = conf_get_int(conf, CONF_addressfamily); /* * Try to find host. */ addr = name_lookup(host, port, realhost, conf, addressfamily, raw->frontend, "main connection"); if ((err = sk_addr_error(addr)) != NULL) { sk_addr_free(addr); return err; } if (port < 0) port = 23; /* default telnet port */ /* * Open socket. */ raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive, (Plug) raw, conf); if ((err = sk_socket_error(raw->s)) != NULL) return err; loghost = conf_get_str(conf, CONF_loghost); if (*loghost) { char *colon; sfree(*realhost); *realhost = dupstr(loghost); colon = host_strrchr(*realhost, ':'); if (colon) *colon++ = '\0'; } return NULL; }
Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; HANDLE us_to_cmd, cmd_from_us; HANDLE us_from_cmd, cmd_to_us; HANDLE us_from_cmd_err, cmd_err_to_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, conf); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); { char *msg = dupprintf("Starting local proxy command: %s", cmd); plug_log(plug, 2, NULL, 0, msg, 0); sfree(msg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); return ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); return ret; } if (flags & FLAG_STDERR) { /* If we have a sensible stderr, the proxy command can send * its own standard error there, so we won't interfere. */ us_from_cmd_err = cmd_err_to_us = NULL; } else { /* If we don't have a sensible stderr, we should catch the * proxy command's standard error to put in our event log. */ if (!CreatePipe(&us_from_cmd_err, &cmd_err_to_us, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); CloseHandle(us_to_cmd); CloseHandle(cmd_from_us); return ret; } } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); if (us_from_cmd_err != NULL) SetHandleInformation(us_from_cmd_err, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = cmd_err_to_us; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); sfree(cmd); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); if (cmd_err_to_us != NULL) CloseHandle(cmd_err_to_us); return make_handle_socket( us_to_cmd, us_from_cmd, us_from_cmd_err, plug, FALSE); }
Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; static const struct socket_function_table socket_fn_table = { sk_localproxy_plug, sk_localproxy_close, sk_localproxy_write, sk_localproxy_write_oob, sk_localproxy_write_eof, sk_localproxy_flush, sk_localproxy_set_frozen, sk_localproxy_socket_error, NULL, /* peer_info */ }; Local_Proxy_Socket ret; int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2], pid, proxytype; proxytype = conf_get_int(conf, CONF_proxy_type); if (proxytype != PROXY_CMD && proxytype != PROXY_FUZZ) return NULL; ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; ret->outgoingeof = EOF_NO; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_error_data); if (proxytype == PROXY_CMD) { cmd = format_telnet_command(addr, port, conf); if (flags & FLAG_STDERR) { /* If we have a sensible stderr, the proxy command can * send its own standard error there, so we won't * interfere. */ cmd_err_pipe[0] = cmd_err_pipe[1] = -1; } else { /* If we don't have a sensible stderr, we should catch the * proxy command's standard error to put in our event * log. */ cmd_err_pipe[0] = cmd_err_pipe[1] = 0; } { char *logmsg = dupprintf("Starting local proxy command: %s", cmd); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ if (pipe(to_cmd_pipe) < 0 || pipe(from_cmd_pipe) < 0 || (cmd_err_pipe[0] == 0 && pipe(cmd_err_pipe) < 0)) { ret->error = dupprintf("pipe: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } cloexec(to_cmd_pipe[1]); cloexec(from_cmd_pipe[0]); if (cmd_err_pipe[0] >= 0) cloexec(cmd_err_pipe[0]); pid = fork(); if (pid < 0) { ret->error = dupprintf("fork: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } else if (pid == 0) { close(0); close(1); dup2(to_cmd_pipe[0], 0); dup2(from_cmd_pipe[1], 1); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); if (cmd_err_pipe[0] >= 0) { dup2(cmd_err_pipe[1], 2); close(cmd_err_pipe[1]); } noncloexec(0); noncloexec(1); execl("/bin/sh", "sh", "-c", cmd, (void *)NULL); _exit(255); } sfree(cmd); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); if (cmd_err_pipe[0] >= 0) close(cmd_err_pipe[1]); ret->to_cmd = to_cmd_pipe[1]; ret->from_cmd = from_cmd_pipe[0]; ret->cmd_err = cmd_err_pipe[0]; } else { cmd = format_telnet_command(addr, port, conf); ret->to_cmd = open("/dev/null", O_WRONLY); if (ret->to_cmd == -1) { ret->error = dupprintf("/dev/null: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } ret->from_cmd = open(cmd, O_RDONLY); if (ret->from_cmd == -1) { ret->error = dupprintf("%s: %s", cmd, strerror(errno)); sfree(cmd); return (Socket)ret; } sfree(cmd); ret->cmd_err = -1; } if (!localproxy_by_fromfd) localproxy_by_fromfd = newtree234(localproxy_fromfd_cmp); if (!localproxy_by_tofd) localproxy_by_tofd = newtree234(localproxy_tofd_cmp); if (!localproxy_by_errfd) localproxy_by_errfd = newtree234(localproxy_errfd_cmp); add234(localproxy_by_fromfd, ret); add234(localproxy_by_tofd, ret); if (ret->cmd_err >= 0) add234(localproxy_by_errfd, ret); uxsel_set(ret->from_cmd, 1, localproxy_select_result); if (ret->cmd_err >= 0) uxsel_set(ret->cmd_err, 1, localproxy_select_result); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, conf); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); { char *msg = dupprintf("Starting local proxy command: %s", cmd); /* We're allowed to pass NULL here, because we're part of the Windows * front end so we know logevent doesn't expect any data. */ logevent(NULL, msg); sfree(msg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); return ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); return ret; } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = NULL; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); sfree(cmd); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); return make_handle_socket(us_to_cmd, us_from_cmd, plug, FALSE); }
/* * Called to set up the raw 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 *raw_init(void *frontend_handle, void **backend_handle, Conf *conf, char *host, int port, char **realhost, int nodelay, int keepalive) { static const struct plug_function_table fn_table = { raw_log, raw_closing, raw_receive, raw_sent }; SockAddr addr; const char *err; Raw raw; int addressfamily; char *loghost; raw = snew(struct raw_backend_data); raw->fn = &fn_table; raw->s = NULL; *backend_handle = raw; raw->sent_console_eof = raw->sent_socket_eof = FALSE; raw->frontend = frontend_handle; addressfamily = conf_get_int(conf, CONF_addressfamily); /* * Try to find host. */ { char *buf; buf = dupprintf("Looking up host \"%s\"%s", host, (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" : (addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : ""))); logevent(raw->frontend, buf); sfree(buf); } addr = name_lookup(host, port, realhost, conf, addressfamily); if ((err = sk_addr_error(addr)) != NULL) { sk_addr_free(addr); return err; } if (port < 0) port = 23; /* default telnet port */ /* * Open socket. */ raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive, (Plug) raw, conf); if ((err = sk_socket_error(raw->s)) != NULL) return err; loghost = conf_get_str(conf, CONF_loghost); if (*loghost) { char *colon; sfree(*realhost); *realhost = dupstr(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'; } } return NULL; }
Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; static const struct socket_function_table socket_fn_table = { sk_localproxy_plug, sk_localproxy_close, sk_localproxy_write, sk_localproxy_write_oob, sk_localproxy_write_eof, sk_localproxy_flush, sk_localproxy_set_private_ptr, sk_localproxy_get_private_ptr, sk_localproxy_set_frozen, sk_localproxy_socket_error }; Local_Proxy_Socket ret; int to_cmd_pipe[2], from_cmd_pipe[2], pid; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, conf); ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; ret->outgoingeof = EOF_NO; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ if (pipe(to_cmd_pipe) < 0 || pipe(from_cmd_pipe) < 0) { ret->error = dupprintf("pipe: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } cloexec(to_cmd_pipe[1]); cloexec(from_cmd_pipe[0]); pid = fork(); if (pid < 0) { ret->error = dupprintf("fork: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } else if (pid == 0) { close(0); close(1); dup2(to_cmd_pipe[0], 0); dup2(from_cmd_pipe[1], 1); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); noncloexec(0); noncloexec(1); execl("/bin/sh", "sh", "-c", cmd, (void *)NULL); _exit(255); } sfree(cmd); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); ret->to_cmd = to_cmd_pipe[1]; ret->from_cmd = from_cmd_pipe[0]; if (!localproxy_by_fromfd) localproxy_by_fromfd = newtree234(localproxy_fromfd_cmp); if (!localproxy_by_tofd) localproxy_by_tofd = newtree234(localproxy_tofd_cmp); add234(localproxy_by_fromfd, ret); add234(localproxy_by_tofd, ret); uxsel_set(ret->from_cmd, 1, localproxy_select_result); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
/* * 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; }