]> andersk Git - openssh.git/commitdiff
- markus@cvs.openbsd.org 2001/04/11 13:56:13
authormouring <mouring>
Wed, 11 Apr 2001 23:08:17 +0000 (23:08 +0000)
committermouring <mouring>
Wed, 11 Apr 2001 23:08:17 +0000 (23:08 +0000)
     [channels.c ssh.c]
     https-connect and socks5 support. i feel so bad.

ChangeLog
channels.c
ssh.c

index 210cf25e72e7f687fbb7dd7fb4c2a7ef8e465dde..bd87b53bc97a5b71318e95640d2b5c0364d5ee42 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,9 @@
    - markus@cvs.openbsd.org 2001/04/11 10:59:01
      [ssh.c]
      use strtol() for ports, thanks jakob@
+   - markus@cvs.openbsd.org 2001/04/11 13:56:13
+     [channels.c ssh.c]
+     https-connect and socks5 support. i feel so bad.
 
 20010410
  - OpenBSD CVS Sync
index 4283abc3ab3108c8a96fef2267dffd1f2f895773..a1aa937ae664604f67b9da1c4c9963147da840bc 100644 (file)
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.105 2001/04/10 12:15:23 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.106 2001/04/11 13:56:13 markus Exp $");
 
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
@@ -576,6 +576,39 @@ channel_decode_helper(Channel *c, int start, int lookfor)
        return 0;       /* need more */
 }
 
+/* try to decode a http connect header */
+int
+channel_decode_https(Channel *c, fd_set * readset, fd_set * writeset)
+{
+       u_char *p, *host, *buf;
+       int port, ret;
+       char httpok[] = "HTTP/1.0 200\r\n\r\n";
+
+       debug2("channel %d: decode https connect", c->self);
+       ret = channel_decode_helper(c, strlen("connect "), '\r');
+       if (ret <= 0)
+               return ret;
+       p = buffer_ptr(&c->input);
+       buf = xmalloc(ret+1);
+       host = xmalloc(ret);
+       memcpy(buf, p, ret);
+       buf[ret] = '\0';
+       if (sscanf(buf, "CONNECT %[^:]:%u HTTP/", host, &port) != 2) {
+               debug("channel %d: cannot parse http header", c->self);
+               return -1;
+       }
+       debug("channel %d: dynamic request: https host %s port %u",
+           c->self, host, port);
+       strlcpy(c->path, host, sizeof(c->path));
+       c->host_port = port;
+       xfree(host);
+       xfree(buf);
+       buffer_consume(&c->input, ret+4);
+       buffer_append(&c->output, httpok, strlen(httpok));
+
+       return 1;
+}
+
 /* try to decode a socks4 header */
 int
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
@@ -601,7 +634,7 @@ channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
        p = buffer_ptr(&c->input);
        len = strlen(p);
        have = buffer_len(&c->input);
-       debug2("channel %d: pre_dynamic: user %s/%d", c->self, p, len);
+       debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
        if (len > have)
                fatal("channel %d: decode socks4: len %d > have %d",
                    c->self, len, have);
@@ -613,10 +646,8 @@ channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
        strlcpy(c->path, host, sizeof(c->path));
        c->host_port = ntohs(s4_req.dest_port);
        
-       debug("channel %d: dynamic request: "
-           "socks%x://%s@%s:%u/command?%u",
-           c->self, s4_req.version, username, host, c->host_port,
-           s4_req.command);
+       debug("channel %d: dynamic request: socks4 host %s port %u command %u",
+           c->self, host, c->host_port, s4_req.command);
 
        if (s4_req.command != 1) {
                debug("channel %d: cannot handle: socks4 cn %d",
@@ -631,6 +662,115 @@ channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
        return 1;
 }
 
+/* try to decode a socks5 header */
+#define SSH_SOCKS5_AUTHDONE    0x1000
+#define SSH_SOCKS5_NOAUTH      0x00
+#define SSH_SOCKS5_IPV4                0x01
+#define SSH_SOCKS5_DOMAIN      0x03
+#define SSH_SOCKS5_IPV6                0x04
+#define SSH_SOCKS5_CONNECT     0x01
+#define SSH_SOCKS5_SUCCESS     0x00
+
+int
+channel_decode_socks5(Channel *c, fd_set * readset, fd_set * writeset)
+{
+       struct {
+               u_int8_t version;
+               u_int8_t command;
+               u_int8_t reserved;
+               u_int8_t atyp;
+       } s5_req, s5_rsp;
+       u_int16_t dest_port;
+       u_char *p, dest_addr[255+1];
+       int i, have, found, nmethods, addrlen, af;
+
+       debug2("channel %d: decode socks5", c->self);
+       p = buffer_ptr(&c->input);
+       if (p[0] != 0x05)
+               return -1;
+       have = buffer_len(&c->input);
+       if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
+               /* format: ver | nmethods | methods */
+               if (have < 2) 
+                       return 0;
+               nmethods = p[1];
+               if (have < nmethods + 2)
+                       return 0;
+               /* look for method: "NO AUTHENTICATION REQUIRED" */
+               for (found = 0, i = 2 ; i < nmethods + 2; i++) {
+                       if (p[i] == SSH_SOCKS5_NOAUTH ) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found) {
+                       debug("channel %d: method SSH_SOCKS5_NOAUTH not found",
+                           c->self);
+                       return -1;
+               }
+               buffer_consume(&c->input, nmethods + 2);
+               buffer_put_char(&c->output, 0x05);              /* version */
+               buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */
+               FD_SET(c->sock, writeset);
+               c->flags |= SSH_SOCKS5_AUTHDONE;
+               debug2("channel %d: socks5 auth done", c->self);
+               return 0;                               /* need more */
+       }
+       debug2("channel %d: socks5 post auth", c->self);
+       if (have < sizeof(s5_req)+1)
+               return 0;                       /* need more */
+       memcpy((char *)&s5_req, p, sizeof(s5_req));
+       if (s5_req.version != 0x05 ||
+           s5_req.command != SSH_SOCKS5_CONNECT ||
+           s5_req.reserved != 0x00) {
+               debug("channel %d: only socks5 connect supported", c->self);
+               return -1;
+       }
+       switch(s5_req.atyp){
+       case SSH_SOCKS5_IPV4:
+               addrlen = 4;
+               af = AF_INET;
+               break;
+       case SSH_SOCKS5_DOMAIN:
+               addrlen = p[sizeof(s5_req)];
+               af = -1;
+               break;
+       case SSH_SOCKS5_IPV6:
+               addrlen = 16;
+               af = AF_INET6;
+               break;
+       default:
+               debug("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp);
+               return -1;
+       }
+       if (have < 4 + addrlen + 2)
+               return 0;
+       buffer_consume(&c->input, sizeof(s5_req));
+       buffer_get(&c->input, (char *)&dest_addr, addrlen);
+       buffer_get(&c->input, (char *)&dest_port, 2);
+       dest_addr[addrlen] = '\0';
+       if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
+               strlcpy(c->path, dest_addr, sizeof(c->path));
+       else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL)
+               return -1;
+       c->host_port = ntohs(dest_port);
+       
+       debug("channel %d: dynamic request: socks5 host %s port %u command %u",
+           c->self, c->path, c->host_port, s5_req.command);
+
+       s5_rsp.version = 0x05;
+       s5_rsp.command = SSH_SOCKS5_SUCCESS;
+       s5_rsp.reserved = 0;                    /* ignored */
+       s5_rsp.atyp = SSH_SOCKS5_IPV4;
+       ((struct in_addr *)&dest_addr)->s_addr = INADDR_ANY;
+       dest_port = 0;                          /* ignored */
+
+       buffer_append(&c->output, (char *)&s5_rsp, sizeof(s5_rsp));
+       buffer_append(&c->output, (char *)&dest_addr, sizeof(struct in_addr));
+       buffer_append(&c->output, (char *)&dest_port, sizeof(dest_port));
+       return 1;
+}
+
 /* dynamic port forwarding */
 void
 channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
@@ -651,17 +791,15 @@ channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
        /* try to guess the protocol */
        p = buffer_ptr(&c->input);
        switch (p[0]) {
-       case 0x04:
-               ret = channel_decode_socks4(c, readset, writeset);
-               break;
-#if 0
        case 'C':
                ret = channel_decode_https(c, readset, writeset);
                break;
+       case 0x04:
+               ret = channel_decode_socks4(c, readset, writeset);
+               break;
        case 0x05:
                ret = channel_decode_socks5(c, readset, writeset);
                break;
-#endif
        default:
                ret = -1;
                break;
diff --git a/ssh.c b/ssh.c
index 89ced97e28d85c00051a90f0544958e1f4d40af5..5180a8d7d122bc6d7837e244df31496296628cb7 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.109 2001/04/11 10:59:01 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.110 2001/04/11 13:56:13 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -179,8 +179,9 @@ usage(void)
        fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
        fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
        fprintf(stderr, "  -D port     Dynamically forward local port to multiple remote addresses.\n");
-       fprintf(stderr, "              Allows SSH to act as an application-layer proxy.\n");
-       fprintf(stderr, "              Protocols Supported: SOCKS4\n");
+       fprintf(stderr, "              Allows %s to act as an application-layer proxy.\n",
+           __progname);
+       fprintf(stderr, "              Protocols supported: SOCKS4, SOCKS5, HTTPS\n");
        fprintf(stderr, "  -C          Enable compression.\n");
        fprintf(stderr, "  -N          Do not execute a shell or command.\n");
        fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
This page took 0.06718 seconds and 5 git commands to generate.