[BACK]Return to channels.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/channels.c between version 1.105 and 1.106

version 1.105, 2001/04/10 12:15:23 version 1.106, 2001/04/11 13:56:13
Line 576 
Line 576 
         return 0;       /* need more */          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 */  /* try to decode a socks4 header */
 int  int
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)  channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
Line 601 
Line 634 
         p = buffer_ptr(&c->input);          p = buffer_ptr(&c->input);
         len = strlen(p);          len = strlen(p);
         have = buffer_len(&c->input);          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)          if (len > have)
                 fatal("channel %d: decode socks4: len %d > have %d",                  fatal("channel %d: decode socks4: len %d > have %d",
                     c->self, len, have);                      c->self, len, have);
Line 613 
Line 646 
         strlcpy(c->path, host, sizeof(c->path));          strlcpy(c->path, host, sizeof(c->path));
         c->host_port = ntohs(s4_req.dest_port);          c->host_port = ntohs(s4_req.dest_port);
   
         debug("channel %d: dynamic request: "          debug("channel %d: dynamic request: socks4 host %s port %u command %u",
             "socks%x://%s@%s:%u/command?%u",              c->self, host, c->host_port, s4_req.command);
             c->self, s4_req.version, username, host, c->host_port,  
             s4_req.command);  
   
         if (s4_req.command != 1) {          if (s4_req.command != 1) {
                 debug("channel %d: cannot handle: socks4 cn %d",                  debug("channel %d: cannot handle: socks4 cn %d",
Line 631 
Line 662 
         return 1;          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 */  /* dynamic port forwarding */
 void  void
 channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)  channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
Line 651 
Line 791 
         /* try to guess the protocol */          /* try to guess the protocol */
         p = buffer_ptr(&c->input);          p = buffer_ptr(&c->input);
         switch (p[0]) {          switch (p[0]) {
         case 0x04:  
                 ret = channel_decode_socks4(c, readset, writeset);  
                 break;  
 #if 0  
         case 'C':          case 'C':
                 ret = channel_decode_https(c, readset, writeset);                  ret = channel_decode_https(c, readset, writeset);
                 break;                  break;
           case 0x04:
                   ret = channel_decode_socks4(c, readset, writeset);
                   break;
         case 0x05:          case 0x05:
                 ret = channel_decode_socks5(c, readset, writeset);                  ret = channel_decode_socks5(c, readset, writeset);
                 break;                  break;
 #endif  
         default:          default:
                 ret = -1;                  ret = -1;
                 break;                  break;

Legend:
Removed from v.1.105  
changed lines
  Added in v.1.106