74 lines
2.2 KiB
Go
74 lines
2.2 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/jcmturner/gokrb5/v8/client"
|
|
"github.com/jcmturner/gokrb5/v8/config"
|
|
)
|
|
|
|
// runAuthProbe performs a Login (AS-REQ + preauth) and, if a targetService
|
|
// is supplied, a TGS-REQ. kdcHosts maps reachable KDC hostnames to their
|
|
// TCP port so we can populate the krb5 config without doing DNS again.
|
|
func runAuthProbe(ctx context.Context, realm, principal, password, targetService string,
|
|
kdcHosts map[string]uint16, timeout time.Duration) *AuthProbeResult {
|
|
res := &AuthProbeResult{Attempted: true, Principal: principal, TargetService: targetService}
|
|
|
|
username := principal
|
|
if i := strings.LastIndex(principal, "@"); i >= 0 {
|
|
username = principal[:i]
|
|
}
|
|
|
|
cfg := config.New()
|
|
cfg.LibDefaults.DefaultRealm = realm
|
|
cfg.LibDefaults.NoAddresses = true
|
|
cfg.LibDefaults.TicketLifetime = 10 * time.Minute
|
|
cfg.LibDefaults.Clockskew = 5 * time.Minute
|
|
cfg.LibDefaults.UDPPreferenceLimit = 1 // force TCP
|
|
cfg.LibDefaults.DefaultTktEnctypeIDs = preferredEnctypes
|
|
cfg.LibDefaults.DefaultTGSEnctypeIDs = preferredEnctypes
|
|
cfg.LibDefaults.PermittedEnctypeIDs = preferredEnctypes
|
|
|
|
realmCfg := config.Realm{Realm: realm}
|
|
for host, port := range kdcHosts {
|
|
realmCfg.KDC = append(realmCfg.KDC, host+":"+strconv.Itoa(int(port)))
|
|
}
|
|
cfg.Realms = []config.Realm{realmCfg}
|
|
cfg.DomainRealm = config.DomainRealm{strings.ToLower(realm): realm}
|
|
|
|
start := time.Now()
|
|
cl := client.NewWithPassword(username, realm, password, cfg,
|
|
client.DisablePAFXFAST(true))
|
|
|
|
loginErr := cl.Login()
|
|
res.Latency = time.Since(start)
|
|
if loginErr != nil {
|
|
res.Error = loginErr.Error()
|
|
if code, name, ok := krbErrorInfo(loginErr); ok {
|
|
res.ErrorCode = code
|
|
res.ErrorName = name
|
|
}
|
|
return res
|
|
}
|
|
res.TGTAcquired = true
|
|
|
|
spn := targetService
|
|
if spn == "" {
|
|
// Self-test: request a fresh TGT (krbtgt/REALM@REALM).
|
|
spn = fmt.Sprintf("krbtgt/%s", realm)
|
|
}
|
|
if _, _, err := cl.GetServiceTicket(spn); err != nil {
|
|
res.Error = fmt.Sprintf("TGS failed for %s: %v", spn, err)
|
|
if code, name, ok := krbErrorInfo(err); ok {
|
|
res.ErrorCode = code
|
|
res.ErrorName = name
|
|
}
|
|
return res
|
|
}
|
|
res.TGSAcquired = true
|
|
return res
|
|
}
|