Fix behaviour of target.UseKerberos in conjunction with client certs

This commit is contained in:
Erik Geiser
2025-02-20 14:43:17 +01:00
parent d237ce0a2d
commit 09cbab2f99
5 changed files with 25 additions and 13 deletions
+1 -1
View File
@@ -153,7 +153,7 @@ func (c *Credential) DC(ctx context.Context, protocol string) (*Target, error) {
}
func (c *Credential) mustUseKerberos() bool {
return c.Password == "" && c.NTHash == "" && (c.CCache != "" || c.AESKey != "" || c.ClientCert != nil)
return c.Password == "" && c.NTHash == "" && (c.CCache != "" || c.AESKey != "")
}
// Keytab returns the Kerberos keytab containing the AES key and/or NT hash if
+1 -1
View File
@@ -59,7 +59,7 @@ func AuthenticationOptions(
dcerpcOptions = append(dcerpcOptions, dcerpc.WithMechanism(ssp.SPNEGO))
switch {
case target.UseKerberos:
case target.UseKerberos || creds.ClientCert != nil:
spn, err := target.SPN(ctx)
if err != nil {
return nil, fmt.Errorf("build SPN: %w", err)
+14 -10
View File
@@ -13,6 +13,7 @@ import (
"encoding/binary"
"encoding/pem"
"fmt"
"net"
"os"
"strings"
"time"
@@ -99,6 +100,15 @@ func ConnectTo(
return nil, fmt.Errorf("configure TLS: %w", err)
}
if !ldapOpts.TLSConfig.InsecureSkipVerify && net.ParseIP(target.AddressWithoutPort()) != nil {
hostname, err := target.Hostname(ctx)
if err != nil {
return nil, fmt.Errorf("determine target hostname for TLS verification: %w", err)
}
opts.TLSConfig.ServerName = hostname
}
conn, err = connect(target, opts)
if err != nil {
return nil, err
@@ -213,18 +223,12 @@ func bind(
case creds.ClientCert != nil && strings.EqualFold(opts.Scheme, "ldap"):
opts.Debug("authenticating with client certificate via StartTLS")
if !opts.TLSConfig.InsecureSkipVerify {
hostname, err := target.Hostname(ctx)
_, ok := conn.TLSConnectionState()
if !ok {
err = conn.StartTLS(opts.TLSConfig)
if err != nil {
return fmt.Errorf("determine target hostname for TLS verification: %w", err)
return fmt.Errorf("StartTLS: %w", err)
}
opts.TLSConfig.ServerName = hostname
}
err = conn.StartTLS(opts.TLSConfig)
if err != nil {
return fmt.Errorf("StartTLS: %w", err)
}
err = conn.ExternalBind()
+1 -1
View File
@@ -266,7 +266,7 @@ func TestKerberos(t *testing.T) {
User: upn,
PFXFileName: "testdata/someuser@domain.tld.pfx",
},
ShouldUseKerberos: true,
ShouldUseKerberos: false,
},
{
Opts: adauth.Options{
+8
View File
@@ -20,6 +20,14 @@ type Target struct {
ip net.IP
// UseKerberos indicated that Kerberos authentication should be used to
// authenticate to this target.
//
// Warning: `UseKerberos` is false when the only credential available is a
// client certificate because in this case mTLS may also be used to
// authenticate depending on the protocol (e.g. LDAP/HTTPS). If the protocol
// that is used does not support using client certificates directly, you
// should decide for Kerberos authentication if `target.UserKerberos &&
// creds.ClientCert != nil` is `true`. In this case, Kerberos with PKINIT
// will be used.
UseKerberos bool
// Protocol is a string that represents the protocol that is used when
// communicating with this target. It is used to construct the SPN, however,