adauth

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2025 License: MIT Imports: 21 Imported by: 3

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.

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 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 *rsa.PrivateKey
	// 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) Keytab

func (c *Credential) Keytab() (*keytab.Keytab, error)

Keytab returns the Kerberos keytab containing the AES key and/or NT hash if they were supplied. If a password is supplied, the keys/hashes are not derived and the keytab will be empty. 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).

type Dialer added in v0.2.1

type Dialer interface {
	Dial(net string, addr string) (net.Conn, error)
}

type Options

type Options struct {
	// Username (with domain) in one of the following formats:
	// `UPN`, `domain\user`, `domain/user` or `user`
	User             string
	Password         string
	NTHash           string
	AESKey           string
	CCache           string
	DomainController string
	ForceKerberos    bool
	PFXFileName      string
	PFXPassword      string

	Debug    func(fmt string, a ...any)
	Resolver Resolver
	// contains filtered or unexported fields
}

Options holds command line options that are used to determine authentication credentials and target.

func (*Options) Domain

func (opts *Options) Domain() string

UPN returns the user's domain. Domain may return an empty string.

func (*Options) NoTarget

func (opts *Options) NoTarget() (*Credential, error)

NoTarget returns the user credentials without supplementing it with information from a target.

func (*Options) RegisterFlags

func (opts *Options) RegisterFlags(flagset *pflag.FlagSet)

RegisterFlags registers authentication flags to a pflag.FlagSet such as the default flagset `pflag.CommandLine`.

func (*Options) UPN

func (opts *Options) UPN() string

UPN returns the user's universal principal name. UPN may return an empty string.

func (*Options) Username

func (opts *Options) Username() string

Username returns the user's name. Username may return an empty string.

func (*Options) WithDCTarget

func (opts *Options) WithDCTarget(ctx context.Context, protocol string) (*Credential, *Target, error)

WithDCTarget returns credentials and the domain controller for the corresponding domain as the target.

func (*Options) WithTarget

func (opts *Options) WithTarget(ctx context.Context, protocol string, target string) (*Credential, *Target, error)

WithTarget returns credentials and the specified target.

type Resolver

type Resolver interface {
	LookupAddr(ctx context.Context, addr string) ([]string, error)
	LookupIP(ctx context.Context, network string, host string) ([]net.IP, error)
	LookupSRV(ctx context.Context, service string, proto string, name string) (string, []*net.SRV, error)
}

type Target

type Target struct {
	// Port holds the target's port which may be empty.
	Port string

	// 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,
	// some protocol name corrections may be applied in this case, such as 'smb'
	// -> 'cifs'.
	Protocol string

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

Target holds information about the authentication target.

func NewTarget

func NewTarget(protocol string, target string) *Target

NewTarget creates a new target. The provided protocol is used to construct the SPN, however, some protocol name corrections may be applied in this case, such as 'smb' -> 'cifs'. The target parameter may or may not contain a port and the protocol string will *not* influence the port of the resulting Target.

func (*Target) Address

func (t *Target) Address() string

Address returns the address including the port if available. It will contain either a hostname or an IP address depending on how the target was constructed.

func (*Target) AddressWithoutPort

func (t *Target) AddressWithoutPort() string

AddressWithoutPort is like Address but without the port.

func (*Target) Hostname

func (t *Target) Hostname(ctx context.Context) (string, error)

Hostname returns the target's hostname. If only the IP address is known, a lookup will be performed.

func (*Target) IP

func (t *Target) IP(ctx context.Context) (net.IP, error)

IP returns the target's IP address. If only the hostname is known, a lookup will be performed.

func (*Target) SPN

func (t *Target) SPN(ctx context.Context) (string, error)

SPN returns the target's service principal name. The protocol part of the SPN *may* be changed to the generic 'host' in order to align with the SPN of service tickets in a CCACHE file. Some protocol name translations will also be applied such as 'smb' -> 'cifs'.

Directories

Path Synopsis
Package compat holds compatibility functions for interoperability between forks or different libraries for the same purpose.
Package compat holds compatibility functions for interoperability between forks or different libraries for the same purpose.
examples
smb
Package othername is a minimal and incomplete implementation of the otherName SAN extension.
Package othername is a minimal and incomplete implementation of the otherName SAN extension.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL