Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
/*
 * 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;
}
Пример #5
0
Файл: raw.c Проект: rdebath/sgt
/*
 * 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;
}
Пример #6
0
/*
 * 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;
}
Пример #7
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;
}
Пример #8
0
/*
 * 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;
}
Пример #9
0
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);
}
Пример #10
0
/*
 * 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;
}
Пример #11
0
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 {
Пример #12
0
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;
}
Пример #13
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,
                            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;
}
Пример #14
0
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;
}
Пример #15
0
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;
  }
Пример #16
0
/*
 * 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;
}
Пример #17
0
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);
}
Пример #18
0
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;
}
Пример #19
0
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);
}
Пример #20
0
/*
 * 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;
}
Пример #21
0
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;
}
Пример #22
0
/*
 * 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;
}