"Fossies" - the Fresh Open Source Software Archive

Member "putty-0.73/cproxy.c" (22 Sep 2019, 6434 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 "cproxy.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  * Routines to do cryptographic interaction with proxies in PuTTY.
    3  * This is in a separate module from proxy.c, so that it can be
    4  * conveniently removed in PuTTYtel by replacing this module with
    5  * the stub version nocproxy.c.
    6  */
    7 
    8 #include <assert.h>
    9 #include <ctype.h>
   10 #include <string.h>
   11 
   12 #include "putty.h"
   13 #include "ssh.h" /* For MD5 support */
   14 #include "network.h"
   15 #include "proxy.h"
   16 #include "marshal.h"
   17 
   18 static void hmacmd5_chap(const unsigned char *challenge, int challen,
   19                          const char *passwd, unsigned char *response)
   20 {
   21     mac_simple(&ssh_hmac_md5, ptrlen_from_asciz(passwd),
   22                make_ptrlen(challenge, challen), response);
   23 }
   24 
   25 void proxy_socks5_offerencryptedauth(BinarySink *bs)
   26 {
   27     put_byte(bs, 0x03);              /* CHAP */
   28 }
   29 
   30 int proxy_socks5_handlechap (ProxySocket *p)
   31 {
   32 
   33     /* CHAP authentication reply format:
   34      *  version number (1 bytes) = 1
   35      *  number of commands (1 byte)
   36      *
   37      * For each command:
   38      *  command identifier (1 byte)
   39      *  data length (1 byte)
   40      */
   41     unsigned char data[260];
   42     unsigned char outbuf[20];
   43 
   44     while(p->chap_num_attributes == 0 ||
   45           p->chap_num_attributes_processed < p->chap_num_attributes) {
   46         if (p->chap_num_attributes == 0 ||
   47             p->chap_current_attribute == -1) {
   48             /* CHAP normally reads in two bytes, either at the
   49              * beginning or for each attribute/value pair.  But if
   50              * we're waiting for the value's data, we might not want
   51              * to read 2 bytes.
   52              */
   53 
   54             if (bufchain_size(&p->pending_input_data) < 2)
   55                 return 1;              /* not got anything yet */
   56 
   57             /* get the response */
   58             bufchain_fetch(&p->pending_input_data, data, 2);
   59             bufchain_consume(&p->pending_input_data, 2);
   60         }
   61 
   62         if (p->chap_num_attributes == 0) {
   63             /* If there are no attributes, this is our first msg
   64              * with the server, where we negotiate version and
   65              * number of attributes
   66              */
   67             if (data[0] != 0x01) {
   68                 plug_closing(p->plug, "Proxy error: SOCKS proxy wants"
   69                              " a different CHAP version",
   70                              PROXY_ERROR_GENERAL, 0);
   71                 return 1;
   72             }
   73             if (data[1] == 0x00) {
   74                 plug_closing(p->plug, "Proxy error: SOCKS proxy won't"
   75                              " negotiate CHAP with us",
   76                              PROXY_ERROR_GENERAL, 0);
   77                 return 1;
   78             }
   79             p->chap_num_attributes = data[1];
   80         } else {
   81             if (p->chap_current_attribute == -1) {
   82                 /* We have to read in each attribute/value pair -
   83                  * those we don't understand can be ignored, but
   84                  * there are a few we'll need to handle.
   85                  */
   86                 p->chap_current_attribute = data[0];
   87                 p->chap_current_datalen = data[1];
   88             }
   89             if (bufchain_size(&p->pending_input_data) <
   90                 p->chap_current_datalen)
   91                 return 1;              /* not got everything yet */
   92 
   93             /* get the response */
   94             bufchain_fetch(&p->pending_input_data, data,
   95                            p->chap_current_datalen);
   96 
   97             bufchain_consume(&p->pending_input_data,
   98                              p->chap_current_datalen);
   99 
  100             switch (p->chap_current_attribute) {
  101               case 0x00:
  102                 /* Successful authentication */
  103                 if (data[0] == 0x00)
  104                     p->state = 2;
  105                 else {
  106                     plug_closing(p->plug, "Proxy error: SOCKS proxy"
  107                                  " refused CHAP authentication",
  108                                  PROXY_ERROR_GENERAL, 0);
  109                     return 1;
  110                 }
  111               break;
  112               case 0x03:
  113                 outbuf[0] = 0x01; /* Version */
  114                 outbuf[1] = 0x01; /* One attribute */
  115                 outbuf[2] = 0x04; /* Response */
  116                 outbuf[3] = 0x10; /* Length */
  117                 hmacmd5_chap(data, p->chap_current_datalen,
  118                              conf_get_str(p->conf, CONF_proxy_password),
  119                              &outbuf[4]);
  120                 sk_write(p->sub_socket, outbuf, 20);
  121               break;
  122               case 0x11:
  123                 /* Chose a protocol */
  124                 if (data[0] != 0x85) {
  125                     plug_closing(p->plug, "Proxy error: Server chose "
  126                                  "CHAP of other than HMAC-MD5 but we "
  127                                  "didn't offer it!",
  128                                  PROXY_ERROR_GENERAL, 0);
  129                     return 1;
  130                 }
  131               break;
  132             }
  133             p->chap_current_attribute = -1;
  134             p->chap_num_attributes_processed++;
  135         }
  136         if (p->state == 8 &&
  137             p->chap_num_attributes_processed >= p->chap_num_attributes) {
  138             p->chap_num_attributes = 0;
  139             p->chap_num_attributes_processed = 0;
  140             p->chap_current_datalen = 0;
  141         }
  142     }
  143     return 0;
  144 }
  145 
  146 int proxy_socks5_selectchap(ProxySocket *p)
  147 {
  148     char *username = conf_get_str(p->conf, CONF_proxy_username);
  149     char *password = conf_get_str(p->conf, CONF_proxy_password);
  150     if (username[0] || password[0]) {
  151         char chapbuf[514];
  152         int ulen;
  153         chapbuf[0] = '\x01'; /* Version */
  154         chapbuf[1] = '\x02'; /* Number of attributes sent */
  155         chapbuf[2] = '\x11'; /* First attribute - algorithms list */
  156         chapbuf[3] = '\x01'; /* Only one CHAP algorithm */
  157         chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
  158         chapbuf[5] = '\x02'; /* Second attribute - username */
  159 
  160         ulen = strlen(username);
  161         if (ulen > 255) ulen = 255;
  162         if (ulen < 1) ulen = 1;
  163 
  164         chapbuf[6] = ulen;
  165         memcpy(chapbuf+7, username, ulen);
  166 
  167         sk_write(p->sub_socket, chapbuf, ulen + 7);
  168         p->chap_num_attributes = 0;
  169         p->chap_num_attributes_processed = 0;
  170         p->chap_current_attribute = -1;
  171         p->chap_current_datalen = 0;
  172 
  173         p->state = 8;
  174     } else
  175         plug_closing(p->plug, "Proxy error: Server chose "
  176                      "CHAP authentication but we didn't offer it!",
  177                  PROXY_ERROR_GENERAL, 0);
  178     return 1;
  179 }