Skip to content

275 Refactor SASL authentication handling and remove redundant tests - #282

Merged
maneesha-xyz merged 7 commits into
OpenGovMail:mainfrom
manupawickramasinghe:main
May 23, 2026
Merged

275 Refactor SASL authentication handling and remove redundant tests#282
maneesha-xyz merged 7 commits into
OpenGovMail:mainfrom
manupawickramasinghe:main

Conversation

@manupawickramasinghe

@manupawickramasinghe manupawickramasinghe commented May 15, 2026

Copy link
Copy Markdown
Contributor

📌 Description

Implements SASL multi-step authentication support for PLAIN and LOGIN mechanisms with per-connection state tracking. Previously, LOGIN only returned "not fully implemented" and PLAIN continuation requests never completed authentication. #275


🔍 Changes Made

  • Added authState struct to track multi-step auth per connection (mechanism, step, username)
  • Added handleCont() — dispatches CONTINUE commands to the correct handler based on stored auth state
  • Implemented handleLoginCont() — full two-step LOGIN flow: Username: prompt → Password: prompt → authenticate
  • Fixed PLAIN without initial response — now accepts CONT with credentials and completes auth
  • Fixed OAUTHBEARER/XOAUTH2 without initial response — handles CONT prompt properly
  • Auth state cleaned up after completion or failure
  • Restored go 1.25.0 and golang.org/x/sync v0.20.0 (were downgraded by bot commits)
  • Wired the CONT command into the SASL command dispatcher

✅ Checklist (Email System)

  • Core IMAP commands tested (LOGIN, CAPABILITY, LIST, SELECT, FETCH, LOGOUT)
  • Authentication is tested
  • Docker build & run validated
  • Configuration loading verified for default and custom paths
  • Persistent storage with Docker volume verified
  • Error handling and logging verified
  • Documentation updated

🧪 Testing Instructions

  1. go test ./internal/sasl/... -v -count=1 — 35 unit tests
  2. go test ./test/integration/sasl/... -v -count=1 — 10 integration tests
  3. PLAIN with initial response: AUTH <id> PLAIN service=smtp resp=<base64>
  4. PLAIN without initial response: AUTH <id> PLAIN service=smtpCONT <id> <base64>
  5. LOGIN multi-step: AUTH <id> LOGIN service=smtpCONT <id> <base64-user>CONT <id> <base64-pass>

📷 Screenshots / Logs

Environment

  • Go version: 1.25.10
  • Docker: Full clean (3.7GB reclaimed — containers, images, volumes)
  • Working directory: Raven repo, branch fix/restore-go-version

Build & Vet

go build ./...  → SUCCESS
go vet ./...    → SUCCESS

SASL Unit Tests — 35/35 PASS

Test Status
TestNewServer PASS
TestServerStartShutdown PASS
TestServerShutdownIdempotent PASS
TestVersionHandshake PASS
TestCPIDCommand PASS
TestPlainAuthenticationSuccess PASS
TestPlainAuthenticationWithDomain PASS
TestPlainAuthenticationFailure PASS
TestPlainAuthenticationWithAuthzid PASS
TestPlainAuthenticationInvalidBase64 PASS
TestPlainAuthenticationMalformedCredentials (3 subtests) PASS
TestPlainAuthenticationContinuationRequest PASS
TestLoginMechanism PASS
TestUnsupportedMechanism (4 subtests) PASS
TestAuthMechanismCaseInsensitive (4 subtests) PASS
TestInvalidAuthCommand PASS
TestConcurrentConnections PASS
TestConnectionTimeout PASS
TestAuthenticationAPIError (5 subtests) PASS
TestMultipleCommandsInSession PASS
TestTCPAuthentication PASS
TestBothListeners PASS
TestTCPConcurrentConnections PASS
TestServerWithSASLScope (3 subtests) PASS
TestSASLScopeConfiguration (3 subtests) PASS

SASL Integration Tests — 10/10 PASS

Test Status Key Verification
TestSASLAuthenticationFlow PASS Version handshake → CPID → PLAIN auth → OK
TestSASLAuthenticationFailure PASS Invalid creds → FAIL
TestSASLPlainWithoutInitialResponse PASS AUTH PLAIN (no resp) → CONT → send creds → OK
TestSASLInvalidMechanism PASS CRAM-MD5/DIGEST-MD5/GSSAPI/NTLM → FAIL
TestSASLMalformedCredentials PASS Invalid base64, missing fields → FAIL
TestSASLConcurrentConnections PASS 5 connections all auth successfully
TestSASLServerShutdownGraceful PASS Clean shutdown, socket cleanup, idempotent
TestSASLAuthenticationServerTimeout PASS Timeout handled
TestSASLDomainHandling PASS Domain appended correctly
TestSASLLoginMechanism PASS AUTH LOGIN → Username: → Password: → OK

Full Test Suite

raven/internal/sasl                   OK    3.505s
raven/test/integration/sasl           OK   12.610s
raven/internal/server                 OK    1.166s
raven/internal/server/auth            OK   27.096s
raven/internal/server/extension       OK   10.558s
raven/internal/server/mailbox         OK   33.671s
raven/internal/server/message         OK   52.468s
raven/internal/server/uid             OK   12.044s
raven/test/integration/delivery       OK    1.366s
raven/test/integration/server         OK    2.307s
raven/test/e2e                        OK    7.371s
raven/internal/delivery/parser        OK    0.085s
raven/internal/delivery/storage       OK    4.031s
raven/internal/auth/oauthbearer       OK    1.702s
raven/internal/conf                   OK    0.018s

Pre-existing failures (unrelated to this change):

  • raven/internal/db — Fails on main too (test data setup issue)
  • raven/internal/delivery/lmtp — Times out at 300s on main too (LMTP session test hang)

manupawickramasinghe and others added 3 commits May 13, 2026 17:07
The ClientState struct is a plain data container with no business logic.
Its tests only verified Go zero-values and struct field assignment, which
are language features, not application logic.
Adds proper multi-step SASL authentication for LOGIN and PLAIN
mechanisms by tracking auth state per connection:
- AUTH LOGIN without initial response: sends Username prompt
- CONT with username: stores decoded username, sends Password prompt
- CONT with password: authenticates via existing auth API
- AUTH PLAIN without initial response: sends CONT prompt, then authenticates
- AUTH OAUTHBEARER/XOAUTH2 without initial response: handles CONT prompt

State is cleaned up after authentication completes or fails.
@manupawickramasinghe manupawickramasinghe changed the title Refactor SASL authentication handling and remove redundant tests 275 Refactor SASL authentication handling and remove redundant tests May 15, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements multi-step SASL authentication by introducing an authState tracker and a CONT command handler. It completes the LOGIN mechanism implementation and updates PLAIN and OAuth mechanisms to support continuation flows, with corresponding integration test updates. Feedback was provided regarding a potential DoS vulnerability where the authStates map could grow indefinitely, and a suggestion was made to send a FAIL response for malformed CONT commands to prevent client hangs.

Comment thread internal/sasl/server.go
Comment thread internal/sasl/server.go
@Aravinda-HWK

Copy link
Copy Markdown
Collaborator

@manupawickramasinghe could you please resolve the Gemini comments, then we can start reviewing this PR.

manupawickramasinghe and others added 2 commits May 16, 2026 15:05
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…andling

- Add maxAuthStatesPerConn limit (10) to prevent unbounded auth state map growth
- Add DoS check in handleAuth rejecting new attempts when limit exceeded
- Fix potential panic in handleCont when accessing parts[1] with len(parts) < 2
- Guard with length check before accessing parts[1] for FAIL response
@manupawickramasinghe
manupawickramasinghe marked this pull request as ready for review May 17, 2026 07:40
Copilot AI review requested due to automatic review settings May 17, 2026 07:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@manupawickramasinghe

Copy link
Copy Markdown
Contributor Author

@Aravinda-HWK The issue have been resolved

@manupawickramasinghe

Copy link
Copy Markdown
Contributor Author

@copilot Please let me know if this needs any additions

Comment thread internal/sasl/server.go Outdated
Comment thread internal/sasl/server.go
@maneesha-xyz

Copy link
Copy Markdown
Collaborator

Can you also run

go fmt ./...

@Aravinda-HWK shall we add this to our ci.

@Aravinda-HWK

Copy link
Copy Markdown
Collaborator

Can you also run

go fmt ./...

@Aravinda-HWK shall we add this to our ci.

Sure, we should add this.

@CLAassistant

CLAassistant commented May 22, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Aravinda-HWK Aravinda-HWK left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@maneesha-xyz

Copy link
Copy Markdown
Collaborator

LGTM.

@maneesha-xyz
maneesha-xyz self-requested a review May 23, 2026 08:27
@maneesha-xyz
maneesha-xyz merged commit 7d2869b into OpenGovMail:main May 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants