|
|
@@ -6,6 +6,7 @@ import (
|
|
|
"fmt"
|
|
|
"io"
|
|
|
"net"
|
|
|
+ "strings"
|
|
|
"time"
|
|
|
|
|
|
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
|
|
@@ -67,88 +68,52 @@ func (cl *Client) sendToKDC(b []byte, realm string) ([]byte, error) {
|
|
|
return rb, nil
|
|
|
}
|
|
|
|
|
|
-// dialKDCTCP establishes a UDP connection to a KDC.
|
|
|
-func dialKDCUDP(count int, kdcs map[int]string) (*net.UDPConn, error) {
|
|
|
- i := 1
|
|
|
- for i <= count {
|
|
|
- udpAddr, err := net.ResolveUDPAddr("udp", kdcs[i])
|
|
|
- if err != nil {
|
|
|
- return nil, fmt.Errorf("error resolving KDC address: %v", err)
|
|
|
- }
|
|
|
-
|
|
|
- conn, err := net.DialTimeout("udp", udpAddr.String(), 5*time.Second)
|
|
|
- if err == nil {
|
|
|
- if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- // conn is guaranteed to be a UDPConn
|
|
|
- return conn.(*net.UDPConn), nil
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- return nil, errors.New("error in getting a UDP connection to any of the KDCs")
|
|
|
-}
|
|
|
-
|
|
|
-// dialKDCTCP establishes a TCP connection to a KDC.
|
|
|
-func dialKDCTCP(count int, kdcs map[int]string) (*net.TCPConn, error) {
|
|
|
- i := 1
|
|
|
- for i <= count {
|
|
|
- tcpAddr, err := net.ResolveTCPAddr("tcp", kdcs[i])
|
|
|
- if err != nil {
|
|
|
- return nil, fmt.Errorf("error resolving KDC address: %v", err)
|
|
|
- }
|
|
|
-
|
|
|
- conn, err := net.DialTimeout("tcp", tcpAddr.String(), 5*time.Second)
|
|
|
- if err == nil {
|
|
|
- if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- // conn is guaranteed to be a TCPConn
|
|
|
- return conn.(*net.TCPConn), nil
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- return nil, errors.New("error in getting a TCP connection to any of the KDCs")
|
|
|
-}
|
|
|
-
|
|
|
// sendKDCUDP sends bytes to the KDC via UDP.
|
|
|
func (cl *Client) sendKDCUDP(realm string, b []byte) ([]byte, error) {
|
|
|
var r []byte
|
|
|
- count, kdcs, err := cl.Config.GetKDCs(realm, false)
|
|
|
- if err != nil {
|
|
|
- return r, err
|
|
|
- }
|
|
|
- conn, err := dialKDCUDP(count, kdcs)
|
|
|
+ _, kdcs, err := cl.Config.GetKDCs(realm, false)
|
|
|
if err != nil {
|
|
|
return r, err
|
|
|
}
|
|
|
- r, err = cl.sendUDP(conn, b)
|
|
|
+ r, err = dialSendUDP(kdcs, b)
|
|
|
if err != nil {
|
|
|
return r, err
|
|
|
}
|
|
|
return checkForKRBError(r)
|
|
|
}
|
|
|
|
|
|
-// sendKDCTCP sends bytes to the KDC via TCP.
|
|
|
-func (cl *Client) sendKDCTCP(realm string, b []byte) ([]byte, error) {
|
|
|
- var r []byte
|
|
|
- count, kdcs, err := cl.Config.GetKDCs(realm, true)
|
|
|
- if err != nil {
|
|
|
- return r, err
|
|
|
- }
|
|
|
- conn, err := dialKDCTCP(count, kdcs)
|
|
|
- if err != nil {
|
|
|
- return r, err
|
|
|
- }
|
|
|
- rb, err := cl.sendTCP(conn, b)
|
|
|
- if err != nil {
|
|
|
- return r, err
|
|
|
+// dialSendUDP establishes a UDP connection to a KDC.
|
|
|
+func dialSendUDP(kdcs map[int]string, b []byte) ([]byte, error) {
|
|
|
+ var errs []string
|
|
|
+ for i := 1; i <= len(kdcs); i++ {
|
|
|
+ udpAddr, err := net.ResolveUDPAddr("udp", kdcs[i])
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error resolving KDC address: %v", err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ conn, err := net.DialTimeout("udp", udpAddr.String(), 5*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error setting dial timeout on connection to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error setting deadline on connection to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // conn is guaranteed to be a UDPConn
|
|
|
+ rb, err := sendUDP(conn.(*net.UDPConn), b)
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error sneding to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ return rb, nil
|
|
|
}
|
|
|
- return checkForKRBError(rb)
|
|
|
+ return nil, fmt.Errorf("error sending to a KDC: %s", strings.Join(errs, "; "))
|
|
|
}
|
|
|
|
|
|
// sendUDP sends bytes to connection over UDP.
|
|
|
-func (cl *Client) sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) {
|
|
|
+func sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) {
|
|
|
var r []byte
|
|
|
defer conn.Close()
|
|
|
_, err := conn.Write(b)
|
|
|
@@ -167,8 +132,52 @@ func (cl *Client) sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) {
|
|
|
return r, nil
|
|
|
}
|
|
|
|
|
|
+// sendKDCTCP sends bytes to the KDC via TCP.
|
|
|
+func (cl *Client) sendKDCTCP(realm string, b []byte) ([]byte, error) {
|
|
|
+ var r []byte
|
|
|
+ _, kdcs, err := cl.Config.GetKDCs(realm, true)
|
|
|
+ if err != nil {
|
|
|
+ return r, err
|
|
|
+ }
|
|
|
+ r, err = dialSendTCP(kdcs, b)
|
|
|
+ if err != nil {
|
|
|
+ return r, err
|
|
|
+ }
|
|
|
+ return checkForKRBError(r)
|
|
|
+}
|
|
|
+
|
|
|
+// dialKDCTCP establishes a TCP connection to a KDC.
|
|
|
+func dialSendTCP(kdcs map[int]string, b []byte) ([]byte, error) {
|
|
|
+ var errs []string
|
|
|
+ for i := 1; i <= len(kdcs); i++ {
|
|
|
+ tcpAddr, err := net.ResolveTCPAddr("tcp", kdcs[i])
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error resolving KDC address: %v", err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ conn, err := net.DialTimeout("tcp", tcpAddr.String(), 5*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error setting dial timeout on connection to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error setting deadline on connection to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // conn is guaranteed to be a TCPConn
|
|
|
+ rb, err := sendTCP(conn.(*net.TCPConn), b)
|
|
|
+ if err != nil {
|
|
|
+ errs = append(errs, fmt.Sprintf("error sneding to %s: %v", kdcs[i], err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ return rb, nil
|
|
|
+ }
|
|
|
+ return nil, errors.New("error in getting a TCP connection to any of the KDCs")
|
|
|
+}
|
|
|
+
|
|
|
// sendTCP sends bytes to connection over TCP.
|
|
|
-func (cl *Client) sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) {
|
|
|
+func sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) {
|
|
|
defer conn.Close()
|
|
|
var r []byte
|
|
|
// RFC 4120 7.2.2 specifies the first 4 bytes indicate the length of the message in big endian order.
|