source: filezilla/trunk/fuentes/src/putty/cproxy.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

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