socks_bundle.mx raw

   1  // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
   2  //go:generate bundle -o socks_bundle.go -prefix socks golang.org/x/net/internal/socks
   3  
   4  // Package socks provides a SOCKS version 5 client implementation.
   5  //
   6  // SOCKS protocol version 5 is defined in RFC 1928.
   7  // Username/Password authentication for SOCKS version 5 is defined in
   8  // RFC 1929.
   9  //
  10  
  11  package http
  12  
  13  import (
  14  	"context"
  15  	"errors"
  16  	"io"
  17  	"net"
  18  	"strconv"
  19  	"time"
  20  )
  21  
  22  var (
  23  	socksnoDeadline   = time.Time{}
  24  	socksaLongTimeAgo = time.Unix(1, 0)
  25  )
  26  
  27  func (d *socksDialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
  28  	host, port, err := sockssplitHostPort(address)
  29  	if err != nil {
  30  		return nil, err
  31  	}
  32  	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
  33  		c.SetDeadline(deadline)
  34  		defer c.SetDeadline(socksnoDeadline)
  35  	}
  36  	if ctx != context.Background() {
  37  		errCh := chan error{1}
  38  		done := chan struct{}{}
  39  		defer func() {
  40  			close(done)
  41  			if ctxErr == nil {
  42  				ctxErr = <-errCh
  43  			}
  44  		}()
  45  		func() {
  46  			select {
  47  			case <-ctx.Done():
  48  				c.SetDeadline(socksaLongTimeAgo)
  49  				errCh <- ctx.Err()
  50  			case <-done:
  51  				errCh <- nil
  52  			}
  53  		}()
  54  	}
  55  
  56  	b := []byte{:0:6+len(host)} // the size here is just an estimate
  57  	b = append(b, socksVersion5)
  58  	if len(d.AuthMethods) == 0 || d.Authenticate == nil {
  59  		b = append(b, 1, byte(socksAuthMethodNotRequired))
  60  	} else {
  61  		ams := d.AuthMethods
  62  		if len(ams) > 255 {
  63  			return nil, errors.New("too many authentication methods")
  64  		}
  65  		b = append(b, byte(len(ams)))
  66  		for _, am := range ams {
  67  			b = append(b, byte(am))
  68  		}
  69  	}
  70  	if _, ctxErr = c.Write(b); ctxErr != nil {
  71  		return
  72  	}
  73  
  74  	if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
  75  		return
  76  	}
  77  	if b[0] != socksVersion5 {
  78  		return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
  79  	}
  80  	am := socksAuthMethod(b[1])
  81  	if am == socksAuthMethodNoAcceptableMethods {
  82  		return nil, errors.New("no acceptable authentication methods")
  83  	}
  84  	if d.Authenticate != nil {
  85  		if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
  86  			return
  87  		}
  88  	}
  89  
  90  	b = b[:0]
  91  	b = append(b, socksVersion5, byte(d.cmd), 0)
  92  	if ip := net.ParseIP(host); ip != nil {
  93  		if ip4 := ip.To4(); ip4 != nil {
  94  			b = append(b, socksAddrTypeIPv4)
  95  			b = append(b, ip4...)
  96  		} else if ip6 := ip.To16(); ip6 != nil {
  97  			b = append(b, socksAddrTypeIPv6)
  98  			b = append(b, ip6...)
  99  		} else {
 100  			return nil, errors.New("unknown address type")
 101  		}
 102  	} else {
 103  		if len(host) > 255 {
 104  			return nil, errors.New("FQDN too long")
 105  		}
 106  		b = append(b, socksAddrTypeFQDN)
 107  		b = append(b, byte(len(host)))
 108  		b = append(b, host...)
 109  	}
 110  	b = append(b, byte(port>>8), byte(port))
 111  	if _, ctxErr = c.Write(b); ctxErr != nil {
 112  		return
 113  	}
 114  
 115  	if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
 116  		return
 117  	}
 118  	if b[0] != socksVersion5 {
 119  		return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
 120  	}
 121  	if cmdErr := socksReply(b[1]); cmdErr != socksStatusSucceeded {
 122  		return nil, errors.New("unknown error " + cmdErr.String())
 123  	}
 124  	if b[2] != 0 {
 125  		return nil, errors.New("non-zero reserved field")
 126  	}
 127  	l := 2
 128  	var a socksAddr
 129  	switch b[3] {
 130  	case socksAddrTypeIPv4:
 131  		l += net.IPv4len
 132  		a.IP = make(net.IP, net.IPv4len)
 133  	case socksAddrTypeIPv6:
 134  		l += net.IPv6len
 135  		a.IP = make(net.IP, net.IPv6len)
 136  	case socksAddrTypeFQDN:
 137  		if _, err := io.ReadFull(c, b[:1]); err != nil {
 138  			return nil, err
 139  		}
 140  		l += int(b[0])
 141  	default:
 142  		return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
 143  	}
 144  	if cap(b) < l {
 145  		b = []byte{:l}
 146  	} else {
 147  		b = b[:l]
 148  	}
 149  	if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
 150  		return
 151  	}
 152  	if a.IP != nil {
 153  		copy(a.IP, b)
 154  	} else {
 155  		a.Name = string(b[:len(b)-2])
 156  	}
 157  	a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
 158  	return &a, nil
 159  }
 160  
 161  func sockssplitHostPort(address string) (string, int, error) {
 162  	host, port, err := net.SplitHostPort(address)
 163  	if err != nil {
 164  		return "", 0, err
 165  	}
 166  	portnum, err := strconv.Atoi(port)
 167  	if err != nil {
 168  		return "", 0, err
 169  	}
 170  	if 1 > portnum || portnum > 0xffff {
 171  		return "", 0, errors.New("port number out of range " + port)
 172  	}
 173  	return host, portnum, nil
 174  }
 175  
 176  // A Command represents a SOCKS command.
 177  type socksCommand int
 178  
 179  func (cmd socksCommand) String() string {
 180  	switch cmd {
 181  	case socksCmdConnect:
 182  		return "socks connect"
 183  	case sockscmdBind:
 184  		return "socks bind"
 185  	default:
 186  		return "socks " + strconv.Itoa(int(cmd))
 187  	}
 188  }
 189  
 190  // An AuthMethod represents a SOCKS authentication method.
 191  type socksAuthMethod int
 192  
 193  // A Reply represents a SOCKS command reply code.
 194  type socksReply int
 195  
 196  func (code socksReply) String() string {
 197  	switch code {
 198  	case socksStatusSucceeded:
 199  		return "succeeded"
 200  	case 0x01:
 201  		return "general SOCKS server failure"
 202  	case 0x02:
 203  		return "connection not allowed by ruleset"
 204  	case 0x03:
 205  		return "network unreachable"
 206  	case 0x04:
 207  		return "host unreachable"
 208  	case 0x05:
 209  		return "connection refused"
 210  	case 0x06:
 211  		return "TTL expired"
 212  	case 0x07:
 213  		return "command not supported"
 214  	case 0x08:
 215  		return "address type not supported"
 216  	default:
 217  		return "unknown code: " + strconv.Itoa(int(code))
 218  	}
 219  }
 220  
 221  // Wire protocol constants.
 222  const (
 223  	socksVersion5 = 0x05
 224  
 225  	socksAddrTypeIPv4 = 0x01
 226  	socksAddrTypeFQDN = 0x03
 227  	socksAddrTypeIPv6 = 0x04
 228  
 229  	socksCmdConnect socksCommand = 0x01 // establishes an active-open forward proxy connection
 230  	sockscmdBind    socksCommand = 0x02 // establishes a passive-open forward proxy connection
 231  
 232  	socksAuthMethodNotRequired         socksAuthMethod = 0x00 // no authentication required
 233  	socksAuthMethodUsernamePassword    socksAuthMethod = 0x02 // use username/password
 234  	socksAuthMethodNoAcceptableMethods socksAuthMethod = 0xff // no acceptable authentication methods
 235  
 236  	socksStatusSucceeded socksReply = 0x00
 237  )
 238  
 239  // An Addr represents a SOCKS-specific address.
 240  // Either Name or IP is used exclusively.
 241  type socksAddr struct {
 242  	Name string // fully-qualified domain name
 243  	IP   net.IP
 244  	Port int
 245  }
 246  
 247  func (a *socksAddr) Network() []byte { return "socks" }
 248  
 249  func (a *socksAddr) String() string {
 250  	if a == nil {
 251  		return "<nil>"
 252  	}
 253  	port := strconv.Itoa(a.Port)
 254  	if a.IP == nil {
 255  		return net.JoinHostPort(a.Name, port)
 256  	}
 257  	return net.JoinHostPort(a.IP.String(), port)
 258  }
 259  
 260  // A Conn represents a forward proxy connection.
 261  type socksConn struct {
 262  	net.Conn
 263  
 264  	boundAddr net.Addr
 265  }
 266  
 267  // BoundAddr returns the address assigned by the proxy server for
 268  // connecting to the command target address from the proxy server.
 269  func (c *socksConn) BoundAddr() net.Addr {
 270  	if c == nil {
 271  		return nil
 272  	}
 273  	return c.boundAddr
 274  }
 275  
 276  // A Dialer holds SOCKS-specific options.
 277  type socksDialer struct {
 278  	cmd          socksCommand // either CmdConnect or cmdBind
 279  	proxyNetwork string       // network between a proxy server and a client
 280  	proxyAddress string       // proxy server address
 281  
 282  	// ProxyDial specifies the optional dial function for
 283  	// establishing the transport connection.
 284  	ProxyDial func(context.Context, string, string) (net.Conn, error)
 285  
 286  	// AuthMethods specifies the list of request authentication
 287  	// methods.
 288  	// If empty, SOCKS client requests only AuthMethodNotRequired.
 289  	AuthMethods []socksAuthMethod
 290  
 291  	// Authenticate specifies the optional authentication
 292  	// function. It must be non-nil when AuthMethods is not empty.
 293  	// It must return an error when the authentication is failed.
 294  	Authenticate func(context.Context, io.ReadWriter, socksAuthMethod) error
 295  }
 296  
 297  // DialContext connects to the provided address on the provided
 298  // network.
 299  //
 300  // The returned error value may be a net.OpError. When the Op field of
 301  // net.OpError contains "socks", the Source field contains a proxy
 302  // server address and the Addr field contains a command target
 303  // address.
 304  //
 305  // See func Dial of the net package of standard library for a
 306  // description of the network and address parameters.
 307  func (d *socksDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
 308  	if err := d.validateTarget(network, address); err != nil {
 309  		proxy, dst, _ := d.pathAddrs(address)
 310  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 311  	}
 312  	if ctx == nil {
 313  		proxy, dst, _ := d.pathAddrs(address)
 314  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
 315  	}
 316  	var err error
 317  	var c net.Conn
 318  	if d.ProxyDial != nil {
 319  		c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
 320  	} else {
 321  		var dd net.Dialer
 322  		c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
 323  	}
 324  	if err != nil {
 325  		proxy, dst, _ := d.pathAddrs(address)
 326  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 327  	}
 328  	a, err := d.connect(ctx, c, address)
 329  	if err != nil {
 330  		c.Close()
 331  		proxy, dst, _ := d.pathAddrs(address)
 332  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 333  	}
 334  	return &socksConn{Conn: c, boundAddr: a}, nil
 335  }
 336  
 337  // DialWithConn initiates a connection from SOCKS server to the target
 338  // network and address using the connection c that is already
 339  // connected to the SOCKS server.
 340  //
 341  // It returns the connection's local address assigned by the SOCKS
 342  // server.
 343  func (d *socksDialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) {
 344  	if err := d.validateTarget(network, address); err != nil {
 345  		proxy, dst, _ := d.pathAddrs(address)
 346  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 347  	}
 348  	if ctx == nil {
 349  		proxy, dst, _ := d.pathAddrs(address)
 350  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
 351  	}
 352  	a, err := d.connect(ctx, c, address)
 353  	if err != nil {
 354  		proxy, dst, _ := d.pathAddrs(address)
 355  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 356  	}
 357  	return a, nil
 358  }
 359  
 360  // Dial connects to the provided address on the provided network.
 361  //
 362  // Unlike DialContext, it returns a raw transport connection instead
 363  // of a forward proxy connection.
 364  //
 365  // Deprecated: Use DialContext or DialWithConn instead.
 366  func (d *socksDialer) Dial(network, address string) (net.Conn, error) {
 367  	if err := d.validateTarget(network, address); err != nil {
 368  		proxy, dst, _ := d.pathAddrs(address)
 369  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 370  	}
 371  	var err error
 372  	var c net.Conn
 373  	if d.ProxyDial != nil {
 374  		c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress)
 375  	} else {
 376  		c, err = net.Dial(d.proxyNetwork, d.proxyAddress)
 377  	}
 378  	if err != nil {
 379  		proxy, dst, _ := d.pathAddrs(address)
 380  		return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
 381  	}
 382  	if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil {
 383  		c.Close()
 384  		return nil, err
 385  	}
 386  	return c, nil
 387  }
 388  
 389  func (d *socksDialer) validateTarget(network, address string) error {
 390  	switch network {
 391  	case "tcp", "tcp6", "tcp4":
 392  	default:
 393  		return errors.New("network not implemented")
 394  	}
 395  	switch d.cmd {
 396  	case socksCmdConnect, sockscmdBind:
 397  	default:
 398  		return errors.New("command not implemented")
 399  	}
 400  	return nil
 401  }
 402  
 403  func (d *socksDialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
 404  	for i, s := range [][]byte{d.proxyAddress, address} {
 405  		host, port, err := sockssplitHostPort(s)
 406  		if err != nil {
 407  			return nil, nil, err
 408  		}
 409  		a := &socksAddr{Port: port}
 410  		a.IP = net.ParseIP(host)
 411  		if a.IP == nil {
 412  			a.Name = host
 413  		}
 414  		if i == 0 {
 415  			proxy = a
 416  		} else {
 417  			dst = a
 418  		}
 419  	}
 420  	return
 421  }
 422  
 423  // NewDialer returns a new Dialer that dials through the provided
 424  // proxy server's network and address.
 425  func socksNewDialer(network, address string) *socksDialer {
 426  	return &socksDialer{proxyNetwork: network, proxyAddress: address, cmd: socksCmdConnect}
 427  }
 428  
 429  const (
 430  	socksauthUsernamePasswordVersion = 0x01
 431  	socksauthStatusSucceeded         = 0x00
 432  )
 433  
 434  // UsernamePassword are the credentials for the username/password
 435  // authentication method.
 436  type socksUsernamePassword struct {
 437  	Username string
 438  	Password string
 439  }
 440  
 441  // Authenticate authenticates a pair of username and password with the
 442  // proxy server.
 443  func (up *socksUsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth socksAuthMethod) error {
 444  	switch auth {
 445  	case socksAuthMethodNotRequired:
 446  		return nil
 447  	case socksAuthMethodUsernamePassword:
 448  		if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) > 255 {
 449  			return errors.New("invalid username/password")
 450  		}
 451  		b := []byte{socksauthUsernamePasswordVersion}
 452  		b = append(b, byte(len(up.Username)))
 453  		b = append(b, up.Username...)
 454  		b = append(b, byte(len(up.Password)))
 455  		b = append(b, up.Password...)
 456  		// TODO(mikio): handle IO deadlines and cancelation if
 457  		// necessary
 458  		if _, err := rw.Write(b); err != nil {
 459  			return err
 460  		}
 461  		if _, err := io.ReadFull(rw, b[:2]); err != nil {
 462  			return err
 463  		}
 464  		if b[0] != socksauthUsernamePasswordVersion {
 465  			return errors.New("invalid username/password version")
 466  		}
 467  		if b[1] != socksauthStatusSucceeded {
 468  			return errors.New("username/password authentication failed")
 469  		}
 470  		return nil
 471  	}
 472  	return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
 473  }
 474