Hallo Heiko,
Heiko Schlittermann (Sat, Feb 13, 2021 at 12:32:14PM +0100):
Hallo Bert, noch ein paar weitere unsortierte Gedanken:
- Vewenden die MySQL/MariaDB Libraries nicht auch Konfigurationsfiles (mehr oder weniger implizit), in denen man dann solche Dinge erledigen könnte?
Die Konfigurationsfiles stecken in den mariadb-server und mariadb-client Paketen, exim4-daemon-heavy hat nur ein Depends: libmariadb3.
- Möchte MariaDB nicht API-kompatibel zu MySQL sein? Exim behandelt aktuell beide Libraries gleich (bis auf etwas Magie zum ermitteln der aktuellen Version, da gab es wohl unterschiedliche Defines in den beiden Libs)
Anscheinend nicht ;) Die nutzen auch eine mysql_optionsv() Methode anstelle der mysql_options(). Und ja das Versionsschema ist schräg.
Vielleicht mysql_servers = <; [tls://]localhost[:port]/DB/User/Passwort
Das würde dann das Verhalten implizieren TLS zu erzwingen wenn tls:// als Protokoll angegeben wurde und darauf bestehen verschlüsselt zu kommuizieren?
So war der Gedanke. Aber wie Du selbst weiter unten ausführst, wird es schnell unübersichtlich, wenn man da noch weitere Optionen mit einbauen möchte (CA, Client-Cert, Ciphers, …)
Dann lege ich mal vor (siehe Patch im Anhang).
Folgende Umstände sind derzeit zu beachten:
- Connection String wird von links nach rechts geparsed und es werden 4 Argumente erwartet: Host Datenbank Username Passwort.
- Das Passwort mag auch Slashes enthalten, es wird einfach der Rest des Strings nach dem 3. Slash verwendet
- Doppelpunkte! Kann man nicht verwenden, der String aus der Konfiguration in "mysql_servers" ist komplett, als "server" in perform_mysql_search() kommt dann nur ein Substring bis zum ersten ":" an. (habe nicht in lf_sqlperform() geschaut, aber vermute das dort ein bisschen zuviel santized wird).
Ich gehe davon aus, dass ein Passwort mit ":" nicht funktioniert:)
Also tls:// ist eine schlechte Idee. Habe jetzt die Syntax auf tls@host definiert (finde ich lesbar: verbinde mit host via tls.)
Das sollte auch nicht zu Irritationen führen, man 7 hostname:
"Valid characters for hostnames are ASCII(7) letters from a to z, the digits from 0 to 9, and the hyphen (-)."
Hier geht es dann weiter und man müsste mindestens prüfen ob das Server Zertifikat durch eine vertrauenswürdige CA ausgestellt wurde (und ggf. noch nicht revoked). Dafür brauchen wir:
MYSQL_OPT_SSL_CA || MYSQL_OPT_SSL_CAPATH MYSQL_OPT_SSL_CRL || MYSQL_OPT_SSL_CRLPATH
Worauf ich hinaus will: mit mysql_servers ist es bestimmt nicht getan.
Full Ack.
tls_mysql_servers // für den connection String tls_mysql_servers_verify // default true, anderenfalls fallback unencrypted
Na, aber z.B. kann man den MySQL-Server auch direkt beim Lookup mitgeben
… = ${lookup mysql,servers=… {SELECT ...}}
und ich glaube, auch so: … = mysql,servers=…;SELECT ...
Es wäre also gut, wenn man alle erforderliche Information in *einen* String bekäme.
mysql_servers = host[:port]/db/user/password/tls=required,ca=…,
Das wäre jetzt "mysql_servers = [tls@]host[:port]/db/user/password"
Dann gäbe es nur ein Problem, wenn das Passwort einen Slash enthält, aber ich denke, das Problem haben wir jetzt schon (habe jetzt nicht in den Sourcen nachgeschaut, ob wir das mit Quting oder Escaping umgehen könnten.
Das Problem würde sich erst ergeben, wenn man die TLS Optionen als 5. Argument einführen möchte und dann muss man die bisherige Logik unnötig verkomplizieren.
Wenn also alle erforderliche Info in einem String steckt, könnten wir das auch problemlos bei der expliziten Verwendung unterbringen. Wird natürlich dann nicht mehr schön
… = ${lookup mysql,servers=localhost/db/user/password/tls=required,ca=…{SELECT …}}
Sollte auch mit "…,servers=[tls@]host[:port]/db/user/password" klappen.
Aber wir haben ja Macros.
Zur Zertifikatsprüfung: Ich würde jetzt mal unterstellen, dass die MySQL libs sich da mit irgendwelchen dazugenommen TLS libs auch selbst kümmern, oder? Wenn man an die Verbindungsdetails dran kommt, könnte man aber sicher auch Zertifikats-Prüfungs-Funktionen nutzen, die der Exim schon bringt (wobei auch der m.W. sich dort auf GnuTLS bzw. OpenSSL verlässt).
Habe bisher nur ein Standard dpkg-buildpackage -uc -us mit GnuTLS getestet.
07:34:32 10541 MYSQL new connection: host=localhost port=0 socket=NULL database=mail user=mail 07:34:32 10541 GnuTLS<3>: ASSERT: ../../../lib/x509/common.c[_gnutls_x509_get_raw_field2]:1575 […] 07:34:32 10541 GnuTLS<2>: issuer in verification was not found or insecure; trying against trust list […] 07:34:32 10541 MYSQL connection: TLS negotiated cipher is DHE-RSA-AES256-SHA
Abgesehen von der "issuer in verification was not found or insecure" Meldung passiert hier erstmal nichts an Verifikation. Hier müsste man also Hand anlegen und schauen wie das in den transports mit host_require_tls funktioniert.
Denke die Ausführungen erklären was ich meinte, es ging mir darum wie dreckig man sich die Finger machen müsste:)
Ich glaube, es wird nicht soo schlimm.
Ja Hände waschen mit Seife hat zunächst gereicht;)
-- Heiko
Gruß Bert