github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/goptlib/socks.go (about) 1 package pt 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "net" 8 "time" 9 ) 10 11 const ( 12 socks4Version = 0x04 13 socks5Version = 0x05 14 15 socksAuthNoneRequired = 0x00 16 socksAuthUsernamePassword = 0x02 17 socksAuthNoAcceptableMethods = 0xff 18 19 socksCmdConnect = 0x01 20 socksReserved = 0x00 21 22 socksAtypeV4 = 0x01 23 socksAtypeDomainName = 0x03 24 socksAtypeV6 = 0x04 25 26 socksAuthRFC1929Ver = 0x01 27 socksAuthRFC1929Success = 0x00 28 socksAuthRFC1929Fail = 0x01 29 30 socksRepSucceeded = 0x00 31 // "general SOCKS server failure" 32 SocksRepGeneralFailure = 0x01 33 // "connection not allowed by ruleset" 34 SocksRepConnectionNotAllowed = 0x02 35 // "Network unreachable" 36 SocksRepNetworkUnreachable = 0x03 37 // "Host unreachable" 38 SocksRepHostUnreachable = 0x04 39 // "Connection refused" 40 SocksRepConnectionRefused = 0x05 41 // "TTL expired" 42 SocksRepTTLExpired = 0x06 43 // "Command not supported" 44 SocksRepCommandNotSupported = 0x07 45 // "Address type not supported" 46 SocksRepAddressNotSupported = 0x08 47 48 socks4ResponseVersion = 0x00 49 socks4RequestGranted = 0x5a 50 socks4RequestRejected = 0x5b 51 ) 52 53 // Put a sanity timeout on how long we wait for a SOCKS request. 54 const socksRequestTimeout = 5 * time.Second 55 56 // SocksRequest describes a SOCKS request. 57 type SocksRequest struct { 58 // The endpoint requested by the client as a "host:port" string. 59 Target string 60 // The userid string sent by the client. 61 Username string 62 // The password string sent by the client. 63 Password string 64 // The parsed contents of Username as a key–value mapping. 65 Args Args 66 } 67 68 // SocksConn encapsulates a net.Conn and information associated with a SOCKS request. 69 type SocksConn struct { 70 net.Conn 71 Req SocksRequest 72 socksVersion byte 73 } 74 75 // Send a message to the proxy client that access to the given address is 76 // granted. 77 // For SOCKS5, Addr is ignored, and "0.0.0.0:0" is always sent back for 78 // BND.ADDR/BND.PORT in the SOCKS response. 79 // For SOCKS4a, if the IP field inside addr is not an IPv4 address, the IP 80 // portion of the response will be four zero bytes. 81 func (conn *SocksConn) Grant(addr *net.TCPAddr) error { 82 if conn.socksVersion == socks4Version { 83 return sendSocks4aResponseGranted(conn, addr) 84 } 85 return sendSocks5ResponseGranted(conn) 86 } 87 88 // Send a message to the proxy client that access was rejected or failed. This 89 // sends back a "General Failure" error code. RejectReason should be used if 90 // more specific error reporting is desired. 91 func (conn *SocksConn) Reject() error { 92 if conn.socksVersion == socks4Version { 93 return sendSocks4aResponseRejected(conn) 94 } 95 return sendSocks5ResponseRejected(conn, SocksRepGeneralFailure) 96 } 97 98 // Send a message to the proxy client that access was rejected, with the 99 // specific error code indicating the reason behind the rejection. 100 // For SOCKS4a, the reason is ignored. 101 func (conn *SocksConn) RejectReason(reason byte) error { 102 if conn.socksVersion == socks4Version { 103 return sendSocks4aResponseRejected(conn) 104 } 105 return sendSocks5ResponseRejected(conn, reason) 106 } 107 108 // SocksListener wraps a net.Listener in order to read a SOCKS request on Accept. 109 // 110 // func handleConn(conn *pt.SocksConn) error { 111 // defer conn.Close() 112 // remote, err := net.Dial("tcp", conn.Req.Target) 113 // if err != nil { 114 // conn.Reject() 115 // return err 116 // } 117 // defer remote.Close() 118 // err = conn.Grant(remote.RemoteAddr().(*net.TCPAddr)) 119 // if err != nil { 120 // return err 121 // } 122 // // do something with conn and remote 123 // return nil 124 // } 125 // ... 126 // ln, err := pt.ListenSocks("tcp", "127.0.0.1:0") 127 // if err != nil { 128 // panic(err.Error()) 129 // } 130 // for { 131 // conn, err := ln.AcceptSocks() 132 // if err != nil { 133 // log.Printf("accept error: %s", err) 134 // if e, ok := err.(net.Error); !ok || !e.Temporary() { 135 // break 136 // } 137 // continue 138 // } 139 // go handleConn(conn) 140 // } 141 type SocksListener struct { 142 net.Listener 143 } 144 145 // Open a net.Listener according to network and laddr, and return it as a 146 // SocksListener. 147 func ListenSocks(network, laddr string) (*SocksListener, error) { 148 ln, err := net.Listen(network, laddr) 149 if err != nil { 150 return nil, err 151 } 152 return NewSocksListener(ln), nil 153 } 154 155 // Create a new SocksListener wrapping the given net.Listener. 156 func NewSocksListener(ln net.Listener) *SocksListener { 157 return &SocksListener{ln} 158 } 159 160 // Accept is the same as AcceptSocks, except that it returns a generic net.Conn. 161 // It is present for the sake of satisfying the net.Listener interface. 162 func (ln *SocksListener) Accept() (net.Conn, error) { 163 return ln.AcceptSocks() 164 } 165 166 // Call Accept on the wrapped net.Listener, do SOCKS negotiation, and return a 167 // SocksConn. After accepting, you must call either conn.Grant or conn.Reject 168 // (presumably after trying to connect to conn.Req.Target). 169 // 170 // Errors returned by AcceptSocks may be temporary (for example, EOF while 171 // reading the request, or a badly formatted userid string), or permanent (e.g., 172 // the underlying socket is closed). You can determine whether an error is 173 // temporary and take appropriate action with a type conversion to net.Error. 174 // For example: 175 // 176 // for { 177 // conn, err := ln.AcceptSocks() 178 // if err != nil { 179 // if e, ok := err.(net.Error); ok && e.Temporary() { 180 // log.Printf("temporary accept error; trying again: %s", err) 181 // continue 182 // } 183 // log.Printf("permanent accept error; giving up: %s", err) 184 // break 185 // } 186 // go handleConn(conn) 187 // } 188 func (ln *SocksListener) AcceptSocks() (*SocksConn, error) { 189 c, err := ln.Listener.Accept() 190 if err != nil { 191 return nil, err 192 } 193 conn := new(SocksConn) 194 conn.Conn = c 195 196 err = conn.SetDeadline(time.Now().Add(socksRequestTimeout)) 197 if err != nil { 198 conn.Close() 199 err = newTemporaryNetError("AcceptSocks: conn.SetDeadline() #1 failed: %s", err.Error()) 200 return nil, err 201 } 202 203 rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) 204 205 // Determine which SOCKS version the client is using and branch on it. 206 if version, err := socksPeekByte(rw.Reader); err != nil { 207 conn.Close() 208 err = newTemporaryNetError("AcceptSocks: socksPeekByte() failed: %s", err.Error()) 209 return nil, err 210 } else if version == socks4Version { 211 conn.socksVersion = socks4Version 212 conn.Req, err = readSocks4aConnect(rw.Reader) 213 if err != nil { 214 conn.Close() 215 return nil, err 216 } 217 } else if version == socks5Version { 218 conn.socksVersion = socks5Version 219 conn.Req, err = socks5Handshake(rw) 220 if err != nil { 221 conn.Close() 222 return nil, err 223 } 224 } else { 225 conn.Close() 226 err = newTemporaryNetError("AcceptSocks: Illegal SOCKS version: 0x%02x", version) 227 return nil, err 228 } 229 230 err = conn.SetDeadline(time.Time{}) 231 if err != nil { 232 conn.Close() 233 err = newTemporaryNetError("AcceptSocks: conn.SetDeadline() #2 failed: %s", err.Error()) 234 return nil, err 235 236 } 237 return conn, nil 238 } 239 240 // Returns "socks5", suitable to be included in a call to Cmethod. 241 func (ln *SocksListener) Version() string { 242 return "socks5" 243 } 244 245 // socks5handshake conducts the SOCKS5 handshake up to the point where the 246 // client command is read and the proxy must open the outgoing connection. 247 // Returns a SocksRequest. 248 func socks5Handshake(rw *bufio.ReadWriter) (req SocksRequest, err error) { 249 // Negotiate the authentication method. 250 var method byte 251 if method, err = socks5NegotiateAuth(rw); err != nil { 252 return 253 } 254 255 // Authenticate the client. 256 if err = socks5Authenticate(rw, method, &req); err != nil { 257 return 258 } 259 260 // Read the command. 261 err = socks5ReadCommand(rw, &req) 262 return 263 } 264 265 // socks5NegotiateAuth negotiates the authentication method and returns the 266 // selected method as a byte. On negotiation failures an error is returned. 267 func socks5NegotiateAuth(rw *bufio.ReadWriter) (method byte, err error) { 268 // Validate the version. 269 if err = socksReadByteVerify(rw.Reader, "version", socks5Version); err != nil { 270 err = newTemporaryNetError("socks5NegotiateAuth: %s", err.Error()) 271 return 272 } 273 274 // Read the number of methods. 275 var nmethods byte 276 if nmethods, err = socksReadByte(rw.Reader); err != nil { 277 err = newTemporaryNetError("socks5NegotiateAuth: Failed to read nmethods byte: %s", err.Error()) 278 return 279 } 280 281 // Read the methods. 282 var methods []byte 283 if methods, err = socksReadBytes(rw.Reader, int(nmethods)); err != nil { 284 err = newTemporaryNetError("socks5NegotiateAuth: Failed to read methods bytes: %s", err.Error()) 285 return 286 } 287 288 // Pick the most "suitable" method. 289 method = socksAuthNoAcceptableMethods 290 for _, m := range methods { 291 // [Psiphon] 292 // Some SOCKS5 clients send both None and Username/Password when in fact they are only 293 // able to auth with None. Since we don't need pluggable transport parameters and prefer 294 // enabling clients to proxy, we prefer None, which allows those clients to connect. 295 /* 296 switch m { 297 case socksAuthNoneRequired: 298 // Pick Username/Password over None if the client happens to 299 // send both. 300 if method == socksAuthNoAcceptableMethods { 301 method = m 302 } 303 304 case socksAuthUsernamePassword: 305 method = m 306 } 307 */ 308 switch m { 309 case socksAuthNoneRequired: 310 method = m 311 312 case socksAuthUsernamePassword: 313 if method == socksAuthNoAcceptableMethods { 314 method = m 315 } 316 } 317 // [Psiphon] 318 } 319 320 // Send the negotiated method. 321 var msg [2]byte 322 msg[0] = socks5Version 323 msg[1] = method 324 if _, err = rw.Writer.Write(msg[:]); err != nil { 325 err = newTemporaryNetError("socks5NegotiateAuth: Failed to write negotiated method: %s", err.Error()) 326 return 327 } 328 329 if err = socksFlushBuffers(rw); err != nil { 330 err = newTemporaryNetError("socks5NegotiateAuth: Failed to flush buffers: %s", err.Error()) 331 return 332 } 333 return 334 } 335 336 // socks5Authenticate authenticates the client via the chosen authentication 337 // mechanism. 338 func socks5Authenticate(rw *bufio.ReadWriter, method byte, req *SocksRequest) (err error) { 339 switch method { 340 case socksAuthNoneRequired: 341 // Straight into reading the connect. 342 343 case socksAuthUsernamePassword: 344 if err = socks5AuthRFC1929(rw, req); err != nil { 345 return 346 } 347 348 case socksAuthNoAcceptableMethods: 349 err = newTemporaryNetError("socks5Authenticate: SOCKS method select had no compatible methods") 350 return 351 352 default: 353 err = newTemporaryNetError("socks5Authenticate: SOCKS method select picked a unsupported method 0x%02x", method) 354 return 355 } 356 357 if err = socksFlushBuffers(rw); err != nil { 358 err = newTemporaryNetError("socks5Authenticate: Failed to flush buffers: %s", err) 359 return 360 } 361 return 362 } 363 364 // socks5AuthRFC1929 authenticates the client via RFC 1929 username/password 365 // auth. As a design decision any valid username/password is accepted as this 366 // field is primarily used as an out-of-band argument passing mechanism for 367 // pluggable transports. 368 func socks5AuthRFC1929(rw *bufio.ReadWriter, req *SocksRequest) (err error) { 369 sendErrResp := func() { 370 // Swallow the write/flush error here, we are going to close the 371 // connection and the original failure is more useful. 372 resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Fail} 373 rw.Write(resp[:]) 374 socksFlushBuffers(rw) 375 } 376 377 // Validate the fixed parts of the command message. 378 if err = socksReadByteVerify(rw.Reader, "auth version", socksAuthRFC1929Ver); err != nil { 379 sendErrResp() 380 err = newTemporaryNetError("socks5AuthRFC1929: %s", err) 381 return 382 } 383 384 // Read the username. 385 var ulen byte 386 if ulen, err = socksReadByte(rw.Reader); err != nil { 387 err = newTemporaryNetError("socks5AuthRFC1929: Failed to read username length: %s", err) 388 return 389 } 390 if ulen < 1 { 391 sendErrResp() 392 err = newTemporaryNetError("socks5AuthRFC1929: username with 0 length") 393 return 394 } 395 var uname []byte 396 if uname, err = socksReadBytes(rw.Reader, int(ulen)); err != nil { 397 err = newTemporaryNetError("socks5AuthRFC1929: Failed to read username: %s", err) 398 return 399 } 400 req.Username = string(uname) 401 402 // Read the password. 403 var plen byte 404 if plen, err = socksReadByte(rw.Reader); err != nil { 405 err = newTemporaryNetError("socks5AuthRFC1929: Failed to read password length: %s", err) 406 return 407 } 408 if plen < 1 { 409 sendErrResp() 410 err = newTemporaryNetError("socks5AuthRFC1929: password with 0 length") 411 return 412 } 413 var passwd []byte 414 if passwd, err = socksReadBytes(rw.Reader, int(plen)); err != nil { 415 err = newTemporaryNetError("socks5AuthRFC1929: Failed to read password: %s", err) 416 return 417 } 418 if !(plen == 1 && passwd[0] == 0x00) { 419 // tor will set the password to 'NUL' if there are no arguments. 420 req.Password = string(passwd) 421 } 422 423 // [Psiphon] 424 // Since we don't need pluggable transport parameters and prefer enabling clients to proxy, 425 // don't parse or validate username/password as PT args. 426 /* 427 // Mash the username/password together and parse it as a pluggable 428 // transport argument string. 429 if req.Args, err = parseClientParameters(req.Username + req.Password); err != nil { 430 sendErrResp() 431 err = newTemporaryNetError("socks5AuthRFC1929: failed to parse client parameters: %s", err) 432 return 433 } 434 */ 435 // [Psiphon] 436 437 // Write success response 438 resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Success} 439 if _, err = rw.Write(resp[:]); err != nil { 440 err = newTemporaryNetError("socks5AuthRFC1929: failed to write success response: %s", err) 441 return 442 } 443 return 444 } 445 446 // socks5ReadCommand reads a SOCKS5 client command and parses out the relevant 447 // fields into a SocksRequest. Only CMD_CONNECT is supported. 448 func socks5ReadCommand(rw *bufio.ReadWriter, req *SocksRequest) (err error) { 449 sendErrResp := func(reason byte) { 450 // Swallow errors that occur when writing/flushing the response, 451 // connection will be closed anyway. 452 sendSocks5ResponseRejected(rw, reason) 453 socksFlushBuffers(rw) 454 } 455 456 // Validate the fixed parts of the command message. 457 if err = socksReadByteVerify(rw.Reader, "version", socks5Version); err != nil { 458 sendErrResp(SocksRepGeneralFailure) 459 err = newTemporaryNetError("socks5ReadCommand: %s", err) 460 return 461 } 462 if err = socksReadByteVerify(rw.Reader, "command", socksCmdConnect); err != nil { 463 sendErrResp(SocksRepCommandNotSupported) 464 err = newTemporaryNetError("socks5ReadCommand: %s", err) 465 return 466 } 467 if err = socksReadByteVerify(rw.Reader, "reserved", socksReserved); err != nil { 468 sendErrResp(SocksRepGeneralFailure) 469 err = newTemporaryNetError("socks5ReadCommand: %s", err) 470 return 471 } 472 473 // Read the destination address/port. 474 // XXX: This should probably eventually send socks 5 error messages instead 475 // of rudely closing connections on invalid addresses. 476 var atype byte 477 if atype, err = socksReadByte(rw.Reader); err != nil { 478 err = newTemporaryNetError("socks5ReadCommand: Failed to read address type: %s", err) 479 return 480 } 481 var host string 482 switch atype { 483 case socksAtypeV4: 484 var addr []byte 485 if addr, err = socksReadBytes(rw.Reader, net.IPv4len); err != nil { 486 err = newTemporaryNetError("socks5ReadCommand: Failed to read IPv4 address: %s", err) 487 return 488 } 489 host = net.IPv4(addr[0], addr[1], addr[2], addr[3]).String() 490 491 case socksAtypeDomainName: 492 var alen byte 493 if alen, err = socksReadByte(rw.Reader); err != nil { 494 err = newTemporaryNetError("socks5ReadCommand: Failed to read domain name length: %s", err) 495 return 496 } 497 if alen == 0 { 498 err = newTemporaryNetError("socks5ReadCommand: SOCKS request had domain name with 0 length") 499 return 500 } 501 var addr []byte 502 if addr, err = socksReadBytes(rw.Reader, int(alen)); err != nil { 503 err = newTemporaryNetError("socks5ReadCommand: Failed to read domain name: %s", err) 504 return 505 } 506 host = string(addr) 507 508 case socksAtypeV6: 509 var rawAddr []byte 510 if rawAddr, err = socksReadBytes(rw.Reader, net.IPv6len); err != nil { 511 err = newTemporaryNetError("socks5ReadCommand: Failed to read IPv6 address: %s", err) 512 return 513 } 514 addr := make(net.IP, net.IPv6len) 515 copy(addr[:], rawAddr[:]) 516 host = fmt.Sprintf("[%s]", addr.String()) 517 518 default: 519 sendErrResp(SocksRepAddressNotSupported) 520 err = newTemporaryNetError("socks5ReadCommand: SOCKS request had unsupported address type 0x%02x", atype) 521 return 522 } 523 var rawPort []byte 524 if rawPort, err = socksReadBytes(rw.Reader, 2); err != nil { 525 err = newTemporaryNetError("socks5ReadCommand: Failed to read port number: %s", err) 526 return 527 } 528 port := int(rawPort[0])<<8 | int(rawPort[1])<<0 529 530 if err = socksFlushBuffers(rw); err != nil { 531 err = newTemporaryNetError("socks5ReadCommand: Failed to flush buffers: %s", err) 532 return 533 } 534 535 req.Target = fmt.Sprintf("%s:%d", host, port) 536 return 537 } 538 539 // Send a SOCKS5 response with the given code. BND.ADDR/BND.PORT is always the 540 // IPv4 address/port "0.0.0.0:0". 541 func sendSocks5Response(w io.Writer, code byte) error { 542 resp := make([]byte, 4+4+2) 543 resp[0] = socks5Version 544 resp[1] = code 545 resp[2] = socksReserved 546 resp[3] = socksAtypeV4 547 548 // BND.ADDR/BND.PORT should be the address and port that the outgoing 549 // connection is bound to on the proxy, but Tor does not use this 550 // information, so all zeroes are sent. 551 552 if _, err := w.Write(resp[:]); err != nil { 553 err = newTemporaryNetError("sendSocks5Response: Failed write response: %s", err) 554 return err 555 } 556 557 return nil 558 } 559 560 // Send a SOCKS5 response code 0x00. 561 func sendSocks5ResponseGranted(w io.Writer) error { 562 return sendSocks5Response(w, socksRepSucceeded) 563 } 564 565 // Send a SOCKS5 response with the provided failure reason. 566 func sendSocks5ResponseRejected(w io.Writer, reason byte) error { 567 return sendSocks5Response(w, reason) 568 } 569 570 /* 571 * Common helpers 572 */ 573 574 func socksFlushBuffers(rw *bufio.ReadWriter) error { 575 if err := rw.Writer.Flush(); err != nil { 576 return err 577 } 578 if err := socksFlushReadBuffer(rw.Reader); err != nil { 579 return err 580 } 581 return nil 582 } 583 584 func socksFlushReadBuffer(r *bufio.Reader) error { 585 if r.Buffered() > 0 { 586 return fmt.Errorf("%d bytes left after SOCKS message", r.Buffered()) 587 } 588 return nil 589 } 590 591 func socksReadByte(r *bufio.Reader) (byte, error) { 592 return r.ReadByte() 593 } 594 595 func socksReadBytes(r *bufio.Reader, n int) ([]byte, error) { 596 ret := make([]byte, n) 597 if _, err := io.ReadFull(r, ret); err != nil { 598 return nil, err 599 } 600 return ret, nil 601 } 602 603 func socksReadByteVerify(r *bufio.Reader, descr string, expected byte) error { 604 val, err := socksReadByte(r) 605 if err != nil { 606 return err 607 } 608 if val != expected { 609 return fmt.Errorf("SOCKS message field %s was 0x%02x, not 0x%02x", descr, val, expected) 610 } 611 return nil 612 } 613 614 func socksReadBytesUntil(r *bufio.Reader, end byte) ([]byte, error) { 615 val, err := r.ReadBytes(end) 616 if err != nil { 617 return nil, err 618 } 619 return val, nil 620 } 621 622 func socksPeekByte(r *bufio.Reader) (b byte, err error) { 623 var byteSlice []byte 624 if byteSlice, err = r.Peek(1); err != nil { 625 return 626 } 627 b = byteSlice[0] 628 return 629 } 630 631 // temporaryNetError is used for our custom errors. All such errors are "temporary"; 632 // that is, the listener doesn't need to be torn down when they occur. They also 633 // need to implement the net.Error interface. 634 type temporaryNetError struct { 635 error 636 } 637 638 // Ensure temporaryNetError implements net.Error 639 var _ net.Error = temporaryNetError{} 640 641 func newTemporaryNetError(errMsg string, args ...interface{}) *temporaryNetError { 642 return &temporaryNetError{ 643 error: fmt.Errorf(errMsg, args...), 644 } 645 } 646 647 func (tne temporaryNetError) Timeout() bool { 648 return false 649 } 650 651 func (tne temporaryNetError) Temporary() bool { 652 return true 653 } 654 655 /* 656 * SOCKS4a-specific code 657 */ 658 659 // Read a SOCKS4a connect request. Returns a SocksRequest. 660 func readSocks4aConnect(r *bufio.Reader) (req SocksRequest, err error) { 661 // Validate the version. 662 if err = socksReadByteVerify(r, "version", socks4Version); err != nil { 663 err = newTemporaryNetError("readSocks4aConnect: %s", err.Error()) 664 return 665 } 666 667 var cmdConnect byte 668 if cmdConnect, err = socksReadByte(r); err != nil { 669 err = newTemporaryNetError("readSocks4aConnect: Failed to read connect command: %s", err.Error()) 670 return 671 } 672 if cmdConnect != socksCmdConnect { 673 err = newTemporaryNetError("readSocks4aConnect: SOCKS header had command 0x%02x, not 0x%02x", cmdConnect, socksCmdConnect) 674 return 675 } 676 677 var rawPort []byte 678 if rawPort, err = socksReadBytes(r, 2); err != nil { 679 err = newTemporaryNetError("readSocks4aConnect: Failed to read port: %s", err.Error()) 680 return 681 } 682 port := int(rawPort[0])<<8 | int(rawPort[1])<<0 683 684 var rawHostIP []byte 685 if rawHostIP, err = socksReadBytes(r, 4); err != nil { 686 err = newTemporaryNetError("readSocks4aConnect: Failed to read IP address: %s", err.Error()) 687 return 688 } 689 // If there's a hostname, it comes after the username, so we'll wait a bit 690 // before we process the IP info. 691 692 var usernameBytes []byte 693 usernameBytes, err = socksReadBytesUntil(r, '\x00') 694 if err != nil { 695 err = newTemporaryNetError("readSocks4aConnect: Failed to read username: %s", err.Error()) 696 return 697 } 698 req.Username = string(usernameBytes[:len(usernameBytes)-1]) 699 700 // [Psiphon] 701 // Since we don't need pluggable transport parameters and prefer enabling clients to proxy, 702 // don't parse or validate username/password as PT args. 703 /* 704 req.Args, err = parseClientParameters(req.Username) 705 if err != nil { 706 err = newTemporaryNetError("readSocks4aConnect: Failed to parse client parameters: %s", err.Error()) 707 return 708 } 709 */ 710 // [Psiphon] 711 712 var host string 713 if rawHostIP[0] == 0 && rawHostIP[1] == 0 && rawHostIP[2] == 0 && rawHostIP[3] != 0 { 714 // If the IP is of the form 0.0.0.x (with x nonzero), then a domain name is provided. 715 var hostBytes []byte 716 if hostBytes, err = socksReadBytesUntil(r, '\x00'); err != nil { 717 err = newTemporaryNetError("readSocks4aConnect: Failed to read domain name: %s", err.Error()) 718 return 719 } 720 host = string(hostBytes[:len(hostBytes)-1]) 721 } else { 722 host = net.IPv4(rawHostIP[0], rawHostIP[1], rawHostIP[2], rawHostIP[3]).String() 723 } 724 725 req.Target = fmt.Sprintf("%s:%d", host, port) 726 727 if err = socksFlushReadBuffer(r); err != nil { 728 err = newTemporaryNetError("readSocks4aConnect: Failed to flush buffers: %s", err.Error()) 729 return 730 } 731 732 return 733 } 734 735 // Send a SOCKS4a response with the given code and address. If the IP field 736 // inside addr is not an IPv4 address, the IP portion of the response will be 737 // four zero bytes. 738 func sendSocks4aResponse(w io.Writer, code byte, addr *net.TCPAddr) error { 739 var resp [8]byte 740 resp[0] = socks4ResponseVersion 741 resp[1] = code 742 resp[2] = byte((addr.Port >> 8) & 0xff) 743 resp[3] = byte((addr.Port >> 0) & 0xff) 744 ipv4 := addr.IP.To4() 745 if ipv4 != nil { 746 resp[4] = ipv4[0] 747 resp[5] = ipv4[1] 748 resp[6] = ipv4[2] 749 resp[7] = ipv4[3] 750 } 751 752 if _, err := w.Write(resp[:]); err != nil { 753 err = newTemporaryNetError("sendSocks4aResponse: Failed to write response: %s", err.Error()) 754 return err 755 } 756 757 return nil 758 } 759 760 // Send a SOCKS4a response code 0x5a. 761 func sendSocks4aResponseGranted(w io.Writer, addr *net.TCPAddr) error { 762 return sendSocks4aResponse(w, socks4RequestGranted, addr) 763 } 764 765 // Send a SOCKS4a response code 0x5b (with an all-zero address). 766 func sendSocks4aResponseRejected(w io.Writer) error { 767 emptyAddr := net.TCPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 0} 768 return sendSocks4aResponse(w, socks4RequestRejected, &emptyAddr) 769 }