network.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package client
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/jcmturner/gokrb5/iana/errorcode"
  6. "github.com/jcmturner/gokrb5/messages"
  7. "math/rand"
  8. "net"
  9. "time"
  10. )
  11. // Send bytes to the KDC.
  12. func (cl *Client) SendToKDC(b []byte) ([]byte, error) {
  13. var rb []byte
  14. var kdcs []string
  15. for _, r := range cl.Config.Realms {
  16. if r.Realm == cl.Config.LibDefaults.Default_realm {
  17. kdcs = r.Kdc
  18. break
  19. }
  20. }
  21. if len(kdcs) < 1 {
  22. return rb, fmt.Errorf("No KDCs defined in configuration for realm: %v", cl.Config.LibDefaults.Default_realm)
  23. }
  24. var kdc string
  25. if len(kdcs) > 1 {
  26. //Select one of the KDCs at random
  27. kdc = kdcs[rand.Intn(len(kdcs))]
  28. } else {
  29. kdc = kdcs[0]
  30. }
  31. if cl.Config.LibDefaults.Udp_preference_limit == 1 {
  32. //1 means we should always use TCP
  33. rb, errtcp := sendTCP(kdc, b)
  34. if errtcp != nil {
  35. return rb, fmt.Errorf("Failed to communicate with KDC %v via TDP (%v)", kdc, errtcp)
  36. }
  37. if len(rb) < 1 {
  38. return rb, fmt.Errorf("No response data from KDC %v", kdc)
  39. }
  40. return rb, nil
  41. }
  42. if len(b) <= cl.Config.LibDefaults.Udp_preference_limit {
  43. //Try UDP first, TCP second
  44. rb, errudp := sendUDP(kdc, b)
  45. if errudp != nil {
  46. rb, errtcp := sendTCP(kdc, b)
  47. if errtcp != nil {
  48. return rb, fmt.Errorf("Failed to communicate with KDC %v via UDP (%v) and then via TDP (%v)", kdc, errudp, errtcp)
  49. }
  50. }
  51. var KRBErr messages.KRBError
  52. if err := KRBErr.Unmarshal(rb); err == nil {
  53. if KRBErr.ErrorCode == errorcode.KRB_ERR_RESPONSE_TOO_BIG {
  54. rb, errtcp := sendTCP(kdc, b)
  55. if errtcp != nil {
  56. return rb, fmt.Errorf("Failed to communicate with KDC %v. Response too big for UDP and errored when using TCP: %v ", kdc, errtcp)
  57. }
  58. }
  59. }
  60. if len(rb) < 1 {
  61. return rb, fmt.Errorf("No response data from KDC %v", kdc)
  62. }
  63. return rb, nil
  64. }
  65. //Try TCP first, UDP second
  66. rb, errtcp := sendTCP(kdc, b)
  67. if errtcp != nil {
  68. rb, errudp := sendUDP(kdc, b)
  69. if errudp != nil {
  70. return rb, fmt.Errorf("Failed to communicate with KDC %v via TCP (%v) and then via UDP (%v)", kdc, errtcp, errudp)
  71. }
  72. }
  73. if len(rb) < 1 {
  74. return rb, fmt.Errorf("No response data from KDC %v", kdc)
  75. }
  76. return rb, nil
  77. }
  78. // Send the bytes to the KDC over UDP.
  79. func sendUDP(kdc string, b []byte) ([]byte, error) {
  80. var r []byte
  81. udpAddr, err := net.ResolveUDPAddr("udp", kdc)
  82. if err != nil {
  83. return r, fmt.Errorf("Error resolving KDC address: %v", err)
  84. }
  85. conn, err := net.DialUDP("udp", nil, udpAddr)
  86. if err != nil {
  87. return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
  88. }
  89. defer conn.Close()
  90. conn.SetDeadline(time.Now().Add(time.Duration(5 * time.Second)))
  91. _, err = conn.Write(b)
  92. if err != nil {
  93. return r, fmt.Errorf("Error sending to KDC: %v", err)
  94. }
  95. udpbuf := make([]byte, 4096)
  96. n, _, err := conn.ReadFrom(udpbuf)
  97. r = udpbuf[:n]
  98. if err != nil {
  99. return r, fmt.Errorf("Sending over UDP failed: %v", err)
  100. }
  101. return r, nil
  102. }
  103. // Send the bytes to the KDC over TCP.
  104. func sendTCP(kdc string, b []byte) ([]byte, error) {
  105. var r []byte
  106. tcpAddr, err := net.ResolveTCPAddr("tcp", kdc)
  107. if err != nil {
  108. return r, fmt.Errorf("Error resolving KDC address: %v", err)
  109. }
  110. conn, err := net.DialTCP("tcp", nil, tcpAddr)
  111. if err != nil {
  112. return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
  113. }
  114. defer conn.Close()
  115. conn.SetDeadline(time.Now().Add(time.Duration(5 * time.Second)))
  116. _, err = conn.Write(b)
  117. if err != nil {
  118. return r, fmt.Errorf("Error sending to KDC: %v", err)
  119. }
  120. tcpbuf := bytes.NewBuffer(make([]byte, 4096))
  121. n, err := conn.ReadFrom(tcpbuf)
  122. r = tcpbuf.Bytes()[:n]
  123. if err != nil {
  124. return r, fmt.Errorf("Sending over TCP failed: %v", err)
  125. }
  126. return r, nil
  127. }