"Fossies" - the Fresh Open Source Software Archive

Member "putty-0.73/proxy.c" (22 Sep 2019, 51870 Bytes) of package /linux/misc/putty-0.73.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "proxy.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.72_vs_0.73.

    1 /*
    2  * Network proxy abstraction in PuTTY
    3  *
    4  * A proxy layer, if necessary, wedges itself between the network
    5  * code and the higher level backend.
    6  */
    7 
    8 #include <assert.h>
    9 #include <ctype.h>
   10 #include <string.h>
   11 
   12 #include "putty.h"
   13 #include "network.h"
   14 #include "proxy.h"
   15 
   16 #define do_proxy_dns(conf) \
   17     (conf_get_int(conf, CONF_proxy_dns) == FORCE_ON || \
   18          (conf_get_int(conf, CONF_proxy_dns) == AUTO && \
   19               conf_get_int(conf, CONF_proxy_type) != PROXY_SOCKS4))
   20 
   21 /*
   22  * Call this when proxy negotiation is complete, so that this
   23  * socket can begin working normally.
   24  */
   25 void proxy_activate (ProxySocket *p)
   26 {
   27     size_t output_before, output_after;
   28 
   29     p->state = PROXY_STATE_ACTIVE;
   30 
   31     /* we want to ignore new receive events until we have sent
   32      * all of our buffered receive data.
   33      */
   34     sk_set_frozen(p->sub_socket, true);
   35 
   36     /* how many bytes of output have we buffered? */
   37     output_before = bufchain_size(&p->pending_oob_output_data) +
   38         bufchain_size(&p->pending_output_data);
   39     /* and keep track of how many bytes do not get sent. */
   40     output_after = 0;
   41 
   42     /* send buffered OOB writes */
   43     while (bufchain_size(&p->pending_oob_output_data) > 0) {
   44         ptrlen data = bufchain_prefix(&p->pending_oob_output_data);
   45         output_after += sk_write_oob(p->sub_socket, data.ptr, data.len);
   46         bufchain_consume(&p->pending_oob_output_data, data.len);
   47     }
   48 
   49     /* send buffered normal writes */
   50     while (bufchain_size(&p->pending_output_data) > 0) {
   51         ptrlen data = bufchain_prefix(&p->pending_output_data);
   52         output_after += sk_write(p->sub_socket, data.ptr, data.len);
   53         bufchain_consume(&p->pending_output_data, data.len);
   54     }
   55 
   56     /* if we managed to send any data, let the higher levels know. */
   57     if (output_after < output_before)
   58         plug_sent(p->plug, output_after);
   59 
   60     /* if we have a pending EOF to send, send it */
   61     if (p->pending_eof) sk_write_eof(p->sub_socket);
   62 
   63     /* if the backend wanted the socket unfrozen, try to unfreeze.
   64      * our set_frozen handler will flush buffered receive data before
   65      * unfreezing the actual underlying socket.
   66      */
   67     if (!p->freeze)
   68         sk_set_frozen(&p->sock, 0);
   69 }
   70 
   71 /* basic proxy socket functions */
   72 
   73 static Plug *sk_proxy_plug (Socket *s, Plug *p)
   74 {
   75     ProxySocket *ps = container_of(s, ProxySocket, sock);
   76     Plug *ret = ps->plug;
   77     if (p)
   78         ps->plug = p;
   79     return ret;
   80 }
   81 
   82 static void sk_proxy_close (Socket *s)
   83 {
   84     ProxySocket *ps = container_of(s, ProxySocket, sock);
   85 
   86     sk_close(ps->sub_socket);
   87     sk_addr_free(ps->remote_addr);
   88     sfree(ps);
   89 }
   90 
   91 static size_t sk_proxy_write (Socket *s, const void *data, size_t len)
   92 {
   93     ProxySocket *ps = container_of(s, ProxySocket, sock);
   94 
   95     if (ps->state != PROXY_STATE_ACTIVE) {
   96         bufchain_add(&ps->pending_output_data, data, len);
   97         return bufchain_size(&ps->pending_output_data);
   98     }
   99     return sk_write(ps->sub_socket, data, len);
  100 }
  101 
  102 static size_t sk_proxy_write_oob (Socket *s, const void *data, size_t len)
  103 {
  104     ProxySocket *ps = container_of(s, ProxySocket, sock);
  105 
  106     if (ps->state != PROXY_STATE_ACTIVE) {
  107         bufchain_clear(&ps->pending_output_data);
  108         bufchain_clear(&ps->pending_oob_output_data);
  109         bufchain_add(&ps->pending_oob_output_data, data, len);
  110         return len;
  111     }
  112     return sk_write_oob(ps->sub_socket, data, len);
  113 }
  114 
  115 static void sk_proxy_write_eof (Socket *s)
  116 {
  117     ProxySocket *ps = container_of(s, ProxySocket, sock);
  118 
  119     if (ps->state != PROXY_STATE_ACTIVE) {
  120         ps->pending_eof = true;
  121         return;
  122     }
  123     sk_write_eof(ps->sub_socket);
  124 }
  125 
  126 static void sk_proxy_set_frozen (Socket *s, bool is_frozen)
  127 {
  128     ProxySocket *ps = container_of(s, ProxySocket, sock);
  129 
  130     if (ps->state != PROXY_STATE_ACTIVE) {
  131         ps->freeze = is_frozen;
  132         return;
  133     }
  134 
  135     /* handle any remaining buffered recv data first */
  136     if (bufchain_size(&ps->pending_input_data) > 0) {
  137         ps->freeze = is_frozen;
  138 
  139         /* loop while we still have buffered data, and while we are
  140          * unfrozen. the plug_receive call in the loop could result
  141          * in a call back into this function refreezing the socket,
  142          * so we have to check each time.
  143          */
  144         while (!ps->freeze && bufchain_size(&ps->pending_input_data) > 0) {
  145             char databuf[512];
  146             ptrlen data = bufchain_prefix(&ps->pending_input_data);
  147             if (data.len > lenof(databuf))
  148                 data.len = lenof(databuf);
  149             memcpy(databuf, data.ptr, data.len);
  150             bufchain_consume(&ps->pending_input_data, data.len);
  151             plug_receive(ps->plug, 0, databuf, data.len);
  152         }
  153 
  154         /* if we're still frozen, we'll have to wait for another
  155          * call from the backend to finish unbuffering the data.
  156          */
  157         if (ps->freeze) return;
  158     }
  159 
  160     sk_set_frozen(ps->sub_socket, is_frozen);
  161 }
  162 
  163 static const char * sk_proxy_socket_error (Socket *s)
  164 {
  165     ProxySocket *ps = container_of(s, ProxySocket, sock);
  166     if (ps->error != NULL || ps->sub_socket == NULL) {
  167         return ps->error;
  168     }
  169     return sk_socket_error(ps->sub_socket);
  170 }
  171 
  172 /* basic proxy plug functions */
  173 
  174 static void plug_proxy_log(Plug *plug, int type, SockAddr *addr, int port,
  175                            const char *error_msg, int error_code)
  176 {
  177     ProxySocket *ps = container_of(plug, ProxySocket, plugimpl);
  178 
  179     plug_log(ps->plug, type, addr, port, error_msg, error_code);
  180 }
  181 
  182 static void plug_proxy_closing (Plug *p, const char *error_msg,
  183                                 int error_code, bool calling_back)
  184 {
  185     ProxySocket *ps = container_of(p, ProxySocket, plugimpl);
  186 
  187     if (ps->state != PROXY_STATE_ACTIVE) {
  188         ps->closing_error_msg = error_msg;
  189         ps->closing_error_code = error_code;
  190         ps->closing_calling_back = calling_back;
  191         ps->negotiate(ps, PROXY_CHANGE_CLOSING);
  192     } else {
  193         plug_closing(ps->plug, error_msg, error_code, calling_back);
  194     }
  195 }
  196 
  197 static void plug_proxy_receive(
  198     Plug *p, int urgent, const char *data, size_t len)
  199 {
  200     ProxySocket *ps = container_of(p, ProxySocket, plugimpl);
  201 
  202     if (ps->state != PROXY_STATE_ACTIVE) {
  203         /* we will lose the urgentness of this data, but since most,
  204          * if not all, of this data will be consumed by the negotiation
  205          * process, hopefully it won't affect the protocol above us
  206          */
  207         bufchain_add(&ps->pending_input_data, data, len);
  208         ps->receive_urgent = (urgent != 0);
  209         ps->receive_data = data;
  210         ps->receive_len = len;
  211         ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
  212     } else {
  213         plug_receive(ps->plug, urgent, data, len);
  214     }
  215 }
  216 
  217 static void plug_proxy_sent (Plug *p, size_t bufsize)
  218 {
  219     ProxySocket *ps = container_of(p, ProxySocket, plugimpl);
  220 
  221     if (ps->state != PROXY_STATE_ACTIVE) {
  222         ps->negotiate(ps, PROXY_CHANGE_SENT);
  223         return;
  224     }
  225     plug_sent(ps->plug, bufsize);
  226 }
  227 
  228 static int plug_proxy_accepting(Plug *p,
  229                                 accept_fn_t constructor, accept_ctx_t ctx)
  230 {
  231     ProxySocket *ps = container_of(p, ProxySocket, plugimpl);
  232 
  233     if (ps->state != PROXY_STATE_ACTIVE) {
  234         ps->accepting_constructor = constructor;
  235         ps->accepting_ctx = ctx;
  236         return ps->negotiate(ps, PROXY_CHANGE_ACCEPTING);
  237     }
  238     return plug_accepting(ps->plug, constructor, ctx);
  239 }
  240 
  241 /*
  242  * This function can accept a NULL pointer as `addr', in which case
  243  * it will only check the host name.
  244  */
  245 static bool proxy_for_destination(SockAddr *addr, const char *hostname,
  246                                   int port, Conf *conf)
  247 {
  248     int s = 0, e = 0;
  249     char hostip[64];
  250     int hostip_len, hostname_len;
  251     const char *exclude_list;
  252 
  253     /*
  254      * Special local connections such as Unix-domain sockets
  255      * unconditionally cannot be proxied, even in proxy-localhost
  256      * mode. There just isn't any way to ask any known proxy type for
  257      * them.
  258      */
  259     if (addr && sk_address_is_special_local(addr))
  260         return false;                  /* do not proxy */
  261 
  262     /*
  263      * Check the host name and IP against the hard-coded
  264      * representations of `localhost'.
  265      */
  266     if (!conf_get_bool(conf, CONF_even_proxy_localhost) &&
  267         (sk_hostname_is_local(hostname) ||
  268          (addr && sk_address_is_local(addr))))
  269         return false;                  /* do not proxy */
  270 
  271     /* we want a string representation of the IP address for comparisons */
  272     if (addr) {
  273         sk_getaddr(addr, hostip, 64);
  274         hostip_len = strlen(hostip);
  275     } else
  276         hostip_len = 0;                /* placate gcc; shouldn't be required */
  277 
  278     hostname_len = strlen(hostname);
  279 
  280     exclude_list = conf_get_str(conf, CONF_proxy_exclude_list);
  281 
  282     /* now parse the exclude list, and see if either our IP
  283      * or hostname matches anything in it.
  284      */
  285 
  286     while (exclude_list[s]) {
  287         while (exclude_list[s] &&
  288                (isspace((unsigned char)exclude_list[s]) ||
  289                 exclude_list[s] == ',')) s++;
  290 
  291         if (!exclude_list[s]) break;
  292 
  293         e = s;
  294 
  295         while (exclude_list[e] &&
  296                (isalnum((unsigned char)exclude_list[e]) ||
  297                 exclude_list[e] == '-' ||
  298                 exclude_list[e] == '.' ||
  299                 exclude_list[e] == '*')) e++;
  300 
  301         if (exclude_list[s] == '*') {
  302             /* wildcard at beginning of entry */
  303 
  304             if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),
  305                                   exclude_list + s + 1, e - s - 1) == 0) ||
  306                 strnicmp(hostname + hostname_len - (e - s - 1),
  307                          exclude_list + s + 1, e - s - 1) == 0) {
  308                 /* IP/hostname range excluded. do not use proxy. */
  309                 return false;
  310             }
  311         } else if (exclude_list[e-1] == '*') {
  312             /* wildcard at end of entry */
  313 
  314             if ((addr && strnicmp(hostip, exclude_list + s, e - s - 1) == 0) ||
  315                 strnicmp(hostname, exclude_list + s, e - s - 1) == 0) {
  316                 /* IP/hostname range excluded. do not use proxy. */
  317                 return false;
  318             }
  319         } else {
  320             /* no wildcard at either end, so let's try an absolute
  321              * match (ie. a specific IP)
  322              */
  323 
  324             if (addr && strnicmp(hostip, exclude_list + s, e - s) == 0)
  325                 return false; /* IP/hostname excluded. do not use proxy. */
  326             if (strnicmp(hostname, exclude_list + s, e - s) == 0)
  327                 return false; /* IP/hostname excluded. do not use proxy. */
  328         }
  329 
  330         s = e;
  331 
  332         /* Make sure we really have reached the next comma or end-of-string */
  333         while (exclude_list[s] &&
  334                !isspace((unsigned char)exclude_list[s]) &&
  335                exclude_list[s] != ',') s++;
  336     }
  337 
  338     /* no matches in the exclude list, so use the proxy */
  339     return true;
  340 }
  341 
  342 static char *dns_log_msg(const char *host, int addressfamily,
  343                          const char *reason)
  344 {
  345     return dupprintf("Looking up host \"%s\"%s for %s", host,
  346                      (addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
  347                       addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
  348                       ""), reason);
  349 }
  350 
  351 SockAddr *name_lookup(const char *host, int port, char **canonicalname,
  352                      Conf *conf, int addressfamily, LogContext *logctx,
  353                      const char *reason)
  354 {
  355     if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
  356         do_proxy_dns(conf) &&
  357         proxy_for_destination(NULL, host, port, conf)) {
  358 
  359         if (logctx)
  360             logeventf(logctx, "Leaving host lookup to proxy of \"%s\""
  361                       " (for %s)", host, reason);
  362 
  363         *canonicalname = dupstr(host);
  364         return sk_nonamelookup(host);
  365     } else {
  366         if (logctx)
  367             logevent_and_free(
  368                 logctx, dns_log_msg(host, addressfamily, reason));
  369 
  370         return sk_namelookup(host, canonicalname, addressfamily);
  371     }
  372 }
  373 
  374 static const struct SocketVtable ProxySocket_sockvt = {
  375     sk_proxy_plug,
  376     sk_proxy_close,
  377     sk_proxy_write,
  378     sk_proxy_write_oob,
  379     sk_proxy_write_eof,
  380     sk_proxy_set_frozen,
  381     sk_proxy_socket_error,
  382     NULL, /* peer_info */
  383 };
  384 
  385 static const struct PlugVtable ProxySocket_plugvt = {
  386     plug_proxy_log,
  387     plug_proxy_closing,
  388     plug_proxy_receive,
  389     plug_proxy_sent,
  390     plug_proxy_accepting
  391 };
  392 
  393 Socket *new_connection(SockAddr *addr, const char *hostname,
  394                        int port, bool privport,
  395                        bool oobinline, bool nodelay, bool keepalive,
  396                        Plug *plug, Conf *conf)
  397 {
  398     if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
  399         proxy_for_destination(addr, hostname, port, conf))
  400     {
  401         ProxySocket *ret;
  402         SockAddr *proxy_addr;
  403         char *proxy_canonical_name;
  404         const char *proxy_type;
  405         Socket *sret;
  406         int type;
  407 
  408         if ((sret = platform_new_connection(addr, hostname, port, privport,
  409                                             oobinline, nodelay, keepalive,
  410                                             plug, conf)) !=
  411             NULL)
  412             return sret;
  413 
  414         ret = snew(ProxySocket);
  415         ret->sock.vt = &ProxySocket_sockvt;
  416         ret->plugimpl.vt = &ProxySocket_plugvt;
  417         ret->conf = conf_copy(conf);
  418         ret->plug = plug;
  419         ret->remote_addr = addr;       /* will need to be freed on close */
  420         ret->remote_port = port;
  421 
  422         ret->error = NULL;
  423         ret->pending_eof = false;
  424         ret->freeze = false;
  425 
  426         bufchain_init(&ret->pending_input_data);
  427         bufchain_init(&ret->pending_output_data);
  428         bufchain_init(&ret->pending_oob_output_data);
  429 
  430         ret->sub_socket = NULL;
  431         ret->state = PROXY_STATE_NEW;
  432         ret->negotiate = NULL;
  433 
  434         type = conf_get_int(conf, CONF_proxy_type);
  435         if (type == PROXY_HTTP) {
  436             ret->negotiate = proxy_http_negotiate;
  437             proxy_type = "HTTP";
  438         } else if (type == PROXY_SOCKS4) {
  439             ret->negotiate = proxy_socks4_negotiate;
  440             proxy_type = "SOCKS 4";
  441         } else if (type == PROXY_SOCKS5) {
  442             ret->negotiate = proxy_socks5_negotiate;
  443             proxy_type = "SOCKS 5";
  444         } else if (type == PROXY_TELNET) {
  445             ret->negotiate = proxy_telnet_negotiate;
  446             proxy_type = "Telnet";
  447         } else {
  448             ret->error = "Proxy error: Unknown proxy method";
  449             return &ret->sock;
  450         }
  451 
  452         {
  453             char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect"
  454                                       " to %s:%d", proxy_type,
  455                                       conf_get_str(conf, CONF_proxy_host),
  456                                       conf_get_int(conf, CONF_proxy_port),
  457                                       hostname, port);
  458             plug_log(plug, 2, NULL, 0, logmsg, 0);
  459             sfree(logmsg);
  460         }
  461 
  462         {
  463             char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host),
  464                                        conf_get_int(conf, CONF_addressfamily),
  465                                        "proxy");
  466             plug_log(plug, 2, NULL, 0, logmsg, 0);
  467             sfree(logmsg);
  468         }
  469 
  470         /* look-up proxy */
  471         proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host),
  472                                    &proxy_canonical_name,
  473                                    conf_get_int(conf, CONF_addressfamily));
  474         if (sk_addr_error(proxy_addr) != NULL) {
  475             ret->error = "Proxy error: Unable to resolve proxy host name";
  476             sk_addr_free(proxy_addr);
  477             return &ret->sock;
  478         }
  479         sfree(proxy_canonical_name);
  480 
  481         {
  482             char addrbuf[256], *logmsg;
  483             sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf));
  484             logmsg = dupprintf("Connecting to %s proxy at %s port %d",
  485                                proxy_type, addrbuf,
  486                                conf_get_int(conf, CONF_proxy_port));
  487             plug_log(plug, 2, NULL, 0, logmsg, 0);
  488             sfree(logmsg);
  489         }
  490 
  491         /* create the actual socket we will be using,
  492          * connected to our proxy server and port.
  493          */
  494         ret->sub_socket = sk_new(proxy_addr,
  495                                  conf_get_int(conf, CONF_proxy_port),
  496                                  privport, oobinline,
  497                                  nodelay, keepalive, &ret->plugimpl);
  498         if (sk_socket_error(ret->sub_socket) != NULL)
  499             return &ret->sock;
  500 
  501         /* start the proxy negotiation process... */
  502         sk_set_frozen(ret->sub_socket, 0);
  503         ret->negotiate(ret, PROXY_CHANGE_NEW);
  504 
  505         return &ret->sock;
  506     }
  507 
  508     /* no proxy, so just return the direct socket */
  509     return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug);
  510 }
  511 
  512 Socket *new_listener(const char *srcaddr, int port, Plug *plug,
  513                      bool local_host_only, Conf *conf, int addressfamily)
  514 {
  515     /* TODO: SOCKS (and potentially others) support inbound
  516      * TODO: connections via the proxy. support them.
  517      */
  518 
  519     return sk_newlistener(srcaddr, port, plug, local_host_only, addressfamily);
  520 }
  521 
  522 /* ----------------------------------------------------------------------
  523  * HTTP CONNECT proxy type.
  524  */
  525 
  526 static bool get_line_end(char *data, size_t len, size_t *out)
  527 {
  528     size_t off = 0;
  529 
  530     while (off < len)
  531     {
  532         if (data[off] == '\n') {
  533             /* we have a newline */
  534             off++;
  535 
  536             /* is that the only thing on this line? */
  537             if (off <= 2) {
  538                 *out = off;
  539                 return true;
  540             }
  541 
  542             /* if not, then there is the possibility that this header
  543              * continues onto the next line, if it starts with a space
  544              * or a tab.
  545              */
  546 
  547             if (off + 1 < len && data[off+1] != ' ' && data[off+1] != '\t') {
  548                 *out = off;
  549                 return true;
  550             }
  551 
  552             /* the line does continue, so we have to keep going
  553              * until we see an the header's "real" end of line.
  554              */
  555             off++;
  556         }
  557 
  558         off++;
  559     }
  560 
  561     return false;
  562 }
  563 
  564 int proxy_http_negotiate (ProxySocket *p, int change)
  565 {
  566     if (p->state == PROXY_STATE_NEW) {
  567         /* we are just beginning the proxy negotiate process,
  568          * so we'll send off the initial bits of the request.
  569          * for this proxy method, it's just a simple HTTP
  570          * request
  571          */
  572         char *buf, dest[512];
  573         char *username, *password;
  574 
  575         sk_getaddr(p->remote_addr, dest, lenof(dest));
  576 
  577         buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",
  578                         dest, p->remote_port, dest, p->remote_port);
  579         sk_write(p->sub_socket, buf, strlen(buf));
  580         sfree(buf);
  581 
  582         username = conf_get_str(p->conf, CONF_proxy_username);
  583         password = conf_get_str(p->conf, CONF_proxy_password);
  584         if (username[0] || password[0]) {
  585             char *buf, *buf2;
  586             int i, j, len;
  587             buf = dupprintf("%s:%s", username, password);
  588             len = strlen(buf);
  589             buf2 = snewn(len * 4 / 3 + 100, char);
  590             sprintf(buf2, "Proxy-Authorization: Basic ");
  591             for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)
  592                 base64_encode_atom((unsigned char *)(buf+i),
  593                                    (len-i > 3 ? 3 : len-i), buf2+j);
  594             strcpy(buf2+j, "\r\n");
  595             sk_write(p->sub_socket, buf2, strlen(buf2));
  596             sfree(buf);
  597             sfree(buf2);
  598         }
  599 
  600         sk_write(p->sub_socket, "\r\n", 2);
  601 
  602         p->state = 1;
  603         return 0;
  604     }
  605 
  606     if (change == PROXY_CHANGE_CLOSING) {
  607         /* if our proxy negotiation process involves closing and opening
  608          * new sockets, then we would want to intercept this closing
  609          * callback when we were expecting it. if we aren't anticipating
  610          * a socket close, then some error must have occurred. we'll
  611          * just pass those errors up to the backend.
  612          */
  613         plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
  614                      p->closing_calling_back);
  615         return 0; /* ignored */
  616     }
  617 
  618     if (change == PROXY_CHANGE_SENT) {
  619         /* some (or all) of what we wrote to the proxy was sent.
  620          * we don't do anything new, however, until we receive the
  621          * proxy's response. we might want to set a timer so we can
  622          * timeout the proxy negotiation after a while...
  623          */
  624         return 0;
  625     }
  626 
  627     if (change == PROXY_CHANGE_ACCEPTING) {
  628         /* we should _never_ see this, as we are using our socket to
  629          * connect to a proxy, not accepting inbound connections.
  630          * what should we do? close the socket with an appropriate
  631          * error message?
  632          */
  633         return plug_accepting(p->plug,
  634                               p->accepting_constructor, p->accepting_ctx);
  635     }
  636 
  637     if (change == PROXY_CHANGE_RECEIVE) {
  638         /* we have received data from the underlying socket, which
  639          * we'll need to parse, process, and respond to appropriately.
  640          */
  641 
  642         char *data, *datap;
  643         size_t len, eol;
  644 
  645         if (p->state == 1) {
  646 
  647             int min_ver, maj_ver, status;
  648 
  649             /* get the status line */
  650             len = bufchain_size(&p->pending_input_data);
  651             assert(len > 0);           /* or we wouldn't be here */
  652             data = snewn(len+1, char);
  653             bufchain_fetch(&p->pending_input_data, data, len);
  654             /*
  655              * We must NUL-terminate this data, because Windows
  656              * sscanf appears to require a NUL at the end of the
  657              * string because it strlens it _first_. Sigh.
  658              */
  659             data[len] = '\0';
  660 
  661             if (!get_line_end(data, len, &eol)) {
  662                 sfree(data);
  663                 return 1;
  664             }
  665 
  666             status = -1;
  667             /* We can't rely on whether the %n incremented the sscanf return */
  668             if (sscanf((char *)data, "HTTP/%i.%i %n",
  669                        &maj_ver, &min_ver, &status) < 2 || status == -1) {
  670                 plug_closing(p->plug, "Proxy error: HTTP response was absent",
  671                              PROXY_ERROR_GENERAL, 0);
  672                 sfree(data);
  673                 return 1;
  674             }
  675 
  676             /* remove the status line from the input buffer. */
  677             bufchain_consume(&p->pending_input_data, eol);
  678             if (data[status] != '2') {
  679                 /* error */
  680                 char *buf;
  681                 data[eol] = '\0';
  682                 while (eol > status &&
  683                        (data[eol-1] == '\r' || data[eol-1] == '\n'))
  684                     data[--eol] = '\0';
  685                 buf = dupprintf("Proxy error: %s", data+status);
  686                 plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);
  687                 sfree(buf);
  688                 sfree(data);
  689                 return 1;
  690             }
  691 
  692             sfree(data);
  693 
  694             p->state = 2;
  695         }
  696 
  697         if (p->state == 2) {
  698 
  699             /* get headers. we're done when we get a
  700              * header of length 2, (ie. just "\r\n")
  701              */
  702 
  703             len = bufchain_size(&p->pending_input_data);
  704             assert(len > 0);           /* or we wouldn't be here */
  705             data = snewn(len, char);
  706             datap = data;
  707             bufchain_fetch(&p->pending_input_data, data, len);
  708 
  709             if (!get_line_end(datap, len, &eol)) {
  710                 sfree(data);
  711                 return 1;
  712             }
  713             while (eol > 2) {
  714                 bufchain_consume(&p->pending_input_data, eol);
  715                 datap += eol;
  716                 len   -= eol;
  717                 if (!get_line_end(datap, len, &eol))
  718                     eol = 0;           /* terminate the loop */
  719             }
  720 
  721             if (eol == 2) {
  722                 /* we're done */
  723                 bufchain_consume(&p->pending_input_data, 2);
  724                 proxy_activate(p);
  725                 /* proxy activate will have dealt with
  726                  * whatever is left of the buffer */
  727                 sfree(data);
  728                 return 1;
  729             }
  730 
  731             sfree(data);
  732             return 1;
  733         }
  734     }
  735 
  736     plug_closing(p->plug, "Proxy error: unexpected proxy error",
  737                  PROXY_ERROR_UNEXPECTED, 0);
  738     return 1;
  739 }
  740 
  741 /* ----------------------------------------------------------------------
  742  * SOCKS proxy type.
  743  */
  744 
  745 /* SOCKS version 4 */
  746 int proxy_socks4_negotiate (ProxySocket *p, int change)
  747 {
  748     if (p->state == PROXY_CHANGE_NEW) {
  749 
  750         /* request format:
  751          *  version number (1 byte) = 4
  752          *  command code (1 byte)
  753          *    1 = CONNECT
  754          *    2 = BIND
  755          *  dest. port (2 bytes) [network order]
  756          *  dest. address (4 bytes)
  757          *  user ID (variable length, null terminated string)
  758          */
  759 
  760         strbuf *command = strbuf_new();
  761         char hostname[512];
  762         bool write_hostname = false;
  763 
  764         put_byte(command, 4);          /* SOCKS version 4 */
  765         put_byte(command, 1);          /* CONNECT command */
  766         put_uint16(command, p->remote_port);
  767 
  768         switch (sk_addrtype(p->remote_addr)) {
  769           case ADDRTYPE_IPV4:
  770             {
  771                 char addr[4];
  772                 sk_addrcopy(p->remote_addr, addr);
  773                 put_data(command, addr, 4);
  774                 break;
  775             }
  776           case ADDRTYPE_NAME:
  777             sk_getaddr(p->remote_addr, hostname, lenof(hostname));
  778             put_uint32(command, 1);
  779             write_hostname = true;
  780             break;
  781           case ADDRTYPE_IPV6:
  782             p->error = "Proxy error: SOCKS version 4 does not support IPv6";
  783             strbuf_free(command);
  784             return 1;
  785         }
  786 
  787         put_asciz(command, conf_get_str(p->conf, CONF_proxy_username));
  788         if (write_hostname)
  789             put_asciz(command, hostname);
  790         sk_write(p->sub_socket, command->s, command->len);
  791         strbuf_free(command);
  792 
  793         p->state = 1;
  794         return 0;
  795     }
  796 
  797     if (change == PROXY_CHANGE_CLOSING) {
  798         /* if our proxy negotiation process involves closing and opening
  799          * new sockets, then we would want to intercept this closing
  800          * callback when we were expecting it. if we aren't anticipating
  801          * a socket close, then some error must have occurred. we'll
  802          * just pass those errors up to the backend.
  803          */
  804         plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
  805                      p->closing_calling_back);
  806         return 0; /* ignored */
  807     }
  808 
  809     if (change == PROXY_CHANGE_SENT) {
  810         /* some (or all) of what we wrote to the proxy was sent.
  811          * we don't do anything new, however, until we receive the
  812          * proxy's response. we might want to set a timer so we can
  813          * timeout the proxy negotiation after a while...
  814          */
  815         return 0;
  816     }
  817 
  818     if (change == PROXY_CHANGE_ACCEPTING) {
  819         /* we should _never_ see this, as we are using our socket to
  820          * connect to a proxy, not accepting inbound connections.
  821          * what should we do? close the socket with an appropriate
  822          * error message?
  823          */
  824         return plug_accepting(p->plug,
  825                               p->accepting_constructor, p->accepting_ctx);
  826     }
  827 
  828     if (change == PROXY_CHANGE_RECEIVE) {
  829         /* we have received data from the underlying socket, which
  830          * we'll need to parse, process, and respond to appropriately.
  831          */
  832 
  833         if (p->state == 1) {
  834             /* response format:
  835              *  version number (1 byte) = 4
  836              *  reply code (1 byte)
  837              *    90 = request granted
  838              *    91 = request rejected or failed
  839              *    92 = request rejected due to lack of IDENTD on client
  840              *    93 = request rejected due to difference in user ID
  841              *         (what we sent vs. what IDENTD said)
  842              *  dest. port (2 bytes)
  843              *  dest. address (4 bytes)
  844              */
  845 
  846             char data[8];
  847 
  848             if (bufchain_size(&p->pending_input_data) < 8)
  849                 return 1;              /* not got anything yet */
  850 
  851             /* get the response */
  852             bufchain_fetch(&p->pending_input_data, data, 8);
  853 
  854             if (data[0] != 0) {
  855                 plug_closing(p->plug, "Proxy error: SOCKS proxy responded with "
  856                                       "unexpected reply code version",
  857                              PROXY_ERROR_GENERAL, 0);
  858                 return 1;
  859             }
  860 
  861             if (data[1] != 90) {
  862 
  863                 switch (data[1]) {
  864                   case 92:
  865                     plug_closing(p->plug, "Proxy error: SOCKS server wanted IDENTD on client",
  866                                  PROXY_ERROR_GENERAL, 0);
  867                     break;
  868                   case 93:
  869                     plug_closing(p->plug, "Proxy error: Username and IDENTD on client don't agree",
  870                                  PROXY_ERROR_GENERAL, 0);
  871                     break;
  872                   case 91:
  873                   default:
  874                     plug_closing(p->plug, "Proxy error: Error while communicating with proxy",
  875                                  PROXY_ERROR_GENERAL, 0);
  876                     break;
  877                 }
  878 
  879                 return 1;
  880             }
  881             bufchain_consume(&p->pending_input_data, 8);
  882 
  883             /* we're done */
  884             proxy_activate(p);
  885             /* proxy activate will have dealt with
  886              * whatever is left of the buffer */
  887             return 1;
  888         }
  889     }
  890 
  891     plug_closing(p->plug, "Proxy error: unexpected proxy error",
  892                  PROXY_ERROR_UNEXPECTED, 0);
  893     return 1;
  894 }
  895 
  896 /* SOCKS version 5 */
  897 int proxy_socks5_negotiate (ProxySocket *p, int change)
  898 {
  899     if (p->state == PROXY_CHANGE_NEW) {
  900 
  901         /* initial command:
  902          *  version number (1 byte) = 5
  903          *  number of available authentication methods (1 byte)
  904          *  available authentication methods (1 byte * previous value)
  905          *    authentication methods:
  906          *     0x00 = no authentication
  907          *     0x01 = GSSAPI
  908          *     0x02 = username/password
  909          *     0x03 = CHAP
  910          */
  911 
  912         strbuf *command;
  913         char *username, *password;
  914         int method_count_offset, methods_start;
  915 
  916         command = strbuf_new();
  917         put_byte(command, 5);          /* SOCKS version 5 */
  918         username = conf_get_str(p->conf, CONF_proxy_username);
  919         password = conf_get_str(p->conf, CONF_proxy_password);
  920 
  921         method_count_offset = command->len;
  922         put_byte(command, 0);
  923         methods_start = command->len;
  924 
  925         put_byte(command, 0x00);       /* no authentication */
  926 
  927         if (username[0] || password[0]) {
  928             proxy_socks5_offerencryptedauth(BinarySink_UPCAST(command));
  929             put_byte(command, 0x02);    /* username/password */
  930         }
  931 
  932         command->u[method_count_offset] = command->len - methods_start;
  933 
  934         sk_write(p->sub_socket, command->s, command->len);
  935         strbuf_free(command);
  936 
  937         p->state = 1;
  938         return 0;
  939     }
  940 
  941     if (change == PROXY_CHANGE_CLOSING) {
  942         /* if our proxy negotiation process involves closing and opening
  943          * new sockets, then we would want to intercept this closing
  944          * callback when we were expecting it. if we aren't anticipating
  945          * a socket close, then some error must have occurred. we'll
  946          * just pass those errors up to the backend.
  947          */
  948         plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
  949                      p->closing_calling_back);
  950         return 0; /* ignored */
  951     }
  952 
  953     if (change == PROXY_CHANGE_SENT) {
  954         /* some (or all) of what we wrote to the proxy was sent.
  955          * we don't do anything new, however, until we receive the
  956          * proxy's response. we might want to set a timer so we can
  957          * timeout the proxy negotiation after a while...
  958          */
  959         return 0;
  960     }
  961 
  962     if (change == PROXY_CHANGE_ACCEPTING) {
  963         /* we should _never_ see this, as we are using our socket to
  964          * connect to a proxy, not accepting inbound connections.
  965          * what should we do? close the socket with an appropriate
  966          * error message?
  967          */
  968         return plug_accepting(p->plug,
  969                               p->accepting_constructor, p->accepting_ctx);
  970     }
  971 
  972     if (change == PROXY_CHANGE_RECEIVE) {
  973         /* we have received data from the underlying socket, which
  974          * we'll need to parse, process, and respond to appropriately.
  975          */
  976 
  977         if (p->state == 1) {
  978 
  979             /* initial response:
  980              *  version number (1 byte) = 5
  981              *  authentication method (1 byte)
  982              *    authentication methods:
  983              *     0x00 = no authentication
  984              *     0x01 = GSSAPI
  985              *     0x02 = username/password
  986              *     0x03 = CHAP
  987              *     0xff = no acceptable methods
  988              */
  989             char data[2];
  990 
  991             if (bufchain_size(&p->pending_input_data) < 2)
  992                 return 1;              /* not got anything yet */
  993 
  994             /* get the response */
  995             bufchain_fetch(&p->pending_input_data, data, 2);
  996 
  997             if (data[0] != 5) {
  998                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned unexpected version",
  999                              PROXY_ERROR_GENERAL, 0);
 1000                 return 1;
 1001             }
 1002 
 1003             if (data[1] == 0x00) p->state = 2; /* no authentication needed */
 1004             else if (data[1] == 0x01) p->state = 4; /* GSSAPI authentication */
 1005             else if (data[1] == 0x02) p->state = 5; /* username/password authentication */
 1006             else if (data[1] == 0x03) p->state = 6; /* CHAP authentication */
 1007             else {
 1008                 plug_closing(p->plug, "Proxy error: SOCKS proxy did not accept our authentication",
 1009                              PROXY_ERROR_GENERAL, 0);
 1010                 return 1;
 1011             }
 1012             bufchain_consume(&p->pending_input_data, 2);
 1013         }
 1014 
 1015         if (p->state == 7) {
 1016 
 1017             /* password authentication reply format:
 1018              *  version number (1 bytes) = 1
 1019              *  reply code (1 byte)
 1020              *    0 = succeeded
 1021              *    >0 = failed
 1022              */
 1023             char data[2];
 1024 
 1025             if (bufchain_size(&p->pending_input_data) < 2)
 1026                 return 1;              /* not got anything yet */
 1027 
 1028             /* get the response */
 1029             bufchain_fetch(&p->pending_input_data, data, 2);
 1030 
 1031             if (data[0] != 1) {
 1032                 plug_closing(p->plug, "Proxy error: SOCKS password "
 1033                              "subnegotiation contained wrong version number",
 1034                              PROXY_ERROR_GENERAL, 0);
 1035                 return 1;
 1036             }
 1037 
 1038             if (data[1] != 0) {
 1039 
 1040                 plug_closing(p->plug, "Proxy error: SOCKS proxy refused"
 1041                              " password authentication",
 1042                              PROXY_ERROR_GENERAL, 0);
 1043                 return 1;
 1044             }
 1045 
 1046             bufchain_consume(&p->pending_input_data, 2);
 1047             p->state = 2;              /* now proceed as authenticated */
 1048         }
 1049 
 1050         if (p->state == 8) {
 1051             int ret;
 1052             ret = proxy_socks5_handlechap(p);
 1053             if (ret) return ret;
 1054         }
 1055 
 1056         if (p->state == 2) {
 1057 
 1058             /* request format:
 1059              *  version number (1 byte) = 5
 1060              *  command code (1 byte)
 1061              *    1 = CONNECT
 1062              *    2 = BIND
 1063              *    3 = UDP ASSOCIATE
 1064              *  reserved (1 byte) = 0x00
 1065              *  address type (1 byte)
 1066              *    1 = IPv4
 1067              *    3 = domainname (first byte has length, no terminating null)
 1068              *    4 = IPv6
 1069              *  dest. address (variable)
 1070              *  dest. port (2 bytes) [network order]
 1071              */
 1072 
 1073             strbuf *command = strbuf_new();
 1074             put_byte(command, 5);      /* SOCKS version 5 */
 1075             put_byte(command, 1);      /* CONNECT command */
 1076             put_byte(command, 0x00);   /* reserved byte */
 1077 
 1078             switch (sk_addrtype(p->remote_addr)) {
 1079               case ADDRTYPE_IPV4:
 1080                 put_byte(command, 1);  /* IPv4 */
 1081                 sk_addrcopy(p->remote_addr, strbuf_append(command, 4));
 1082                 break;
 1083               case ADDRTYPE_IPV6:
 1084                 put_byte(command, 4);  /* IPv6 */
 1085                 sk_addrcopy(p->remote_addr, strbuf_append(command, 16));
 1086                 break;
 1087               case ADDRTYPE_NAME:
 1088                 {
 1089                     char hostname[512];
 1090                     put_byte(command, 3);  /* domain name */
 1091                     sk_getaddr(p->remote_addr, hostname, lenof(hostname));
 1092                     if (!put_pstring(command, hostname)) {
 1093                         p->error = "Proxy error: SOCKS 5 cannot "
 1094                             "support host names longer than 255 chars";
 1095                         strbuf_free(command);
 1096                         return 1;
 1097                     }
 1098                 }
 1099                 break;
 1100             }
 1101 
 1102             put_uint16(command, p->remote_port);
 1103 
 1104             sk_write(p->sub_socket, command->s, command->len);
 1105 
 1106             strbuf_free(command);
 1107 
 1108             p->state = 3;
 1109             return 1;
 1110         }
 1111 
 1112         if (p->state == 3) {
 1113 
 1114             /* reply format:
 1115              *  version number (1 bytes) = 5
 1116              *  reply code (1 byte)
 1117              *    0 = succeeded
 1118              *    1 = general SOCKS server failure
 1119              *    2 = connection not allowed by ruleset
 1120              *    3 = network unreachable
 1121              *    4 = host unreachable
 1122              *    5 = connection refused
 1123              *    6 = TTL expired
 1124              *    7 = command not supported
 1125              *    8 = address type not supported
 1126              * reserved (1 byte) = x00
 1127              * address type (1 byte)
 1128              *    1 = IPv4
 1129              *    3 = domainname (first byte has length, no terminating null)
 1130              *    4 = IPv6
 1131              * server bound address (variable)
 1132              * server bound port (2 bytes) [network order]
 1133              */
 1134             char data[5];
 1135             int len;
 1136 
 1137             /* First 5 bytes of packet are enough to tell its length. */
 1138             if (bufchain_size(&p->pending_input_data) < 5)
 1139                 return 1;              /* not got anything yet */
 1140 
 1141             /* get the response */
 1142             bufchain_fetch(&p->pending_input_data, data, 5);
 1143 
 1144             if (data[0] != 5) {
 1145                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned wrong version number",
 1146                              PROXY_ERROR_GENERAL, 0);
 1147                 return 1;
 1148             }
 1149 
 1150             if (data[1] != 0) {
 1151                 char buf[256];
 1152 
 1153                 strcpy(buf, "Proxy error: ");
 1154 
 1155                 switch (data[1]) {
 1156                   case 1: strcat(buf, "General SOCKS server failure"); break;
 1157                   case 2: strcat(buf, "Connection not allowed by ruleset"); break;
 1158                   case 3: strcat(buf, "Network unreachable"); break;
 1159                   case 4: strcat(buf, "Host unreachable"); break;
 1160                   case 5: strcat(buf, "Connection refused"); break;
 1161                   case 6: strcat(buf, "TTL expired"); break;
 1162                   case 7: strcat(buf, "Command not supported"); break;
 1163                   case 8: strcat(buf, "Address type not supported"); break;
 1164                   default: sprintf(buf+strlen(buf),
 1165                                    "Unrecognised SOCKS error code %d",
 1166                                    data[1]);
 1167                     break;
 1168                 }
 1169                 plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);
 1170 
 1171                 return 1;
 1172             }
 1173 
 1174             /*
 1175              * Eat the rest of the reply packet.
 1176              */
 1177             len = 6;                   /* first 4 bytes, last 2 */
 1178             switch (data[3]) {
 1179               case 1: len += 4; break; /* IPv4 address */
 1180               case 4: len += 16; break;/* IPv6 address */
 1181               case 3: len += (unsigned char)data[4]; break; /* domain name */
 1182               default:
 1183                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned "
 1184                              "unrecognised address format",
 1185                              PROXY_ERROR_GENERAL, 0);
 1186                 return 1;
 1187             }
 1188             if (bufchain_size(&p->pending_input_data) < len)
 1189                 return 1;              /* not got whole reply yet */
 1190             bufchain_consume(&p->pending_input_data, len);
 1191 
 1192             /* we're done */
 1193             proxy_activate(p);
 1194             return 1;
 1195         }
 1196 
 1197         if (p->state == 4) {
 1198             /* TODO: Handle GSSAPI authentication */
 1199             plug_closing(p->plug, "Proxy error: We don't support GSSAPI authentication",
 1200                          PROXY_ERROR_GENERAL, 0);
 1201             return 1;
 1202         }
 1203 
 1204         if (p->state == 5) {
 1205             const char *username = conf_get_str(p->conf, CONF_proxy_username);
 1206             const char *password = conf_get_str(p->conf, CONF_proxy_password);
 1207             if (username[0] || password[0]) {
 1208                 strbuf *auth = strbuf_new_nm();
 1209                 put_byte(auth, 1); /* version number of subnegotiation */
 1210                 if (!put_pstring(auth, username)) {
 1211                     p->error = "Proxy error: SOCKS 5 authentication cannot "
 1212                         "support usernames longer than 255 chars";
 1213                     strbuf_free(auth);
 1214                     return 1;
 1215                 }
 1216                 if (!put_pstring(auth, password)) {
 1217                     p->error = "Proxy error: SOCKS 5 authentication cannot "
 1218                         "support passwords longer than 255 chars";
 1219                     strbuf_free(auth);
 1220                     return 1;
 1221                 }
 1222                 sk_write(p->sub_socket, auth->s, auth->len);
 1223                 strbuf_free(auth);
 1224                 p->state = 7;
 1225             } else
 1226                 plug_closing(p->plug, "Proxy error: Server chose "
 1227                              "username/password authentication but we "
 1228                              "didn't offer it!",
 1229                          PROXY_ERROR_GENERAL, 0);
 1230             return 1;
 1231         }
 1232 
 1233         if (p->state == 6) {
 1234             int ret;
 1235             ret = proxy_socks5_selectchap(p);
 1236             if (ret) return ret;
 1237         }
 1238 
 1239     }
 1240 
 1241     plug_closing(p->plug, "Proxy error: Unexpected proxy error",
 1242                  PROXY_ERROR_UNEXPECTED, 0);
 1243     return 1;
 1244 }
 1245 
 1246 /* ----------------------------------------------------------------------
 1247  * `Telnet' proxy type.
 1248  *
 1249  * (This is for ad-hoc proxies where you connect to the proxy's
 1250  * telnet port and send a command such as `connect host port'. The
 1251  * command is configurable, since this proxy type is typically not
 1252  * standardised or at all well-defined.)
 1253  */
 1254 
 1255 char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 1256 {
 1257     char *fmt = conf_get_str(conf, CONF_proxy_telnet_command);
 1258     int so = 0, eo = 0;
 1259     strbuf *buf = strbuf_new();
 1260 
 1261     /* we need to escape \\, \%, \r, \n, \t, \x??, \0???,
 1262      * %%, %host, %port, %user, and %pass
 1263      */
 1264 
 1265     while (fmt[eo] != 0) {
 1266 
 1267         /* scan forward until we hit end-of-line,
 1268          * or an escape character (\ or %) */
 1269         while (fmt[eo] != 0 && fmt[eo] != '%' && fmt[eo] != '\\')
 1270             eo++;
 1271 
 1272         /* if we hit eol, break out of our escaping loop */
 1273         if (fmt[eo] == 0) break;
 1274 
 1275         /* if there was any unescaped text before the escape
 1276          * character, send that now */
 1277         if (eo != so)
 1278             put_data(buf, fmt + so, eo - so);
 1279 
 1280         so = eo++;
 1281 
 1282         /* if the escape character was the last character of
 1283          * the line, we'll just stop and send it. */
 1284         if (fmt[eo] == 0) break;
 1285 
 1286         if (fmt[so] == '\\') {
 1287 
 1288             /* we recognize \\, \%, \r, \n, \t, \x??.
 1289              * anything else, we just send unescaped (including the \).
 1290              */
 1291 
 1292             switch (fmt[eo]) {
 1293 
 1294               case '\\':
 1295                 put_byte(buf, '\\');
 1296                 eo++;
 1297                 break;
 1298 
 1299               case '%':
 1300                 put_byte(buf, '%');
 1301                 eo++;
 1302                 break;
 1303 
 1304               case 'r':
 1305                 put_byte(buf, '\r');
 1306                 eo++;
 1307                 break;
 1308 
 1309               case 'n':
 1310                 put_byte(buf, '\n');
 1311                 eo++;
 1312                 break;
 1313 
 1314               case 't':
 1315                 put_byte(buf, '\t');
 1316                 eo++;
 1317                 break;
 1318 
 1319               case 'x':
 1320               case 'X':
 1321                 {
 1322                     /* escaped hexadecimal value (ie. \xff) */
 1323                     unsigned char v = 0;
 1324                     int i = 0;
 1325 
 1326                     for (;;) {
 1327                         eo++;
 1328                         if (fmt[eo] >= '0' && fmt[eo] <= '9')
 1329                             v += fmt[eo] - '0';
 1330                         else if (fmt[eo] >= 'a' && fmt[eo] <= 'f')
 1331                             v += fmt[eo] - 'a' + 10;
 1332                         else if (fmt[eo] >= 'A' && fmt[eo] <= 'F')
 1333                             v += fmt[eo] - 'A' + 10;
 1334                         else {
 1335                             /* non hex character, so we abort and just
 1336                              * send the whole thing unescaped (including \x)
 1337                              */
 1338                             put_byte(buf, '\\');
 1339                             eo = so + 1;
 1340                             break;
 1341                         }
 1342 
 1343                         /* we only extract two hex characters */
 1344                         if (i == 1) {
 1345                             put_byte(buf, v);
 1346                             eo++;
 1347                             break;
 1348                         }
 1349 
 1350                         i++;
 1351                         v <<= 4;
 1352                     }
 1353                 }
 1354                 break;
 1355 
 1356               default:
 1357                 put_data(buf, fmt + so, 2);
 1358                 eo++;
 1359                 break;
 1360             }
 1361         } else {
 1362 
 1363             /* % escape. we recognize %%, %host, %port, %user, %pass.
 1364              * %proxyhost, %proxyport. Anything else we just send
 1365              * unescaped (including the %).
 1366              */
 1367 
 1368             if (fmt[eo] == '%') {
 1369                 put_byte(buf, '%');
 1370                 eo++;
 1371             }
 1372             else if (strnicmp(fmt + eo, "host", 4) == 0) {
 1373                 char dest[512];
 1374                 sk_getaddr(addr, dest, lenof(dest));
 1375                 put_data(buf, dest, strlen(dest));
 1376                 eo += 4;
 1377             }
 1378             else if (strnicmp(fmt + eo, "port", 4) == 0) {
 1379                 strbuf_catf(buf, "%d", port);
 1380                 eo += 4;
 1381             }
 1382             else if (strnicmp(fmt + eo, "user", 4) == 0) {
 1383                 const char *username = conf_get_str(conf, CONF_proxy_username);
 1384                 put_data(buf, username, strlen(username));
 1385                 eo += 4;
 1386             }
 1387             else if (strnicmp(fmt + eo, "pass", 4) == 0) {
 1388                 const char *password = conf_get_str(conf, CONF_proxy_password);
 1389                 put_data(buf, password, strlen(password));
 1390                 eo += 4;
 1391             }
 1392             else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) {
 1393                 const char *host = conf_get_str(conf, CONF_proxy_host);
 1394                 put_data(buf, host, strlen(host));
 1395                 eo += 9;
 1396             }
 1397             else if (strnicmp(fmt + eo, "proxyport", 9) == 0) {
 1398                 int port = conf_get_int(conf, CONF_proxy_port);
 1399                 strbuf_catf(buf, "%d", port);
 1400                 eo += 9;
 1401             }
 1402             else {
 1403                 /* we don't escape this, so send the % now, and
 1404                  * don't advance eo, so that we'll consider the
 1405                  * text immediately following the % as unescaped.
 1406                  */
 1407                 put_byte(buf, '%');
 1408             }
 1409         }
 1410 
 1411         /* resume scanning for additional escapes after this one. */
 1412         so = eo;
 1413     }
 1414 
 1415     /* if there is any unescaped text at the end of the line, send it */
 1416     if (eo != so) {
 1417         put_data(buf, fmt + so, eo - so);
 1418     }
 1419 
 1420     return strbuf_to_str(buf);
 1421 }
 1422 
 1423 int proxy_telnet_negotiate (ProxySocket *p, int change)
 1424 {
 1425     if (p->state == PROXY_CHANGE_NEW) {
 1426         char *formatted_cmd;
 1427 
 1428         formatted_cmd = format_telnet_command(p->remote_addr, p->remote_port,
 1429                                               p->conf);
 1430 
 1431         {
 1432             /*
 1433              * Re-escape control chars in the command, for logging.
 1434              */
 1435             char *reescaped = snewn(4*strlen(formatted_cmd) + 1, char);
 1436             const char *in;
 1437             char *out;
 1438             char *logmsg;
 1439 
 1440             for (in = formatted_cmd, out = reescaped; *in; in++) {
 1441                 if (*in == '\n') {
 1442                     *out++ = '\\'; *out++ = 'n';
 1443                 } else if (*in == '\r') {
 1444                     *out++ = '\\'; *out++ = 'r';
 1445                 } else if (*in == '\t') {
 1446                     *out++ = '\\'; *out++ = 't';
 1447                 } else if (*in == '\\') {
 1448                     *out++ = '\\'; *out++ = '\\';
 1449                 } else if ((unsigned)(((unsigned char)*in) - 0x20) <
 1450                            (0x7F-0x20)) {
 1451                     *out++ = *in;
 1452                 } else {
 1453                     out += sprintf(out, "\\x%02X", (unsigned)*in & 0xFF);
 1454                 }
 1455             }
 1456             *out = '\0';
 1457 
 1458             logmsg = dupprintf("Sending Telnet proxy command: %s", reescaped);
 1459             plug_log(p->plug, 2, NULL, 0, logmsg, 0);
 1460             sfree(logmsg);
 1461             sfree(reescaped);
 1462         }
 1463 
 1464         sk_write(p->sub_socket, formatted_cmd, strlen(formatted_cmd));
 1465         sfree(formatted_cmd);
 1466 
 1467         p->state = 1;
 1468         return 0;
 1469     }
 1470 
 1471     if (change == PROXY_CHANGE_CLOSING) {
 1472         /* if our proxy negotiation process involves closing and opening
 1473          * new sockets, then we would want to intercept this closing
 1474          * callback when we were expecting it. if we aren't anticipating
 1475          * a socket close, then some error must have occurred. we'll
 1476          * just pass those errors up to the backend.
 1477          */
 1478         plug_closing(p->plug, p->closing_error_msg, p->closing_error_code,
 1479                      p->closing_calling_back);
 1480         return 0; /* ignored */
 1481     }
 1482 
 1483     if (change == PROXY_CHANGE_SENT) {
 1484         /* some (or all) of what we wrote to the proxy was sent.
 1485          * we don't do anything new, however, until we receive the
 1486          * proxy's response. we might want to set a timer so we can
 1487          * timeout the proxy negotiation after a while...
 1488          */
 1489         return 0;
 1490     }
 1491 
 1492     if (change == PROXY_CHANGE_ACCEPTING) {
 1493         /* we should _never_ see this, as we are using our socket to
 1494          * connect to a proxy, not accepting inbound connections.
 1495          * what should we do? close the socket with an appropriate
 1496          * error message?
 1497          */
 1498         return plug_accepting(p->plug,
 1499                               p->accepting_constructor, p->accepting_ctx);
 1500     }
 1501 
 1502     if (change == PROXY_CHANGE_RECEIVE) {
 1503         /* we have received data from the underlying socket, which
 1504          * we'll need to parse, process, and respond to appropriately.
 1505          */
 1506 
 1507         /* we're done */
 1508         proxy_activate(p);
 1509         /* proxy activate will have dealt with
 1510          * whatever is left of the buffer */
 1511         return 1;
 1512     }
 1513 
 1514     plug_closing(p->plug, "Proxy error: Unexpected proxy error",
 1515                  PROXY_ERROR_UNEXPECTED, 0);
 1516     return 1;
 1517 }