Exemplo n.º 1
0
/*
 * This function can accept a NULL pointer as `addr', in which case
 * it will only check the host name.
 */
int proxy_for_destination(SockAddr addr,
                          const char *hostname,
                          int port,
                          Conf *conf)
{
  int s = 0, e = 0;
  char hostip[64];
  int hostip_len, hostname_len;
  const char *exclude_list;

  /*
   * Special local connections such as Unix-domain sockets
   * unconditionally cannot be proxied, even in proxy-localhost
   * mode. There just isn't any way to ask any known proxy type for
   * them.
   */
  if (addr && sk_address_is_special_local(addr))
    return 0; /* do not proxy */

  /*
   * Check the host name and IP against the hard-coded
   * representations of `localhost'.
   */
  if (!conf_get_int(conf, CONF_even_proxy_localhost) &&
      (sk_hostname_is_local(hostname) || (addr && sk_address_is_local(addr))))
    return 0; /* do not proxy */

  /* we want a string representation of the IP address for comparisons */
  if (addr) {
    sk_getaddr(addr, hostip, 64);
    hostip_len = strlen(hostip);
  } else
    hostip_len = 0; /* placate gcc; shouldn't be required */

  hostname_len = strlen(hostname);

  exclude_list = conf_get_str(conf, CONF_proxy_exclude_list);

  /* now parse the exclude list, and see if either our IP
   * or hostname matches anything in it.
   */

  while (exclude_list[s]) {
    while (exclude_list[s] &&
           (isspace((unsigned char)exclude_list[s]) || exclude_list[s] == ','))
      s++;

    if (!exclude_list[s])
      break;

    e = s;

    while (exclude_list[e] &&
           (isalnum((unsigned char)exclude_list[e]) || exclude_list[e] == '-' ||
            exclude_list[e] == '.' || exclude_list[e] == '*'))
      e++;

    if (exclude_list[s] == '*') {
      /* wildcard at beginning of entry */

      if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),
                            exclude_list + s + 1,
                            e - s - 1) == 0) ||
          strnicmp(hostname + hostname_len - (e - s - 1),
                   exclude_list + s + 1,
                   e - s - 1) == 0)
        return 0; /* IP/hostname range excluded. do not use proxy. */

    } else if (exclude_list[e - 1] == '*') {
      /* wildcard at end of entry */

      if ((addr && strnicmp(hostip, exclude_list + s, e - s - 1) == 0) ||
          strnicmp(hostname, exclude_list + s, e - s - 1) == 0)
        return 0; /* IP/hostname range excluded. do not use proxy. */

    } else {
      /* no wildcard at either end, so let's try an absolute
       * match (ie. a specific IP)
       */

      if (addr && strnicmp(hostip, exclude_list + s, e - s) == 0)
        return 0; /* IP/hostname excluded. do not use proxy. */
      if (strnicmp(hostname, exclude_list + s, e - s) == 0)
        return 0; /* IP/hostname excluded. do not use proxy. */
    }

    s = e;

    /* Make sure we really have reached the next comma or end-of-string */
    while (exclude_list[s] && !isspace((unsigned char)exclude_list[s]) &&
           exclude_list[s] != ',')
      s++;
  }

  /* no matches in the exclude list, so use the proxy */
  return 1;
}
Exemplo n.º 2
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 {