mssql

package
v0.0.0-...-0d458a7 Latest Latest
Warning

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

Go to latest
Published: May 7, 2026 License: Apache-2.0 Imports: 41 Imported by: 0

Documentation

Overview

Package mssql provides SQL Server connection and data collection functionality.

Package mssql provides SQL Server connection and data collection functionality.

Package mssql - Custom NTLM authentication provider with EPA channel binding support. This bridges the go-mssqldb integratedauth interface with our custom ntlmAuth implementation that supports MsvAvChannelBindings and MsvAvTargetName AV_PAIRs.

go-mssqldb's built-in NTLM implementation (integratedauth/ntlm) does NOT include EPA channel binding tokens, causing authentication failures when SQL Server has Extended Protection set to "Required". This provider solves that by injecting the correct CBT (computed from the TLS server certificate) into the NTLM Type3 message.

Package mssql - EPA test orchestrator. Performs raw TDS+TLS+NTLM login attempts with controllable Channel Binding and Service Binding AV_PAIRs to determine EPA enforcement level. This matches the approach used in the Python reference implementation (MssqlExtended.py / MssqlInformer.py).

Package mssql - Custom Kerberos authentication provider for go-mssqldb.

go-mssqldb's built-in krb5 provider (integratedauth/krb5) uses gokrb5's spnego.SPNEGOClient.InitSecContext() which hardcodes ContextFlagInteg and ContextFlagConf in the AP-REQ authenticator checksum. This can cause SQL Server to reject the token with "untrusted domain" errors when the connection is TLS-encrypted or EPA is enabled.

This provider builds the SPNEGO token manually (same approach as the LDAP GSSAPI bind fix in gssapi_krb5.go) with empty GSS flags, giving us full control over the token generation.

Package mssql - Kerberos configuration helpers. Auto-generates a minimal krb5.conf when --domain and --dc are provided but no explicit krb5.conf path is given. This avoids requiring users to manually create /etc/krb5.conf on systems where it doesn't exist.

Package mssql - NTLMv2 authentication with controllable AV_PAIRs for EPA testing. Implements NTLM Type1/Type2/Type3 message generation with the ability to add, remove, or modify MsvAvChannelBindings and MsvAvTargetName AV_PAIRs.

Package mssql - TDS transport layer for raw EPA testing. Implements TDS packet framing and TLS-over-TDS handshake adapter.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AVPairName

func AVPairName(id uint16) string

AVPairName returns a human-readable name for an AV_PAIR ID.

func GenerateKrb5Config

func GenerateKrb5Config(domain, kdcAddress string) (string, error)

generateKrb5Config creates a minimal krb5.conf in a temp file and returns its path. The caller is responsible for cleaning up the file (e.g. via os.Remove or defer).

func IsAuthError

func IsAuthError(err error) bool

IsAuthError checks if the error is an authentication failure that would count toward AD account lockout, as opposed to transport/TLS errors that do not.

func IsEPAPrereqError

func IsEPAPrereqError(err error) bool

IsEPAPrereqError checks if an error is an EPA prerequisite failure.

func TestConnection

func TestConnection(serverInstance, userID, password string, timeout time.Duration) error

TestConnection tests if a connection can be established

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client handles SQL Server connections and data collection

func NewClient

func NewClient(serverInstance, userID, password string) *Client

NewClient creates a new SQL Server client

func (*Client) CheckPort

func (c *Client) CheckPort(ctx context.Context) error

CheckPort performs a quick TCP connectivity check against the SQL Server port. Call this before EPA testing or authentication to skip unreachable servers fast.

func (*Client) Close

func (c *Client) Close() error

Close closes the database connection

func (*Client) CollectServerInfo

func (c *Client) CollectServerInfo(ctx context.Context) (*types.ServerInfo, error)

CollectServerInfo gathers all information about the SQL Server

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect establishes a native go-mssqldb connection to the SQL Server.

func (*Client) DB

func (c *Client) DB() *sql.DB

DB returns the underlying database connection.

func (*Client) DBW

func (c *Client) DBW() *DBWrapper

DBW returns a database wrapper for query methods.

func (*Client) SetCollectFromLinkedServers

func (c *Client) SetCollectFromLinkedServers(collect bool)

func (*Client) SetDNSResolver

func (c *Client) SetDNSResolver(resolver string)

SetDNSResolver sets the DNS resolver IP (e.g. domain controller) for hostname lookups.

func (*Client) SetDebug

func (c *Client) SetDebug(debug bool)

SetDebug enables or disables debug logging (EPA/TLS/NTLM diagnostics)

func (*Client) SetDomain

func (c *Client) SetDomain(domain string)

SetDomain sets the domain for NTLM authentication (needed for EPA testing)

func (*Client) SetEPAResult

func (c *Client) SetEPAResult(result *EPATestResult)

SetEPAResult stores a pre-computed EPA test result on the client. When set, collectEncryptionSettings will use this instead of running EPA tests.

func (*Client) SetKerberosConfig

func (c *Client) SetKerberosConfig(configFile, ccacheFile, keytabFile, realm string)

SetKerberosConfig sets Kerberos authentication parameters.

func (*Client) SetLDAPCredentials

func (c *Client) SetLDAPCredentials(ldapUser, ldapPassword string)

SetLDAPCredentials sets the LDAP credentials used for EPA testing. The ldapUser can be in DOMAIN\user or user@domain format.

func (*Client) SetLogger

func (c *Client) SetLogger(l *slog.Logger)

SetLogger sets the structured logger for the client.

func (*Client) SetNTHash

func (c *Client) SetNTHash(hash []byte)

SetNTHash sets a pre-computed NT hash (16 bytes) for pass-the-hash authentication. When set, NTLM auth will use this hash instead of deriving one from the password.

func (*Client) SetProxyDialer

func (c *Client) SetProxyDialer(d interface {
	DialContext(ctx context.Context, network, address string) (net.Conn, error)
})

SetProxyDialer sets a SOCKS5 proxy dialer for all network operations.

func (*Client) SetVerbose

func (c *Client) SetVerbose(verbose bool)

SetVerbose enables or disables verbose logging

func (*Client) TestEPA

func (c *Client) TestEPA(ctx context.Context) (*EPATestResult, error)

TestEPA performs Extended Protection for Authentication testing using raw TDS+TLS+NTLM connections with controllable Channel Binding and Service Binding. This matches the approach used in the Python reference implementation (MssqlExtended.py / MssqlInformer.py).

Two-path EPA detection flow (per MS-TDS spec):

Path 1 - TDS 7.x normal (most servers):
  PRELOGIN(cleartext) -> TLS-over-TDS handshake -> LOGIN7 with NTLM Type1
  -> server returns NTLM Type2 challenge (contains encryption flag)

Path 2 - TDS 8.0 strict (ForceStrictEncryption=1):
  Direct TLS handshake -> PRELOGIN(inside TLS) -> LOGIN7 with NTLM Type1
  -> server returns NTLM Type2 challenge
  Tried only when Path 1 PRELOGIN fails (strict servers reject cleartext PRELOGIN).

EPA determination logic (for encrypted connections):

  1. Normal login (unmodified NTLM) succeeds -> baseline established
  2. BogusCBT login (garbage channel binding token) fails with "untrusted domain" -> server is checking channel bindings, proceed to step 3 BogusCBT succeeds -> EPA is Off (server ignores channel bindings)
  3. MissingCBT login (no channel binding token at all): Fails with "untrusted domain" -> EPA = Required Succeeds -> EPA = Allowed (accepts but doesn't require CBT)

For unencrypted connections (ENCRYPT_OFF): service binding is tested instead.

type DBWrapper

type DBWrapper struct {
	// contains filtered or unexported fields
}

DBWrapper provides a small interface around database/sql query methods.

func NewDBWrapper

func NewDBWrapper(db *sql.DB) *DBWrapper

NewDBWrapper creates a new database wrapper.

func (*DBWrapper) ExecContext

func (w *DBWrapper) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

ExecContext executes a query without returning rows.

func (*DBWrapper) QueryContext

func (w *DBWrapper) QueryContext(ctx context.Context, query string, args ...interface{}) (Rows, error)

QueryContext executes a query and returns rows.

func (*DBWrapper) QueryRowContext

func (w *DBWrapper) QueryRowContext(ctx context.Context, query string, args ...interface{}) RowScanner

QueryRowContext executes a query and returns a single row.

type EPAPrereqError

type EPAPrereqError struct {
	Err error
}

EPAPrereqError indicates that the EPA prerequisite check failed. When this error is returned, no further EPA tests or MSSQL authentication attempts should be made (to match the Python mssql.py flow and avoid account lockout with invalid credentials).

func (*EPAPrereqError) Error

func (e *EPAPrereqError) Error() string

func (*EPAPrereqError) Unwrap

func (e *EPAPrereqError) Unwrap() error

type EPATestConfig

type EPATestConfig struct {
	Hostname           string
	Port               int
	InstanceName       string
	Domain             string
	Username           string
	Password           string
	NTHash             []byte // Pre-computed NT hash for pass-the-hash (16 bytes)
	TestMode           EPATestMode
	Logger             *slog.Logger
	Verbose            bool
	Debug              bool
	DisableMIC         bool   // Diagnostic: omit MsvAvFlags and MIC from Type3
	UseRawTargetInfo   bool   // Diagnostic: use server's raw target info (no EPA mods, no MIC)
	UseClientTimestamp bool   // Diagnostic: use time.Now() FILETIME instead of server's MsvAvTimestamp
	DNSResolver        string // DNS resolver IP (e.g. domain controller)
	ProxyDialer        interface {
		DialContext(ctx context.Context, network, address string) (net.Conn, error)
	}
}

EPATestConfig holds configuration for a single EPA test connection.

type EPATestMode

type EPATestMode int

EPATestMode controls what AV_PAIRs are included/excluded in the NTLM Type3 message.

const (
	// EPATestNormal includes correct CBT and service binding
	EPATestNormal EPATestMode = iota
	// EPATestBogusCBT includes incorrect CBT hash
	EPATestBogusCBT
	// EPATestMissingCBT excludes MsvAvChannelBindings AV_PAIR entirely
	EPATestMissingCBT
	// EPATestBogusService includes incorrect service name ("cifs")
	EPATestBogusService
	// EPATestMissingService excludes MsvAvTargetName and strips target service
	EPATestMissingService
)

type EPATestResult

type EPATestResult struct {
	UnmodifiedSuccess bool
	NoSBSuccess       bool
	NoCBTSuccess      bool
	ForceEncryption   bool
	StrictEncryption  bool
	EncryptionFlag    byte
	EPAStatus         string
}

EPATestResult holds the results of EPA connection testing

type QueryResult

type QueryResult map[string]interface{}

QueryResult represents a row of query results.

type RowScanner

type RowScanner interface {
	Scan(dest ...interface{}) error
}

RowScanner provides a unified interface for scanning rows.

type Rows

type Rows interface {
	Next() bool
	Scan(dest ...interface{}) error
	Close() error
	Err() error
	Columns() ([]string, error)
}

Rows provides a unified interface for iterating over query results.

Jump to

Keyboard shortcuts

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