auth_handler.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package socks
  2. import (
  3. "fmt"
  4. "io"
  5. )
  6. const (
  7. // NoAuth means no authentication is used when connecting
  8. NoAuth = uint8(0)
  9. // UserPassAuth means a user/password is used when connecting
  10. UserPassAuth = uint8(2)
  11. noAcceptable = uint8(255)
  12. userAuthVersion = uint8(1)
  13. authSuccess = uint8(0)
  14. authFailure = uint8(1)
  15. )
  16. // AuthHandler handles socks authenication requests
  17. type AuthHandler interface {
  18. Handle(io.Reader, io.Writer) error
  19. Register(uint8, Authenticator)
  20. }
  21. // StandardAuthHandler loads the default authenticators
  22. type StandardAuthHandler struct {
  23. authenticators map[uint8]Authenticator
  24. }
  25. // NewAuthHandler creates a default auth handler
  26. func NewAuthHandler() AuthHandler {
  27. defaults := make(map[uint8]Authenticator)
  28. defaults[NoAuth] = NewNoAuthAuthenticator()
  29. return &StandardAuthHandler{
  30. authenticators: defaults,
  31. }
  32. }
  33. // Register adds/replaces an Authenticator to use when handling Authentication requests
  34. func (h *StandardAuthHandler) Register(method uint8, a Authenticator) {
  35. h.authenticators[method] = a
  36. }
  37. // Handle gets the methods from the SOCKS5 client and authenicates with the first supported method
  38. func (h *StandardAuthHandler) Handle(bufConn io.Reader, conn io.Writer) error {
  39. methods, err := readMethods(bufConn)
  40. if err != nil {
  41. return fmt.Errorf("Failed to read auth methods: %v", err)
  42. }
  43. // first supported method is used
  44. for _, method := range methods {
  45. authenticator := h.authenticators[method]
  46. if authenticator != nil {
  47. return authenticator.Handle(bufConn, conn)
  48. }
  49. }
  50. // failed to authenticate. No supported authentication type found
  51. conn.Write([]byte{socks5Version, noAcceptable})
  52. return fmt.Errorf("unknown authentication type")
  53. }
  54. // readMethods is used to read the number and type of methods
  55. func readMethods(r io.Reader) ([]byte, error) {
  56. header := []byte{0}
  57. if _, err := r.Read(header); err != nil {
  58. return nil, err
  59. }
  60. numMethods := int(header[0])
  61. methods := make([]byte, numMethods)
  62. _, err := io.ReadAtLeast(r, methods, numMethods)
  63. return methods, err
  64. }