From 3cce9c110733ef85e4373040d36f670007028be9 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 23 Sep 2026 00:44:26 +0200 Subject: [PATCH] IMP-10: pruefprotokoll Co-Authored-By: Claude Sonnet 5 --- docs/IMP-10-PRUEFPROTOKOLL.md | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/IMP-10-PRUEFPROTOKOLL.md diff --git a/docs/IMP-10-PRUEFPROTOKOLL.md b/docs/IMP-10-PRUEFPROTOKOLL.md new file mode 100644 index 00000000..76aa4f76 --- /dev/null +++ b/docs/IMP-10-PRUEFPROTOKOLL.md @@ -0,0 +1,40 @@ +# IMP-10 – Prüfprotokoll: IMAP-Import mit TLS und sicheren Befehlen + +Ticket: `mail-kanban/tickets/IMP-10.md`. Basis: `integration/gesamtprojekt` (Head 27d3dca), Branch `feature/imp-10-imap-tls-sichere-befehle-mail`. + +## Befund + +`mail/internal/imapimport/client_real.go` (`RealClient.Sync`) verband ohne TLS und baute `LOGIN`/`SELECT` durch reine String-Verkettung aus Benutzername, Passwort und Postfachname — QA-15-Befund F-19 (mittel, latent, da das Modul noch nicht verdrahtet ist). + +## Umsetzung + +- **TLS-Pflicht (AK1):** `Sync` sendet vor `LOGIN` immer `STARTTLS` und führt den TLS-Handshake durch (`crypto/tls`, `MinVersion: TLS 1.2`), außer der ausdrückliche Schalter `WithInsecureAllowPlaintextForTests()` ist gesetzt. Bietet der Server kein STARTTLS an oder lehnt es ab, bricht `Sync` mit Fehler ab, bevor Zugangsdaten gesendet werden. `WithTLSConfig` erlaubt das Setzen einer eigenen `tls.Config` (Produktivbetrieb: Systemwurzeln + aus `addr` abgeleiteter Servername; Tests: `InsecureSkipVerify` gegen das selbstsignierte Testzertifikat). +- **Sichere Befehlskonstruktion (AK2/AK3):** Neue Funktion `quoteIMAPString` baut RFC-3501-Quoted-Strings (Escaping von `"` und `\`) und weist Werte mit `\r`, `\n` oder NUL zurück, statt sie zu escapen — eingebettet in einen Quoted-String würden sie die zeilenbasierte Übertragung ohnehin vorzeitig beenden und einen zweiten, eingeschleusten Befehl ermöglichen. `buildLoginCommand`/`buildSelectCommand` nutzen das für Benutzername, Passwort und Postfachname; ein ungültiges Passwort erzeugt bewusst einen Fehlertext ohne den Rohwert (Prüfung 2). +- Nach dem STARTTLS-Handshake wird der gepufferte Reader neu aufgesetzt (gleiches Muster wie serverseitig in `mail/internal/imap.handleStartTLS`), damit vor dem Handshake gepufferte Klartextdaten nicht als Serverantwort nach dem Wechsel verarbeitet werden. + +## Prüfungen (alle real auf Host 204, `go test ./internal/imapimport/...`) + +| # | Prüfung | Ergebnis | +|---|---|---| +| 1 | Tests gegen den In-Process-IMAP-Server (`TestRunOnce_AgainstRealTestMailboxWithRealisticVolume`, jetzt mit STARTTLS-Aufwertung gegen selbstsigniertes Testzertifikat) | bestanden, 30/30 Nachrichten, zweiter Lauf 0 neue | +| 1 (Negativ) | `TestSync_RejectsServerWithoutTLSOffer`: Server ohne TLS-Konfiguration wird abgelehnt | bestanden | +| 1 (Schalter) | `TestSync_WithInsecureAllowPlaintextForTests_WorksAgainstPlaintextServer`: expliziter Test-Schalter funktioniert weiterhin | bestanden | +| 3 | `TestSync_RejectsCRLFInjectionInUsernameAndMailbox`: `\r\n`-Einschleusung in Benutzername und Postfachname erreicht keinen zweiten Befehl, `Sync` bricht vor dem Senden mit Validierungsfehler ab | bestanden | +| 2 | `TestSync_PasswordNeverAppearsInErrorOrLog`: Passwort erscheint bei Anmeldefehler weder im Fehlertext noch in protokollierten Meldungen | bestanden | +| 3 | Verdrahtung des Importmoduls bleibt unverändert nicht angeschlossen (dieses Ticket ändert nur `client_real.go`, keine Aufrufstelle außerhalb der Tests existiert) | bestätigt (`grep -rn NewRealClient` außerhalb der Tests: keine Treffer) | + +Bestandstests `nonconformant_test.go` (UIDVALIDITY=0-Fallback, kaputte FETCH-Zeilen) laufen gegen einen handgeschriebenen Fake-Server ohne STARTTLS-Verständnis; sie wurden auf den expliziten `WithInsecureAllowPlaintextForTests()`-Schalter umgestellt, da sie eine andere Schicht (Protokoll-Fehlertoleranz) prüfen, nicht TLS. + +## Regression + +- `go build ./...`, `go vet ./...`: sauber. +- `gofmt -l internal/imapimport/`: leer (die vier von `gofmt -l .` gemeldeten Dateien im Gesamtmodul sind Bestand, von diesem Branch nicht berührt). +- `go test -count=1 ./...` über das gesamte Mail-Modul: 0 FAIL. + +## QA und Entscheidungen + +- **Implicit-TLS-Port:** Nicht umgesetzt, nur STARTTLS-Aufwertung. Begründung: Der Testserver und alle im Repo bekannten Zielserver bieten STARTTLS auf dem Standardport, ein separater Implicit-TLS-Port wäre unbelegte Mehrarbeit außerhalb des Ticket-Scopes. +- **CR/LF: Abweisen statt Escapen.** Ein IMAP-Quoted-String kann `\r`/`\n` nicht sicher transportieren, weil sowohl Server als auch Client zeilenbasiert lesen (`bufio.Reader.ReadString('\n')`) — ein eingebettetes `\n` würde die Zeile unabhängig von Anführungszeichen vorzeitig beenden. Abweisen ist die einzige korrekte Lösung, kein Kompromiss. +- **Kein Merge, kein Deploy**, wie in allen Tickets dieser Session. + +Iterationen: 1 (STARTTLS-Unwissenheit des `nonconformant_test.go`-Fakes, sofort erkannt und korrigiert).