Пример #1
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
  }
Пример #5
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;
}
Пример #6
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 {
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
Socket new_connection(SockAddr addr, char *hostname,
		      int port, int privport,
		      int oobinline, int nodelay, int keepalive,
		      Plug plug, const Config *cfg)
{
    static const struct socket_function_table socket_fn_table = {
	sk_proxy_plug,
	sk_proxy_close,
	sk_proxy_write,
	sk_proxy_write_oob,
	sk_proxy_flush,
	sk_proxy_set_private_ptr,
	sk_proxy_get_private_ptr,
	sk_proxy_set_frozen,
	sk_proxy_socket_error
    };

    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 (cfg->proxy_type != PROXY_NONE &&
	proxy_for_destination(addr, hostname, port, cfg))
    {
	Proxy_Socket ret;
	Proxy_Plug pplug;
	SockAddr proxy_addr;
	char *proxy_canonical_name;
	Socket sret;

	if ((sret = platform_new_connection(addr, hostname, port, privport,
					    oobinline, nodelay, keepalive,
					    plug, cfg)) !=
	    NULL)
	    return sret;

	ret = snew(struct Socket_proxy_tag);
	ret->fn = &socket_fn_table;
	ret->cfg = *cfg;	       /* STRUCTURE COPY */
	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->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;
	
	if (cfg->proxy_type == PROXY_HTTP) {
	    ret->negotiate = proxy_http_negotiate;
	} else if (cfg->proxy_type == PROXY_SOCKS4) {
            ret->negotiate = proxy_socks4_negotiate;
	} else if (cfg->proxy_type == PROXY_SOCKS5) {
            ret->negotiate = proxy_socks5_negotiate;
	} else if (cfg->proxy_type == PROXY_TELNET) {
	    ret->negotiate = proxy_telnet_negotiate;
	} else {
	    ret->error = "Proxy error: Unknown proxy method";
	    return (Socket) ret;
	}

	/* 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;

	/* look-up proxy */
	proxy_addr = sk_namelookup(cfg->proxy_host,
				   &proxy_canonical_name, cfg->addressfamily);
	if (sk_addr_error(proxy_addr) != NULL) {
	    ret->error = "Proxy error: Unable to resolve proxy host name";
	    return (Socket)ret;
	}
	sfree(proxy_canonical_name);

	/* create the actual socket we will be using,
	 * connected to our proxy server and port.
	 */
	ret->sub_socket = sk_new(proxy_addr, cfg->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;
    }
Пример #11
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;
}
Пример #12
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;
}
Пример #13
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);
}
Пример #14
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;
}