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

Diff for /src/usr.bin/nc/socks.c between version 1.15 and 1.16

version 1.15, 2005/05/24 20:13:28 version 1.16, 2006/01/25 23:21:37
Line 37 
Line 37 
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <resolv.h>
   #include <readpassphrase.h>
 #include "atomicio.h"  #include "atomicio.h"
   
 #define SOCKS_PORT      "1080"  #define SOCKS_PORT      "1080"
Line 52 
Line 54 
 #define SOCKS_IPV6      4  #define SOCKS_IPV6      4
   
 int     remote_connect(const char *, const char *, struct addrinfo);  int     remote_connect(const char *, const char *, struct addrinfo);
 int     socks_connect(const char *host, const char *port, struct addrinfo hints,  int     socks_connect(const char *, const char *, struct addrinfo,
             const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,              const char *, const char *, struct addrinfo, int,
             int socksv);              const char *);
   
 static int  static int
 decode_addrport(const char *h, const char *p, struct sockaddr *addr,  decode_addrport(const char *h, const char *p, struct sockaddr *addr,
Line 107 
Line 109 
         return (off);          return (off);
 }  }
   
   static const char *
   getproxypass(const char *proxyuser, const char *proxyhost)
   {
           char prompt[512];
           static char pw[256];
   
           snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
              proxyuser, proxyhost);
           if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
                   errx(1, "Unable to read proxy passphrase");
           return (pw);
   }
   
 int  int
 socks_connect(const char *host, const char *port,  socks_connect(const char *host, const char *port,
     struct addrinfo hints __attribute__ ((__unused__)),      struct addrinfo hints __attribute__ ((__unused__)),
     const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,      const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
     int socksv)      int socksv, const char *proxyuser)
 {  {
         int proxyfd, r;          int proxyfd, r, authretry = 0;
         size_t hlen, wlen;          size_t hlen, wlen;
         unsigned char buf[1024];          unsigned char buf[1024];
         size_t cnt;          size_t cnt;
Line 121 
Line 136 
         struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;          struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
         struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;          struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
         in_port_t serverport;          in_port_t serverport;
           const char *proxypass = NULL;
   
         if (proxyport == NULL)          if (proxyport == NULL)
                 proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;                  proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
   
         proxyfd = remote_connect(proxyhost, proxyport, proxyhints);  
   
         if (proxyfd < 0)  
                 return (-1);  
   
         /* Abuse API to lookup port */          /* Abuse API to lookup port */
         if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,          if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
             sizeof(addr), 1, 1) == -1)              sizeof(addr), 1, 1) == -1)
                 errx(1, "unknown port \"%.64s\"", port);                  errx(1, "unknown port \"%.64s\"", port);
         serverport = in4->sin_port;          serverport = in4->sin_port;
   
    again:
           if (authretry++ > 3)
                   errx(1, "Too many authentication failures");
   
           proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
   
           if (proxyfd < 0)
                   return (-1);
   
         if (socksv == 5) {          if (socksv == 5) {
                 if (decode_addrport(host, port, (struct sockaddr *)&addr,                  if (decode_addrport(host, port, (struct sockaddr *)&addr,
                     sizeof(addr), 0, 1) == -1)                      sizeof(addr), 0, 1) == -1)
Line 239 
Line 259 
                 /* Try to be sane about numeric IPv6 addresses */                  /* Try to be sane about numeric IPv6 addresses */
                 if (strchr(host, ':') != NULL) {                  if (strchr(host, ':') != NULL) {
                         r = snprintf(buf, sizeof(buf),                          r = snprintf(buf, sizeof(buf),
                             "CONNECT [%s]:%d HTTP/1.0\r\n\r\n",                              "CONNECT [%s]:%d HTTP/1.0\r\n",
                             host, ntohs(serverport));                              host, ntohs(serverport));
                 } else {                  } else {
                         r = snprintf(buf, sizeof(buf),                          r = snprintf(buf, sizeof(buf),
                             "CONNECT %s:%d HTTP/1.0\r\n\r\n",                              "CONNECT %s:%d HTTP/1.0\r\n",
                             host, ntohs(serverport));                              host, ntohs(serverport));
                 }                  }
                 if (r == -1 || (size_t)r >= sizeof(buf))                  if (r == -1 || (size_t)r >= sizeof(buf))
Line 254 
Line 274 
                 if (cnt != r)                  if (cnt != r)
                         err(1, "write failed (%d/%d)", cnt, r);                          err(1, "write failed (%d/%d)", cnt, r);
   
                 /* Read reply */                  if (authretry > 1) {
                           char resp[1024];
   
                           proxypass = getproxypass(proxyuser, proxyhost);
                           r = snprintf(buf, sizeof(buf), "%s:%s",
                               proxyuser, proxypass);
                           if (r == -1 || (size_t)r >= sizeof(buf) ||
                               b64_ntop(buf, strlen(buf), resp,
                               sizeof(resp)) == -1)
                                   errx(1, "Proxy username/password too long");
                           r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
                               "Basic %s\r\n", resp);
                           if (r == -1 || (size_t)r >= sizeof(buf))
                                   errx(1, "Proxy auth response too long");
                           r = strlen(buf);
                           if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
                                   err(1, "write failed (%d/%d)", cnt, r);
                   }
   
                   /* Terminate headers */
                   if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
                           err(1, "write failed (2/%d)", r);
   
                   /* Read status reply */
                   proxy_read_line(proxyfd, buf, sizeof(buf));
                   if (proxyuser != NULL &&
                       strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
                           if (authretry > 1) {
                                   fprintf(stderr, "Proxy authentication "
                                       "failed\n");
                           }
                           close(proxyfd);
                           goto again;
                   } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0)
                           errx(1, "Proxy error: \"%s\"", buf);
   
                   /* Headers continue until we hit an empty line */
                 for (r = 0; r < HTTP_MAXHDRS; r++) {                  for (r = 0; r < HTTP_MAXHDRS; r++) {
                         proxy_read_line(proxyfd, buf, sizeof(buf));                          proxy_read_line(proxyfd, buf, sizeof(buf));
                         if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0)  
                                 errx(1, "Proxy error: \"%s\"", buf);  
                         /* Discard headers until we hit an empty line */  
                         if (*buf == '\0')                          if (*buf == '\0')
                                 break;                                  break;
                 }                  }
                   if (*buf != '\0')
                           errx(1, "Too many proxy headers received");
         } else          } else
                 errx(1, "Unknown proxy protocol %d", socksv);                  errx(1, "Unknown proxy protocol %d", socksv);
   

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16