adauth

package module
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2025 License: MIT Imports: 24 Imported by: 9

README

adauth

Active Directory Authentication Library

Release Go Doc Software License Go Report Card

Warning: The API of this library is not yet stable. Expect breaking changes.

adauth is a Go library for active directory authentication. It can be used to quickly set up authentication options:

var (
    ctx = context.Background()
    authOpts = &adauth.Options{}
)

authOpts.RegisterFlags(pflag.CommandLine)
pflag.Parse()
//     --aes-key hex key       Kerberos AES hex key
//     --ccache file           Kerberos CCache file name (defaults to $KRB5CCNAME, currently unset)
//     --dc string             Domain controller
// -k, --kerberos              Use Kerberos authentication
// -H, --nt-hash hash          NT hash ('NT', ':NT' or 'LM:NT')
// -p, --password string       Password
//     --pfx file              Client certificate and private key as PFX file
//     --pfx-password string   Password for PFX file
// -u, --user user@domain      Username ('user@domain', 'domain\user', 'domain/user' or 'user')

// Credentials for an arbitrary target:
creds, target, err := authOpts.WithTarget(ctx, "smb", pflag.Arg(0))
if err != nil { /* error handling */ }


// Only credentials are needed, no specific target:
creds, err := authOpts.NoTarget()
if err != nil { /* error handling */ }

// Credentials to authenticate to the corresponding DC:
creds, dc, err := authOpts.WithDCTarget(ctx, "ldap")
if err != nil { /* error handling */ }

It deduces as much information from the parameters as possible. For example, Kerberos authentication is possible even when specifying the target via IP address if reverse lookups are possible. Similarly, the domain can be omitted when the target hostname contains the domain.

The library also contains helper packages for LDAP, SMB and DCERPC, a Kerebros PKINIT implementation as well as helpers for creating and writing CCache files (see examples).

Features

  • Kerberos:
    • PKINIT
    • UnPAC-the-Hash
    • Pass-the-Hash (RC4/NT or AES key)
    • CCache (containing TGT or ST)
    • SOCKS5 support
  • NTLM:
    • Pass-the-Hash
  • LDAP:
    • Kerberos, NTLM, Simple Bind
    • mTLS Authentication / Pass-the-Certificate (LDAPS or LDAP+StartTLS)
    • Channel Binding (Kerberos and NTLM)
    • SOCKS5 support
  • SMB:
    • Kerberos, NTLM
    • Signing and Sealing
    • SOCKS5 support
  • DCERPC:
    • Kerberos, NTLM
    • Raw endpoits (with port mapping)
    • Named pipes (SMB)
    • Signing and Sealing
    • SOCKS5 support

Caveats

LDAP:

The LDAP helper package does not support authentication using RC4 service tickets from ccache, since Windows returns unsupported GSSAPI wrap tokens during the SASL handshake when presented with an RC4 service ticket (see github.com/jcmturner/gokrb5/pull/498).

However, it should still be possible to request an AES256 service ticket instead, even when an NT hash was used for pre-authentication . Unfortunately, impacket always requests RC4 tickets. This behavior can be changed by adding int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value), as the first element of this list and this list for S4U tickets.

The LDAP library does not (yet) support LDAP signing, but it supports channel binding for LDAPS and LDAP+StartTLS which is typically sufficient as a workaround unless the server lacks a TLS certificate.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodePFX added in v0.5.1

func DecodePFX(pfxData []byte, password string) (privateKey any, cert *x509.Certificate, chain []*x509.Certificate, err error)

DecodePFX loads the private key, certificate and certificate chain from PFX bytes that may or may not be protected by a password.

func NewDebugFunc

func NewDebugFunc(enabled *bool, writer io.Writer, colored bool) func(string, ...any)

NewDebugFunc creates a debug output handler.

Types

type ContextDialer added in v0.2.1

type ContextDialer interface {
	DialContext(ctx context.Context, net string, addr string) (net.Conn, error)
	Dial(net string, addr string) (net.Conn, error)
}

func AsContextDialer added in v0.2.1

func AsContextDialer(d Dialer) ContextDialer

AsContextDialer converts a Dialer into a ContextDialer that either uses the dialer's DialContext method if implemented or it uses a DialContext method that simply calls Dial ignoring the context.

func DialerWithSOCKS5ProxyIfSet added in v0.2.1

func DialerWithSOCKS5ProxyIfSet(socks5Server string, forward *net.Dialer) ContextDialer

DialerWithSOCKS5ProxyIfSet returns a SOCKS5 dialer if socks5Server is not empty and it returns the forward dialer otherwise.

func SOCKS5Dialer added in v0.2.1

func SOCKS5Dialer(
	network string,
	address string,
	auth *proxy.Auth,
	forward *net.Dialer,
) ContextDialer

SOCKS5Dialer returns a SOCKS5 dialer.

type Credential

type Credential struct {
	// Username is the username without the domain.
	Username string
	// Password contains the users cleartext password if available.
	Password string
	// Domain holds the user's domain.
	Domain string
	// NTHash holds the user's NT hash or Kerberos RC4 key if available.
	NTHash string
	// AESKey holds the user's Kerberos AES128 or AES256 key if available.
	AESKey string
	// CCache contains the path to the user's CCache file.
	CCache string
	// ClientCert holds a client certificate for Kerberos or LDAP authentication if available.
	ClientCert *x509.Certificate
	// ClientCertKey holds the private key that corresponds to ClientCert.
	ClientCertKey any
	// CACerts holds CA certificates that were loaded alongside the ClientCert.
	CACerts []*x509.Certificate

	// PasswordIsEmptyString is true when an empty Password field should not be
	// interpreted as a missing password but as a password that happens to be
	// empty.
	PasswordIsEmtpyString bool
	// CCacheIsFromEnv indicates whether the CCache was set explicitly or
	// implicitly through an environment variable.
	CCacheIsFromEnv bool

	// Resolver can be used to set an alternative DNS resolver. If empty,
	// net.DefaultResolver is used.
	Resolver Resolver
	// contains filtered or unexported fields
}

Credential represents Active Directory credentials.

func CredentialFromPFX

func CredentialFromPFX(
	username string, domain string, pfxFile string, pfxPassword string,
) (*Credential, error)

CredentialFromPFX creates a Credential structure for certificate-based authentication based on a PFX file.

func CredentialFromPFXBytes

func CredentialFromPFXBytes(
	username string, domain string, pfxData []byte, pfxPassword string,
) (*Credential, error)

CredentialFromPFX creates a Credential structure for certificate-based authentication based on PFX data.

func (*Credential) DC

func (c *Credential) DC(ctx context.Context, protocol string) (*Target, error)

DC returns the domain controller of the credential's domain as a target.

func (*Credential) ImpacketLogonName

func (c *Credential) ImpacketLogonName() string

ImpacketLogonName is the Impacket-style logon name (domain/username).

func (*Credential) KerberosConfig

func (c *Credential) KerberosConfig(ctx context.Context) (*config.Config, error)

KerberosConfig returns the Kerberos configuration for the credential's domain. For compatibility with other Kerberos libraries, see the `compat` package.

func (*Credential) LogonName

func (c *Credential) LogonName() string

LogonName is the legacy logon name (domain\username).

func (*Credential) LogonNameWithUpperCaseDomain

func (c *Credential) LogonNameWithUpperCaseDomain() string

LogonNameWithUpperCaseDomain is like LogonName with the domain capitalized for compatibility with the Kerberos library (DOMAIN\username).

func (*Credential) SetDC

func (c *Credential) SetDC(dc string)

SetDC configures a specific domain controller for this credential.

func (*Credential) UPN

func (c *Credential) UPN() string

UPN is the user principal name (username@domain). If the credential does not contain a domain, only the username is returned. If username and domain are empty, the UPN will be empty, too.

type Dialer