enhancement
major
minor
major
minor
major
#29004
Allow to use a virus scanner for uploads
Hochgeladene Dateien werden bisher nur anhand ihres Namens geprüft (FileNameStrategy, Größen- und Namenslimits). Eine inhaltliche Prüfung – insbesondere ein Virenscan – gibt es nicht. Betreiber, die Uploads aus regulatorischen Gründen scannen müssen, können TopLogic daher nicht ohne eigene Erweiterung einsetzen.
Nach diesem Ticket kann ein Betreiber per Deployment-Konfiguration einen Virenscanner (ClamAV, clamd) für alle Uploads aktivieren. Eine als infiziert erkannte Datei wird abgewiesen, bevor sie ein Control erreicht; der Benutzer sieht eine Meldung mit Dateiname und erkannter Signatur. Ohne Aktivierung ändert sich nichts.
Lösung
Erweiterungspunkt. UploadContentChecker (in com.top_logic.basic.io.binary.scan) ist das inhaltliche Gegenstück zur FileNameStrategy: er erhält den Upload als BinaryData und liefert bei Ablehnung einen Meldungsschlüssel. Der UploadSecurityService (ConfiguredManagedClass) führt die konfigurierten Checker der Reihe nach aus. Der ClamAvScanner streamt den Inhalt per INSTREAM-Protokoll an clamd (Host, Port, Timeouts, Chunk-Größe, maximale Scan-Größe konfigurierbar) und kennt eine unavailable-policy (REJECT = Standard, fail-closed; ACCEPT = fail-open), falls der Daemon nicht erreichbar ist.
Deployment. Aktivierung und Konfiguration erfolgen über Umgebungsvariablen bzw. System-Properties (upload_virus_scan_enabled, upload_virus_scan_host, upload_virus_scan_port, upload_virus_scan_unavailable_policy), Aliase in tl_basic.xml; keine ausgelieferte Konfiguration muss editiert werden.
Durchsetzung an einer Stelle. Die Prüfung sitzt nicht in den einzelnen Upload-Controls (davon gibt es acht ohne gemeinsame Oberklasse), sondern im TopLogicServlet, der Basis aller TopLogic-Servlets, den ReactServlet eingeschlossen. Ist der Dienst aktiv und die Anfrage ein Multipart-Upload, wird der HttpServletRequest in einen Guard gehüllt. Dessen getParts()/`getPart()` lässt beim ersten Aufruf den Container die Anfrage parsen, liest jeden Part genau einmal in eine TopLogic-eigene BinaryData (Temp-Datei), führt die Checker aus und wirft bei einem Treffer eine UploadRejectedException (I18N-Laufzeitausnahme mit dem Meldungsschlüssel). Andernfalls erhält das Control BinaryDataPart`s: `Part-Implementierungen, die ihren Inhalt aus der BinaryData liefern und daher beliebig oft lesbar sind – unabhängig davon, ob der Servlet-Container ein mehrfaches Lesen eines Parts erlaubt (die Servlet-Spezifikation garantiert das nicht). BinaryDataFactory.createUploadData(Part) erkennt einen solchen Part und liefert dessen Daten ohne weitere Kopie. Da die Ausnahme beim ersten Zugriff auf die Parts fliegt, ist ein Upload immer als Ganzes abgewiesen; kein Control verarbeitet einen Teil davon.
Meldung an den Benutzer.
- React (ReactServlet.handleUpload): die Ablehnung wird wie die Überschreitung des Größenlimits behandelt – Meldung in der Snackbar des Controls, Antwort HTTP 422.
- Klassische Oberfläche (TopLogicServlet um doService): Antwort HTTP 422, im Body die als Info-Service-Eintrag gerenderte Meldung. Die Upload-Clients (ajax-form.js für Datei- und Bildupload, DragAndDropFile.js für Ordner und Galerie, das CKEditor-Plugin imageUploader) zeigen diesen Body im Info-Bereich an; der Drag-and-Drop-Client schließt dabei seinen Fortschrittsdialog, der bisher bei jedem Serverfehler offen blieb.
Ohne aktiven Dienst wird die Anfrage nicht gehüllt; es entsteht weder Kopie noch Laufzeitkosten.