mirror of
https://github.com/RedTeamPentesting/adauth
synced 2026-06-08 12:20:46 +00:00
104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
package smbauth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/RedTeamPentesting/adauth"
|
|
"github.com/RedTeamPentesting/adauth/dcerpcauth"
|
|
msrpcSMB2 "github.com/oiweiwei/go-msrpc/smb2"
|
|
"github.com/oiweiwei/go-msrpc/ssp"
|
|
"github.com/oiweiwei/go-msrpc/ssp/gssapi"
|
|
"github.com/oiweiwei/go-msrpc/ssp/krb5"
|
|
"github.com/oiweiwei/go-smb2.fork"
|
|
)
|
|
|
|
// Options holds options that modify the behavior of the Dialer function.
|
|
type Options struct {
|
|
// SMBOptions holds options for the SMB dialer. If SMBOptions is nil,
|
|
// encryption/sealing will be enabled. Specify an empty slice to disable
|
|
// this default.
|
|
SMBOptions []msrpcSMB2.DialerOption
|
|
|
|
// KerberosDialer is a custom dialer that is used to request Kerberos
|
|
// tickets.
|
|
KerberosDialer adauth.Dialer
|
|
|
|
// Debug can be set to enable debug output, for example with
|
|
// adauth.NewDebugFunc(...).
|
|
Debug func(string, ...any)
|
|
}
|
|
|
|
func (opts *Options) debug(format string, a ...any) {
|
|
if opts == nil || opts.Debug == nil {
|
|
return
|
|
}
|
|
|
|
opts.Debug(format, a...)
|
|
}
|
|
|
|
// Dialer returns an SMB dialer which is prepared for authentication with the
|
|
// given credentials. The dialer can be further customized with
|
|
// options.SMBDialerOptions.
|
|
func Dialer(
|
|
ctx context.Context, creds *adauth.Credential, target *adauth.Target, options *Options,
|
|
) (*smb2.Dialer, error) {
|
|
smbCreds, err := dcerpcauth.DCERPCCredentials(ctx, creds, &dcerpcauth.Options{
|
|
Debug: options.debug,
|
|
KerberosDialer: options.KerberosDialer,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dialerOptions := options.SMBOptions
|
|
if dialerOptions == nil {
|
|
dialerOptions = append(dialerOptions, msrpcSMB2.WithSeal())
|
|
}
|
|
|
|
switch {
|
|
case target.UseKerberos || creds.ClientCert != nil:
|
|
spn, err := target.SPN(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("build SPN: %w", err)
|
|
}
|
|
|
|
options.debug("Using Kerberos with SPN %q", spn)
|
|
|
|
krbConf, err := creds.KerberosConfig(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("generate Kerberos config: %w", err)
|
|
}
|
|
|
|
dialerOptions = append(dialerOptions, msrpcSMB2.WithSecurity(
|
|
gssapi.WithTargetName(spn),
|
|
gssapi.WithCredential(smbCreds),
|
|
gssapi.WithMechanismFactory(ssp.KRB5, &krb5.Config{
|
|
KRB5Config: krbConf,
|
|
CCachePath: creds.CCache,
|
|
DisablePAFXFAST: true,
|
|
KDCDialer: options.KerberosDialer,
|
|
AnyServiceClassSPN: true,
|
|
}),
|
|
))
|
|
|
|
return msrpcSMB2.NewDialer(dialerOptions...), nil
|
|
default:
|
|
options.debug("Using NTLM")
|
|
|
|
secOptions := []gssapi.ContextOption{
|
|
gssapi.WithCredential(smbCreds),
|
|
gssapi.WithMechanismFactory(ssp.NTLM),
|
|
}
|
|
|
|
spn, err := target.SPN(ctx)
|
|
if err == nil {
|
|
secOptions = append(secOptions, gssapi.WithTargetName(spn))
|
|
}
|
|
|
|
dialerOptions = append(dialerOptions, msrpcSMB2.WithSecurity(secOptions...))
|
|
|
|
return msrpcSMB2.NewDialer(dialerOptions...), nil
|
|
}
|
|
}
|