@@ -67,6 +67,7 @@ public function generateRootCert(
6767
6868 private function getRootCertOptions (): array {
6969 $ this ->generateRootCertConfig ();
70+ $ this ->generateCaConfig ();
7071 $ configPath = $ this ->getConfigPath ();
7172
7273 $ options = [
@@ -99,8 +100,14 @@ public function generateCertificate(): string {
99100
100101 $ serialNumber = random_int (1000000 , 2147483647 );
101102
103+ // Use CA config for certificate signing if available
104+ $ configFile = $ this ->getCaConfigPath ();
105+ if (!file_exists ($ configFile )) {
106+ $ configFile = $ this ->getFilenameToLeafCert ();
107+ }
108+
102109 $ x509 = openssl_csr_sign ($ csr , $ rootCertificate , $ rootPrivateKey , $ this ->expirity (), [
103- 'config ' => $ this -> getFilenameToLeafCert () ,
110+ 'config ' => $ configFile ,
104111 'x509_extensions ' => 'v3_req ' ,
105112 ], $ serialNumber );
106113
@@ -179,6 +186,92 @@ private function generateRootCertConfig(): void {
179186 CertificateHelper::saveFile ($ configFile , $ iniContent );
180187 }
181188
189+ private function generateCaConfig (): void {
190+ $ configPath = $ this ->getConfigPath ();
191+
192+ // Generate CA configuration for advanced operations (including CRL)
193+ $ config = [
194+ '[ ca ] ' => null ,
195+ 'default_ca ' => 'CA_default ' ,
196+ '' ,
197+ '[ CA_default ] ' => null ,
198+ 'dir ' => $ configPath ,
199+ 'certs ' => '$dir ' ,
200+ 'crl_dir ' => '$dir/crl ' ,
201+ 'database ' => '$dir/index.txt ' ,
202+ 'new_certs_dir ' => '$dir/newcerts ' ,
203+ 'certificate ' => '$dir/ca.pem ' ,
204+ 'serial ' => '$dir/serial ' ,
205+ 'crlnumber ' => '$dir/crlnumber ' ,
206+ 'crl ' => '$dir/crl.pem ' ,
207+ 'private_key ' => '$dir/ca-key.pem ' ,
208+ 'RANDFILE ' => '$dir/.rand ' ,
209+ 'default_days ' => 365 ,
210+ 'default_crl_days ' => 30 ,
211+ 'default_md ' => 'sha256 ' ,
212+ 'preserve ' => 'no ' ,
213+ 'policy ' => 'policy_strict ' ,
214+ '' ,
215+ '[ policy_strict ] ' => null ,
216+ 'countryName ' => 'match ' ,
217+ 'stateOrProvinceName ' => 'match ' ,
218+ 'organizationName ' => 'match ' ,
219+ 'organizationalUnitName ' => 'optional ' ,
220+ 'commonName ' => 'supplied ' ,
221+ 'emailAddress ' => 'optional ' ,
222+ ];
223+
224+ $ configContent = '' ;
225+ foreach ($ config as $ key => $ value ) {
226+ if ($ value === null ) {
227+ $ configContent .= "$ key \n" ;
228+ } elseif ($ key === '' ) {
229+ $ configContent .= "\n" ;
230+ } else {
231+ $ configContent .= "$ key = $ value \n" ;
232+ }
233+ }
234+
235+ $ configFile = $ configPath . '/ca.conf ' ;
236+ CertificateHelper::saveFile ($ configFile , $ configContent );
237+
238+ // Initialize required files for CA operations
239+ $ this ->initializeCaFiles ($ configPath );
240+ }
241+
242+ private function initializeCaFiles (string $ configPath ): void {
243+ // Create necessary directories
244+ $ directories = ['crl ' , 'newcerts ' ];
245+ foreach ($ directories as $ dir ) {
246+ $ dirPath = $ configPath . '/ ' . $ dir ;
247+ if (!is_dir ($ dirPath )) {
248+ mkdir ($ dirPath , 0755 , true );
249+ }
250+ }
251+
252+ // Initialize index.txt (certificate database)
253+ $ indexFile = $ configPath . '/index.txt ' ;
254+ if (!file_exists ($ indexFile )) {
255+ CertificateHelper::saveFile ($ indexFile , '' );
256+ }
257+
258+ // Initialize serial number file
259+ $ serialFile = $ configPath . '/serial ' ;
260+ if (!file_exists ($ serialFile )) {
261+ CertificateHelper::saveFile ($ serialFile , '1000 ' );
262+ }
263+
264+ // Initialize CRL number file
265+ $ crlNumberFile = $ configPath . '/crlnumber ' ;
266+ if (!file_exists ($ crlNumberFile )) {
267+ CertificateHelper::saveFile ($ crlNumberFile , '01 ' );
268+ }
269+ }
270+
271+ private function getCaConfigPath (): string {
272+ return $ this ->getConfigPath () . '/ca.conf ' ;
273+ }
274+
182275 private function getSubjectAltNames (): string {
183276 $ hosts = $ this ->getHosts ();
184277 $ altNames = [];
@@ -226,7 +319,10 @@ public function isSetupOk(): bool {
226319 $ configPath = $ this ->getConfigPath ();
227320 $ certificate = file_exists ($ configPath . DIRECTORY_SEPARATOR . 'ca.pem ' );
228321 $ privateKey = file_exists ($ configPath . DIRECTORY_SEPARATOR . 'ca-key.pem ' );
229- return $ certificate && $ privateKey ;
322+ $ opensslConfig = file_exists ($ configPath . DIRECTORY_SEPARATOR . 'openssl.cnf ' );
323+ $ caConfig = file_exists ($ configPath . DIRECTORY_SEPARATOR . 'ca.conf ' );
324+
325+ return $ certificate && $ privateKey && $ opensslConfig && $ caConfig ;
230326 }
231327
232328 #[\Override]
0 commit comments