Document current-server IMAP source audit

This commit is contained in:
Mario Fetka
2026-07-29 09:44:54 +02:00
parent 834c93226e
commit 9fc7fc6f80
2 changed files with 96 additions and 29 deletions
+1 -1
View File
@@ -174,7 +174,7 @@ review does not mark an open live test as passed.
| IMAP-05 | LIST, LSUB, extended LIST, LIST-STATUS, hierarchy quoting | [PASS](test-evidence/0.7-r1.md#imap-0506) | | |
| IMAP-06 | CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE | [PASS](test-evidence/0.7-r1.md#imap-0506) | | |
| IMAP-07 | SELECT, EXAMINE, STATUS/SIZE, CHECK, CLOSE, UNSELECT | [PASS](test-evidence/0.7-r1.md#imap-07) | | |
| IMAP-08 | APPEND, LITERAL+, APPENDLIMIT, flags/date, oversized literals | | | |
| IMAP-08 | APPEND, LITERAL+, APPENDLIMIT, flags/date, oversized literals | [PASS](test-evidence/0.7-r1.md#imap-08) | | |
| IMAP-09 | FETCH/UID FETCH body, headers, partials, flags, envelope, binary | | | |
| IMAP-10 | STORE/UID STORE add/remove/replace flags and silent variants | | | |
| IMAP-11 | COPY/UID COPY/MOVE/UID MOVE and UIDPLUS response codes | | | |
+95 -28
View File
@@ -3367,7 +3367,7 @@ document, and left `bongo.service` active.
Result: **PASS**
The installed `865c632d` GCC 15.3.0 debug build was exercised on 2026-07-29
The installed `834c9322` GCC 15.3.0 debug build was exercised on 2026-07-29
with the reusable `smtp-tlsrpt-delivery-check.py --live` fixture. It delivered
one RFC 8460 report as a DKIM-signed, gzip-compressed MIME attachment and one
gzip-compressed report through HTTPS with validated TLS. Reports with a
@@ -3447,15 +3447,21 @@ GSASL PLAIN and LOGIN mechanisms. The TLS capability response contained
an RFC 2971 client ID with name and version, the RFC 2342 personal namespace,
and LOGOUT with an untagged BYE followed by tagged completion.
This state model was compared with current Cyrus IMAP `imap/imapd.c`. Cyrus
likewise limits STARTTLS and SASL-IR to pre-authentication state, advertises
`LOGINDISABLED` from connection state, starts TLS immediately for IMAPS, and
explicitly discards input pipelined after STARTTLS. Bongo's focused
This state model was compared with Cyrus IMAP 3.12.3 `imap/imapd.c` and
Dovecot 2.4.4 `src/imap/imap-commands.c`,
`src/imap-login/client-authenticate.c`,
`src/login-common/client-common-auth.c`, and `src/imap/cmd-id.c`. The source
comparison added checks for AUTHENTICATE cancellation, malformed base64,
unknown mechanisms, trailing arguments, continued session usability, ID
field limits, NIL keys, literals, and commands which take no arguments.
Cyrus and Dovecot likewise limit STARTTLS and SASL-IR to pre-authentication
state, derive `LOGINDISABLED` from connection state, and discard input
pipelined after STARTTLS. Bongo's focused
`imap-capabilities`, `imap-protocol`, and `sasl-password-mechanisms` native
tests all passed before the live run.
```text
IMAP-01/02/03/04 PASS host=127.0.0.1 starttls=143/TLSv1.3 imaps=993/TLSv1.3 protocols=IMAP4rev2,IMAP4rev1,IMAP4 pre-tls=LOGINDISABLED login=LOGIN,PLAIN,LOGIN-SASL commands=CAPABILITY,NOOP,ID,NAMESPACE,LOGOUT repeated-starttls=rejected pipeline=discarded
IMAP-01/02/03/04 PASS host=127.0.0.1 starttls=143/TLSv1.3 imaps=993/TLSv1.3 protocols=IMAP4rev2,IMAP4rev1,IMAP4 pre-tls=LOGINDISABLED login=LOGIN,PLAIN,LOGIN-SASL commands=CAPABILITY,NOOP,ID,NAMESPACE,LOGOUT id=literal+,limits,nil-key-rejected auth=cancel/unknown/base64/trailing/session-alive noarg-syntax=capability/noop/namespace/logout repeated-starttls=rejected pipeline=discarded
```
The test only authenticates and logs out. It does not create, alter, or
@@ -3465,7 +3471,7 @@ delete any mailbox or message and leaves the service configuration unchanged.
Result: **PASS**
The installed `9bb5eb8e` GCC 15.3.0 debug build was exercised on 2026-07-29
The installed `834c9322` GCC 15.3.0 debug build was exercised on 2026-07-29
with the reusable `imap-mailbox-check.py`. The test used disposable mailbox
names containing spaces and multiple hierarchy levels. It verified the
reported hierarchy delimiter, LIST with both `%` and `*`, exact and recursive
@@ -3474,26 +3480,37 @@ LIST-STATUS responses.
CREATE left new mailboxes unsubscribed until an explicit SUBSCRIBE. RENAME
moved the complete hierarchy without changing any child or grandchild suffix.
UNSUBSCRIBE removed only the subscription. DELETE removed an empty leaf, and
deleting a parent with inferiors retained its children while converting the
parent into a `\NoSelect` hierarchy placeholder. The test then removed all
disposable objects depth-first and verified that none remained.
UNSUBSCRIBE removed only the subscription. DELETE retained subscriptions
independently of mailbox existence: obsolete LSUB continued to return the
deleted name, extended LIST returned `\Subscribed \NonExistent`, basic LIST
returned `\NoSelect`, and CREATE restored the selectable mailbox without
dropping its subscription. Deleting a parent with inferiors retained its
children. A final UNSUBSCRIBE removed an unused non-existent placeholder.
The test then removed all disposable objects depth-first and verified that
none remained.
The live pass exposed and fixed three issues before succeeding: CREATE had
The live pass exposed and fixed several issues before succeeding: CREATE had
implicitly subscribed folders, recursive Store rename truncated hierarchy
suffixes, and Store commands did not quote paths containing spaces when
converting a deleted parent to hierarchy-only state. Focused native coverage
now exercises SPECIAL-USE creation, LIST-EXTENDED parsing, and the exact SQL
rename boundary for children, grandchildren, and similarly prefixed
mailboxes.
suffixes, LSUB overwrote a syntax error with a path-length error, wildcard and
reference handling were incomplete, INBOX was not canonicalized
case-insensitively, subscriptions disappeared with a deleted mailbox, and
several Store commands did not quote paths containing spaces. The missing
quotes also caused the old CREATE error path to return without a tagged IMAP
response. Focused native coverage now exercises SPECIAL-USE creation,
LIST-EXTENDED parsing, and the exact SQL rename boundary for children,
grandchildren, and similarly prefixed mailboxes.
The behavior was also compared directly with current Cyrus IMAP source:
subscription is independent of mailbox creation, hierarchy rename preserves
descendants, and deleting a mailbox with inferiors leaves the hierarchy
available for those descendants.
The behavior was compared directly with Cyrus IMAP 3.12.3
`imap/imapd.c` (`cmd_changesub`, LIST processing, rename and delete paths) and
Dovecot 2.4.4 `src/imap/cmd-list.c`, `src/imap/cmd-subscribe.c`, and
`src/lib-storage/mailbox-list.c`. Both implementations keep subscriptions
separate from mailbox existence. Dovecot's `used_listext` distinction was
also used to preserve the RFC difference between basic `\NoSelect` and
extended `\NonExistent` responses. RFC 9051 sections 6.3.7 through 6.3.9 were
checked alongside both implementations.
```text
IMAP-05/06 PASS host=127.0.0.1:993 delimiter=/ hierarchy=quoted list=percent/star lsub=subscribed-only extended=subscribed/children/list-status lifecycle=create/rename/sub/unsub/delete delete-with-inferiors=noselect/preserved cleanup=yes
IMAP-05/06 PASS host=127.0.0.1:993 delimiter=/ hierarchy=quoted list=percent/star/literal-pattern-list/reference/inbox-case lsub=subscribed-only lsub=mid-wildcard/no-match/delimiter extended=subscribed/children/list-status lifecycle=create/rename/sub/unsub/delete syntax=trailing-arguments-rejected delete-subscription=retained/nonexistent/recreated delete-with-inferiors=noselect/preserved cleanup=yes
```
The test creates only uniquely named disposable mailboxes for `test1`, removes
@@ -3503,7 +3520,7 @@ them before exit, and does not alter service configuration or existing mail.
Result: **PASS**
The installed `0c0d281b` GCC 15.3.0 debug build was exercised on 2026-07-29
The installed `834c9322` GCC 15.3.0 debug build was exercised on 2026-07-29
with the reusable `imap-selected-state-check.py`. The test created two
disposable mailboxes and appended one disposable message using a synchronizing
IMAP literal. Rev1 SELECT returned EXISTS, RECENT, UIDVALIDITY, UIDNEXT, FLAGS,
@@ -3519,10 +3536,12 @@ After `ENABLE IMAP4rev2`, STATUS accepted DELETED and DELETED-STORAGE but
rejected RECENT; SELECT omitted RECENT, emitted the required LIST response,
and selecting a second mailbox emitted the CLOSED response code.
The source audit used current Cyrus IMAP `imap/imapd.c` as the implementation
comparison. Cyrus likewise separates EXAMINE read-only state, expunges on
CLOSE but not UNSELECT, emits CLOSED when rev2 selection replaces an open
mailbox, and refreshes selected-mailbox state before STATUS.
The source audit used Cyrus IMAP 3.12.3 `imap/imapd.c` and Dovecot 2.4.4
`src/imap/cmd-select.c`, `cmd-examine.c`, `cmd-status.c`, `cmd-close.c`,
`cmd-unselect.c`, and the command registration table as implementation
comparisons. Both separate EXAMINE read-only state, expunge on CLOSE but not
UNSELECT, reject arguments on CHECK/CLOSE/UNSELECT, and implement the rev2
CLOSED transition when a selected mailbox is replaced.
The first live attempt found a real APPEND deadlock: the IMAP agent buffered
the message sent to Store and waited for Store's completion without flushing
@@ -3533,9 +3552,57 @@ returns only its payload. The corrected payload parser is covered by the
native `imap-uidplus` test and also fixes the later COPY/MOVE UIDPLUS paths.
```text
IMAP-07 PASS host=127.0.0.1:993 select=read-write examine=read-only status=rev1/rev2/size check=selected-only close=deselect/expunge-semantics unselect=no-expunge rev2=closed/list/no-recent cleanup=yes
IMAP-07 PASS host=127.0.0.1:993 select=read-write examine=read-only status=rev1/rev2/size check=selected-only noarg-syntax=check/close/unselect close=deselect/expunge-semantics unselect=no-expunge rev2=closed/list/no-recent cleanup=yes
```
The successful run removed its disposable message and mailboxes. The three
mailboxes left by deliberately interrupted diagnostic runs were separately
listed, matched by their unique test names, and removed afterward.
## IMAP-08
Result: **PASS**
The installed `834c9322` GCC 15.3.0 debug build was exercised on 2026-07-29
with the reusable `imap-append-check.py`. Synchronizing literals and
non-synchronizing LITERAL+ both committed messages and returned UIDPLUS
APPENDUID data. Supplied system flags and INTERNALDATE survived the append.
APPEND to a missing mailbox returned TRYCREATE. The advertised global
APPENDLIMIT and per-mailbox STATUS APPENDLIMIT agreed, an oversized
non-synchronizing literal returned TOOBIG without accepting its body, and the
next command proved that the parser stream remained synchronized.
The implementation was compared with Cyrus IMAP 3.12.3 `imap/imapd.c` append
handling and Dovecot 2.4.4 `src/imap/cmd-append.c` plus its command/literal
reader. The comparison covered literal continuation timing, LITERAL+,
mailbox lookup before data acceptance, bounded literal sizes, flag/date
parsing, failure stream recovery, and UIDPLUS completion. RFC 9051 and the
advertised APPENDLIMIT/LITERAL+ extension contracts were checked at the same
time.
The native `imap-append-message`, `imap-literal`, and `imap-uidplus` tests
passed as part of the complete 101-test native run before the live matrix.
```text
IMAP-08 PASS host=127.0.0.1:993 append=sync/literal+ appendlimit=capability/status/toobig metadata=flags/date missing=trycreate stream=resynchronized cleanup=yes
```
The test removed all disposable messages and mailboxes and did not change
service configuration.
## IMAP retrospective source audit
Result: **PASS for IMAP-01 through IMAP-08**
The already completed IMAP blocks were re-audited against actual current
server source, not only documentation: Cyrus IMAP 3.12.3 and Dovecot 2.4.4.
The comparison found and fixed authentication cancellation/error handling,
ID and no-argument syntax validation, LIST/LSUB parsing and wildcard
semantics, case-insensitive INBOX handling, independent subscription
lifetime, basic-versus-extended LIST attributes, missing Store path quoting,
and several error paths which could otherwise omit a tagged response.
After the fixes, all 101 native tests passed and the four reusable live
scripts for IMAP-01 through IMAP-08 passed consecutively against the
installed debug build. The same Cyrus/Dovecot source-comparison requirement
applies to every remaining IMAP and POP3 row as it is reached in the matrix.