fix(SEC-29): Rollen-Trennung Admins/Auditoren, domain_auditor Rolle

- superadmin + domain_admin haben keinen Mail-Zugriff mehr (requireMailAccess)
- Neue Rolle domain_auditor: alle Tenant-Mails, kein Admin-Zugriff
- auditor + user: nur eigene Mails
- ZIP-Export: kein separates Attachment-Entpacken mehr, nur EML
- roleLevel() um domain_auditor (Level 3) erweitert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-31 01:09:19 +02:00
parent e0f6a818eb
commit 64433aa847
5 changed files with 47 additions and 48 deletions
+6 -5
View File
@@ -231,8 +231,8 @@ func (s *Server) handleGetMail(w http.ResponseWriter, r *http.Request) {
}
}
// user role: only own mailbox
if sess.Role == userstore.RoleUser {
// user and auditor: only own mails; domain_auditor: all tenant mails (no filter)
if sess.Role == userstore.RoleUser || sess.Role == userstore.RoleAuditor {
u, err := s.users.GetByUsername(sess.Username)
if err != nil || !mailBelongsToUser(pm, u.Email) {
writeError(w, http.StatusForbidden, "access denied")
@@ -326,7 +326,8 @@ func (s *Server) handleGetAttachment(w http.ResponseWriter, r *http.Request) {
}
}
if sess.Role == userstore.RoleUser {
// user and auditor: only own mails; domain_auditor: all tenant mails (no filter)
if sess.Role == userstore.RoleUser || sess.Role == userstore.RoleAuditor {
u, err := s.users.GetByUsername(sess.Username)
if err != nil || !mailBelongsToUser(pm, u.Email) {
writeError(w, http.StatusForbidden, "access denied")
@@ -377,8 +378,8 @@ func (s *Server) handleGetRaw(w http.ResponseWriter, r *http.Request) {
}
}
// SEC-28: Access check for user role — parse failure must NOT grant access.
if sess.Role == userstore.RoleUser {
// SEC-28/29: User and Auditor: only own mails. Parse failure must NOT grant access.
if sess.Role == userstore.RoleUser || sess.Role == userstore.RoleAuditor {
pm, err := mailparser.Parse(raw)
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to parse mail")