sk_getaddr(p->remote_addr, dest, 64);
- sprintf(buf, "CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n\r\n",
+ sprintf(buf, "CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",
dest, p->remote_port, dest, p->remote_port);
sk_write(p->sub_socket, buf, strlen(buf));
+ if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
+ char buf[sizeof(cfg.proxy_username)+sizeof(cfg.proxy_password)];
+ char buf2[sizeof(buf)*4/3 + 100];
+ int i, j, len;
+ sprintf(buf, "%s:%s", cfg.proxy_username, cfg.proxy_password);
+ len = strlen(buf);
+ sprintf(buf2, "Proxy-Authorization: basic ");
+ for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)
+ base64_encode_atom(buf+i, (len-i > 3 ? 3 : len-i), buf2+j);
+ strcpy(buf2+j, "\r\n");
+ sk_write(p->sub_socket, buf2, strlen(buf2));
+ }
+
+ sprintf(buf, "\r\n");
+ sk_write(p->sub_socket, buf, strlen(buf));
+
p->state = 1;
return 0;
}
return 1;
}
+ bufchain_consume(&p->pending_input_data, 2);
/* we're done */
proxy_activate(p);
* 0x03 = CHAP
*/
- char command[3];
+ char command[4];
+ int len;
command[0] = 5; /* version 5 */
- command[1] = 1; /* TODO: we don't currently support any auth methods */
- command[2] = 0x00; /* no authentication */
+ if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
+ command[1] = 2; /* two methods supported: */
+ command[2] = 0x00; /* no authentication */
+ command[3] = 0x02; /* username/password */
+ len = 4;
+ } else {
+ command[1] = 1; /* one methods supported: */
+ command[2] = 0x00; /* no authentication */
+ len = 3;
+ }
- sk_write(p->sub_socket, command, 3);
+ sk_write(p->sub_socket, command, len);
p->state = 1;
return 0;
PROXY_ERROR_GENERAL, 0);
return 1;
}
+ bufchain_consume(&p->pending_input_data, 2);
+ }
+
+ if (p->state == 7) {
+
+ /* password authentication reply format:
+ * version number (1 bytes) = 1
+ * reply code (1 byte)
+ * 0 = succeeded
+ * >0 = failed
+ */
+
+ /* get the response */
+ bufchain_prefix(&p->pending_input_data, &data, &len);
+
+ if (data[0] != 1) {
+ plug_closing(p->plug, "Network error: Error while communicating with proxy",
+ PROXY_ERROR_GENERAL, 0);
+ return 1;
+ }
+
+ if (data[1] != 0) {
+
+ plug_closing(p->plug, "Network error: Proxy refused authentication",
+ PROXY_ERROR_GENERAL, 0);
+ return 1;
+ }
+
+ bufchain_consume(&p->pending_input_data, 2);
+ p->state = 2; /* now proceed as authenticated */
}
if (p->state == 2) {
}
if (p->state == 5) {
- /* TODO: Handle username/password authentication */
- plug_closing(p->plug, "Network error: We don't support username/password "
- "authentication",
+ if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
+ char userpwbuf[514];
+ int ulen, plen;
+ ulen = strlen(cfg.proxy_username);
+ if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;
+ plen = strlen(cfg.proxy_password);
+ if (plen > 255) plen = 255; if (plen < 1) plen = 1;
+ userpwbuf[0] = 1; /* version number of subnegotiation */
+ userpwbuf[1] = ulen;
+ memcpy(userpwbuf+2, cfg.proxy_username, ulen);
+ userpwbuf[ulen+2] = plen;
+ memcpy(userpwbuf+ulen+3, cfg.proxy_password, plen);
+ sk_write(p->sub_socket, userpwbuf, ulen + plen + 3);
+ p->state = 7;
+ } else
+ plug_closing(p->plug, "Network error: Server chose "
+ "username/password authentication but we "
+ "didn't offer it!",
PROXY_ERROR_GENERAL, 0);
return 1;
}
PROXY_ERROR_GENERAL, 0);
return 1;
}
+
}
plug_closing(p->plug, "Network error: Unexpected proxy error",