shadow1ng/fscan · error
mssql: login acknowledgement not received
Error message
mssql: login acknowledgement not received
What it means
This error means the TDS login handshake completed without the server sending a LoginAck token (0xAD). The library performs a raw prelogin + Login7 exchange and treats a missing LoginAck as a failed/indeterminate login — typically authentication or protocol negotiation did not conclude successfully even though no explicit error token was parsed.
Source
Thrown at plugins/services/mssql_raw.go:111
if err := mssqlSendPrelogin(conn); err != nil {
return result, err
}
if err := mssqlReadPrelogin(conn); err != nil {
return result, err
}
result.sawPrelogin = true
if err := mssqlSendLogin7(conn, host, username, password); err != nil {
return result, err
}
if err := mssqlReadLoginResponse(conn, result); err != nil {
return result, err
}
if len(result.errors) > 0 {
return result, result.errors[len(result.errors)-1]
}
if !result.sawLoginAck {
return result, fmt.Errorf("mssql: login acknowledgement not received")
}
return result, nil
}
func mssqlSendPrelogin(w io.Writer) error {
fields := map[byte][]byte{
tdsPreloginVersion: {0, 0, 0, 0, 0, 0},
tdsPreloginEncryption: {tdsEncryptNotSupported},
tdsPreloginInstOpt: {0},
tdsPreloginThreadID: {0, 0, 0, 0},
tdsPreloginMARS: {0},
}
keys := make([]int, 0, len(fields))
for k := range fields {
keys = append(keys, int(k))
}
sort.Ints(keys)View on GitHub (pinned to 95cc12e753)
Solutions
- Verify the username/password is correct and the account is not locked — retry with known-good credentials via a full driver (go-mssqldb) to confirm.
- Enable TLS on the login (send encryption-not-supported vs require correctly) or point the check at a server supporting TDS 7.4.
- Capture the raw packet stream (tcpdump/Wireshark) and inspect whether a 0xAD token was actually sent but skipped by the parser.
- Check that the target host:port really is SQL Server and not a proxy/other TDS-speaking service.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before trusting a positive result, require both prelogin and loginack:
res, err := mssqlRawLogin(ctx, host, port, user, pass, timeout)
if err == nil && (!res.sawPrelogin || !res.sawLoginAck) {
// treat as failed login
} Type guard
func loginFullyAcknowledged(r *mssqlRawResult) bool {
return r != nil && r.sawPrelogin && r.sawLoginAck && len(r.errors) == 0
} Try / catch
res, err := mssqlRawLogin(ctx, host, port, user, pass, 5*time.Second)
if err != nil {
if strings.Contains(err.Error(), "login acknowledgement not received") {
// fall back to a full driver or surface 'authentication/protocol failed'
}
return err
} Prevention
- Always check both sawPrelogin and sawLoginAck, not just err == nil.
- Set a realistic deadline so half-open handshakes don't hang.
- Test credentials with a full driver before relying on the raw prober.
- Capture packets when diagnosing missing LoginAck.
When it happens
Trigger: Calling mssqlRawLogin where mssqlReadLoginResponse returns without result.sawLoginAck set: the server returned a response stream containing only env-change/done tokens, the stream ended after an early done token, or parsing stopped after an info token.
Common situations: Server requires encryption or a newer TDS version and silently rejects the plain Login7; connection to a non-SQL-Server service that replies with a malformed token stream; network middleboxes truncating the response.
Related errors
- mssql: invalid prelogin response packet type %d
- mssql: prelogin response missing encryption field
- mssql: unexpected login response packet type %d
- mssql: unexpected login token 0x%02x
- oracle authentication protocol internal error
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/cd4f07b6de8d7c36.
Report an issue: GitHub.