@@ -25,6 +25,19 @@ abstract class AbstractDatabase {
2525 */
2626 protected const array CONNECTION_ENCRYPTION_OPTIONS = ['dbdriveroptions ' ];
2727
28+ /**
29+ * Installer options describing an encrypted database connection independently of the
30+ * database in use, as provided by the web installer and `occ maintenance:install`.
31+ * @var string[]
32+ */
33+ protected const array ENCRYPTION_OPTIONS = ['dbsslmode ' , 'dbsslca ' , 'dbsslcert ' , 'dbsslkey ' , 'dbsslcrl ' , 'dbsslnoverify ' ];
34+
35+ /**
36+ * The subset of {@see static::ENCRYPTION_OPTIONS} this database supports.
37+ * @var string[]
38+ */
39+ protected const array SUPPORTED_ENCRYPTION_OPTIONS = [];
40+
2841 protected string $ dbprettyname = 'abstract ' ;
2942
3043 protected string $ dbUser ;
@@ -55,16 +68,46 @@ public function validate(array $config): array {
5568 if (substr_count ($ config ['dbname ' ], '. ' ) >= 1 ) {
5669 $ errors [] = $ this ->trans ->t ('You cannot use dots in the database name %s ' , [$ this ->dbprettyname ]);
5770 }
71+ return array_merge ($ errors , $ this ->validateEncryptionOptions ($ config ));
72+ }
73+
74+ /**
75+ * Validate the installer options configuring an encrypted database connection.
76+ *
77+ * @param array $config The options passed to the installer
78+ * @return string[]
79+ */
80+ protected function validateEncryptionOptions (array $ config ): array {
81+ $ errors = [];
5882 foreach (static ::CONNECTION_ENCRYPTION_OPTIONS as $ option ) {
5983 if (isset ($ config [$ option ]) && !is_array ($ config [$ option ])) {
60- // Fail instead of ignoring the option, otherwise the instance would be
61- // installed with an unencrypted connection without the admin noticing.
6284 $ errors [] = $ this ->trans ->t ('The database option "%1$s" for %2$s has to be a list of values ' , [$ option , $ this ->dbprettyname ]);
6385 }
6486 }
87+ foreach (static ::ENCRYPTION_OPTIONS as $ option ) {
88+ if (!empty ($ config [$ option ]) && !in_array ($ option , static ::SUPPORTED_ENCRYPTION_OPTIONS , true )) {
89+ $ errors [] = $ this ->trans ->t ('The database option "%1$s" is not supported by %2$s ' , [$ option , $ this ->dbprettyname ]);
90+ }
91+ }
92+ // A client certificate is useless without its private key and vice versa
93+ if (in_array ('dbsslcert ' , static ::SUPPORTED_ENCRYPTION_OPTIONS , true )
94+ && empty ($ config ['dbsslcert ' ]) !== empty ($ config ['dbsslkey ' ])) {
95+ $ errors [] = $ this ->trans ->t ('The database options "dbsslcert" and "dbsslkey" have to be provided together ' );
96+ }
6597 return $ errors ;
6698 }
6799
100+ /**
101+ * Translate the `ENCRYPTION_OPTIONS` into the system config values that
102+ * configure an encrypted connection for this database.
103+ *
104+ * @param array $config The options passed to the installer
105+ * @return array<string, array> System config values, empty if no option was provided
106+ */
107+ protected function getEncryptionConfig (array $ config ): array {
108+ return [];
109+ }
110+
68111 public function initialize (array $ config ): void {
69112 $ dbUser = $ config ['dbuser ' ];
70113 $ dbPass = $ config ['dbpass ' ];
@@ -97,6 +140,13 @@ public function initialize(array $config): void {
97140 $ configValues [$ option ] = $ config [$ option ];
98141 }
99142
143+ // The database independent options end up in the same config values, so they are
144+ // applied on top of any raw value provided, e.g. through an autoconfig file.
145+ // array_replace() instead of array_merge() to keep the numeric PDO attribute keys.
146+ foreach ($ this ->getEncryptionConfig ($ config ) as $ option => $ value ) {
147+ $ configValues [$ option ] = array_replace ($ configValues [$ option ] ?? [], $ value );
148+ }
149+
100150 $ this ->config ->setValues ($ configValues );
101151
102152 $ this ->dbUser = $ dbUser ;
0 commit comments