Bearsampp 2026.7.11
Loading...
Searching...
No Matches
OpenSsl Class Reference

Public Member Functions

 createCrt ($name, $destPath=null)
 delSslCertificate ()
 delSslCertificateHandler ($window, $id, $ctrl, $param1, $param2)
 existsCrt ($name)
 genSslCertificate ()
 genSslCertificateHandler ($window, $id, $ctrl, $param1, $param2)
 getCrts ()
 isExpired ($name)
 makeRootCa ()
 rebuildAllCerts ()
 removeCrt ($name, $destPath=null)

Private Member Functions

 ensureMkcertExeExists ()
 ensureRootCaExists ($destPath)
 ensureSslDirExists ()
 validateCertificateName ($name)

Private Attributes

 $rootCaName = 'BearsamppRootCA'
 $wbDelSslBtnCancel
 $wbDelSslBtnDelete
 $wbDelSslBtnDest
 $wbDelSslInputDest
 $wbDelSslListCerts
 $wbDelSslProgressBar
 $wbGenSslBtnCancel
 $wbGenSslBtnDest
 $wbGenSslBtnSave
 $wbGenSslInputDest
 $wbGenSslInputName
 $wbGenSslProgressBar

Detailed Description

Definition at line 11 of file class.openssl.php.

Member Function Documentation

◆ createCrt()

createCrt ( $name,
$destPath = null )

Creates a certificate with the specified name and destination path.

Parameters
string$nameThe name of the certificate.
string | null$destPathThe destination path where the certificate files will be saved. If null, the default SSL path is used.
Returns
bool True if the certificate was created successfully, false otherwise.

Definition at line 187 of file class.openssl.php.

188 {
189 Log::trace('createCrt called for: ' . $name . ($destPath ? ' (dest: ' . $destPath . ')' : ''));
190
191 if (!$this->validateCertificateName($name)) {
192 Log::error('Invalid certificate name: ' . $name);
193 return false;
194 }
195
196 if (!$this->ensureMkcertExeExists()) {
197 return false;
198 }
199 if (empty($destPath)) {
200 $destPath = $this->ensureSslDirExists();
201 }
202 $mkcertExe = Path::getMkcertExe();
203
204 if (!$this->ensureRootCaExists($destPath)) {
205 Log::error('Failed to ensure Root CA exists for: ' . $name);
206 return false;
207 }
208
209 $crtPath = '"' . Path::formatWindowsPath($destPath . '/' . $name . '.crt') . '"';
210 $pubPath = '"' . Path::formatWindowsPath($destPath . '/' . $name . '.pub') . '"';
211 $keyPath = '"' . Path::formatWindowsPath($destPath . '/' . $name . '.ppk') . '"'; // Using .ppk as requested in previous tasks
212 $opensslExe = '"' . Path::formatWindowsPath(Path::getOpenSslExe()) . '"';
213
214 $batch = 'SET "CAROOT=' . Path::formatWindowsPath($destPath) . '"' . PHP_EOL;
215
216 $mkcertNames = '"' . $name . '"';
217 if ($name === 'localhost') {
218 $mkcertNames .= ' 127.0.0.1 ::1';
219 } else {
220 $mkcertNames .= ' "*.' . $name . '" localhost 127.0.0.1 ::1';
221 }
222
223 Log::trace('Executing mkcert for "' . $name . '"');
224 // Use -- to terminate flag parsing before hostname arguments as defense-in-depth
225 $batch .= '"' . $mkcertExe . '" -cert-file ' . $crtPath . ' -key-file ' . $keyPath . ' -- ' . $mkcertNames . PHP_EOL;
226 $batch .= $opensslExe . " rsa -in " . $keyPath . " -out " . $keyPath . " -passin pass:" . PHP_EOL;
227 $batch .= "COPY /Y " . $keyPath . " " . $pubPath . PHP_EOL;
228 $batch .= 'IF EXIST ' . $crtPath . ' IF EXIST ' . $keyPath . ' ECHO OK' . PHP_EOL;
229
230 Log::trace('Creating SSL Certificate for "' . $name . '" using mkcert. Batch content: ' . $batch);
231 $result = Batch::exec('createCertificateMkcert', $batch);
232
233 if ($result === false || !is_array($result)) {
234 Log::error('Batch execution failed for mkcert generation of "' . $name . '". Check logs for createCertificateMkcert.');
235 return false;
236 }
237
238 $success = false;
239 foreach ($result as $line) {
240 if (trim($line) === 'OK') {
241 $success = true;
242 break;
243 }
244 }
245
246 if (!$success) {
247 Log::error('mkcert generation for "' . $name . '" did not return OK. Output: ' . implode(' | ', $result));
248 }
249 Log::trace('mkcert generation for "' . $name . '": ' . ($success ? 'SUCCESS' : 'FAILURE'));
250
251 return $success;
252 }
$result
static exec($basename, $content, $timeout=true, $catchOutput=true, $standalone=false, $silent=true, $rebuild=true)
static trace($data, $file=null)
static error($data, $file=null)
ensureRootCaExists($destPath)
ensureMkcertExeExists()
validateCertificateName($name)
ensureSslDirExists()
static getOpenSslExe($aetrayPath=false)
static getMkcertExe($aetrayPath=false)
static formatWindowsPath($path)

References $result, ensureMkcertExeExists(), ensureRootCaExists(), ensureSslDirExists(), Log\error(), Batch\exec(), Path\formatWindowsPath(), Path\getMkcertExe(), Path\getOpenSslExe(), Log\trace(), and validateCertificateName().

Referenced by makeRootCa(), and rebuildAllCerts().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delSslCertificate()

delSslCertificate ( )

Displays a WinBinder GUI for deleting an SSL certificate.

Definition at line 293 of file class.openssl.php.

294 {
295 global $bearsamppLang, $bearsamppWinbinder;
296
297 $initServerName = 'test.local';
298 $initDocumentRoot = Path::formatWindowsPath(Path::getSslPath());
299
300 $bearsamppWinbinder->reset();
301 $wbWindow = $bearsamppWinbinder->createAppWindow($bearsamppLang->getValue(Lang::DELSSL_TITLE), 490, 160, WBC_NOTIFY, WBC_KEYDOWN | WBC_KEYUP);
302
303 $wbLabelName = $bearsamppWinbinder->createLabel($wbWindow, $bearsamppLang->getValue(Lang::NAME) . ' :', 15, 15, 85, null, WBC_RIGHT);
304 $this->wbDelSslListCerts = $bearsamppWinbinder->createInputText($wbWindow, $initServerName, 105, 13, 150, null);
305
306 $wbLabelDest = $bearsamppWinbinder->createLabel($wbWindow, $bearsamppLang->getValue(Lang::TARGET) . ' :', 15, 45, 85, null, WBC_RIGHT);
307 $this->wbDelSslInputDest = $bearsamppWinbinder->createInputText($wbWindow, $initDocumentRoot, 105, 43, 190, null, null, WBC_READONLY);
308 $this->wbDelSslBtnDest = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_BROWSE), 300, 43, 110);
309
310 $this->wbDelSslProgressBar = $bearsamppWinbinder->createProgressBar($wbWindow, 3, 15, 97, 275);
311 $this->wbDelSslBtnDelete = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_DELETE), 300, 92);
312 $this->wbDelSslBtnCancel = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_CANCEL), 387, 92);
313
314 $bearsamppWinbinder->setHandler($wbWindow, $this, 'delSslCertificateHandler');
315
316 $bearsamppWinbinder->mainLoop();
317 $bearsamppWinbinder->reset();
318 }
global $bearsamppLang
const NAME
const BUTTON_BROWSE
const BUTTON_CANCEL
const BUTTON_DELETE
const TARGET
const DELSSL_TITLE
static getSslPath($aetrayPath=false)

References $bearsamppLang, Lang\BUTTON_BROWSE, Lang\BUTTON_CANCEL, Lang\BUTTON_DELETE, Lang\DELSSL_TITLE, Path\formatWindowsPath(), Path\getSslPath(), Lang\NAME, and Lang\TARGET.

Here is the call graph for this function:

◆ delSslCertificateHandler()

delSslCertificateHandler ( $window,
$id,
$ctrl,
$param1,
$param2 )

Handler for the SSL certificate deletion WinBinder GUI.

Definition at line 323 of file class.openssl.php.

324 {
325 global $bearsamppLang, $bearsamppOpenSsl, $bearsamppWinbinder;
326
327 switch ($id) {
328 case $this->wbDelSslBtnDest[WinBinder::CTRL_ID]:
329 $target = $bearsamppWinbinder->getText($this->wbDelSslInputDest[WinBinder::CTRL_OBJ]);
330 $target = $bearsamppWinbinder->sysDlgPath($window, $bearsamppLang->getValue(Lang::GENSSL_PATH), $target);
331 if ($target && is_dir($target)) {
332 $bearsamppWinbinder->setText($this->wbDelSslInputDest[WinBinder::CTRL_OBJ], $target . '\\');
333 }
334 break;
335 case $this->wbDelSslBtnDelete[WinBinder::CTRL_ID]:
336 $cert = $bearsamppWinbinder->getText($this->wbDelSslListCerts[WinBinder::CTRL_OBJ]);
337 $target = $bearsamppWinbinder->getText($this->wbDelSslInputDest[WinBinder::CTRL_OBJ]);
338
339 if ($cert) {
340 $existingCerts = $this->getCrts();
341 if (!in_array($cert, $existingCerts)) {
342 $bearsamppWinbinder->messageBoxError(sprintf($bearsamppLang->getValue(Lang::ERROR_FILE_NOT_FOUND), $cert, $target), $bearsamppLang->getValue(Lang::DELSSL_TITLE));
343 return;
344 }
345
346 $bearsamppWinbinder->setProgressBarMax($this->wbDelSslProgressBar, 3);
347 $bearsamppWinbinder->incrProgressBar($this->wbDelSslProgressBar);
348
349 $target = Path::formatUnixPath($target);
350 if ($bearsamppOpenSsl->removeCrt($cert, $target)) {
351 $bearsamppWinbinder->incrProgressBar($this->wbDelSslProgressBar);
352 $bearsamppWinbinder->messageBoxInfo(
353 sprintf($bearsamppLang->getValue(Lang::DELSSL_DELETED), $cert),
355 );
356 $bearsamppWinbinder->destroyWindow($window);
357 } else {
358 $bearsamppWinbinder->messageBoxError($bearsamppLang->getValue(Lang::DELSSL_DELETED_ERROR), $bearsamppLang->getValue(Lang::DELSSL_TITLE));
359 $bearsamppWinbinder->resetProgressBar($this->wbDelSslProgressBar);
360 }
361 }
362 break;
363 case IDCLOSE:
364 case $this->wbDelSslBtnCancel[WinBinder::CTRL_ID]:
365 $bearsamppWinbinder->destroyWindow($window);
366 break;
367 }
368 }
const GENSSL_PATH
const DELSSL_DELETED_ERROR
const DELSSL_DELETED
const ERROR_FILE_NOT_FOUND
static formatUnixPath($path)

References $bearsamppLang, WinBinder\CTRL_ID, WinBinder\CTRL_OBJ, Lang\DELSSL_DELETED, Lang\DELSSL_DELETED_ERROR, Lang\DELSSL_TITLE, Lang\ERROR_FILE_NOT_FOUND, Path\formatUnixPath(), Lang\GENSSL_PATH, and getCrts().

Here is the call graph for this function:

◆ ensureMkcertExeExists()

ensureMkcertExeExists ( )
private

Ensures that the mkcert executable exists, attempting to download it if missing.

Returns
bool True if mkcert exists or was successfully downloaded.

Definition at line 34 of file class.openssl.php.

35 {
36 $mkcertExe = Path::getMkcertExe();
37 if (file_exists($mkcertExe)) {
38 return true;
39 }
40
41 Log::error('mkcert.exe missing at: ' . $mkcertExe . '. It must be fetched during build time (prepareBase/buildFull/buildLite).');
42 return false;
43 }

References Log\error(), and Path\getMkcertExe().

Referenced by createCrt(), ensureRootCaExists(), and makeRootCa().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ensureRootCaExists()

ensureRootCaExists ( $destPath)
private

Ensures that the Root CA exists, creating it if necessary.

Parameters
string$destPathThe destination path.
Returns
bool True if the Root CA exists or was created successfully.

Definition at line 260 of file class.openssl.php.

261 {
262 if (!$this->ensureMkcertExeExists()) {
263 return false;
264 }
265 $mkcertExe = Path::getMkcertExe();
266
267 $rootCaPath = $destPath . '/' . Path::getMkcertRootCaName(); // mkcert default root CA name
268 if (!file_exists($rootCaPath)) {
269 Log::info('Root CA missing at ' . $rootCaPath . '. Running mkcert -install');
270 $batch = 'SET "CAROOT=' . Path::formatWindowsPath($destPath) . '"' . PHP_EOL;
271 $batch .= '"' . $mkcertExe . '" -install' . PHP_EOL;
272 $batch .= 'IF EXIST "' . Path::formatWindowsPath($rootCaPath) . '" (ECHO OK)' . PHP_EOL;
273 $result = Batch::exec('mkcertInstall', $batch);
274
275 if ($result === false) {
276 Log::error('Batch execution failed for mkcert -install');
277 return false;
278 }
279
280 // Re-check after installation
281 if (!file_exists($rootCaPath)) {
282 Log::error('Root CA still missing after mkcert -install at: ' . $rootCaPath);
283 return false;
284 }
285 Log::info('Root CA successfully created and verified.');
286 }
287 return true;
288 }
static info($data, $file=null)
static getMkcertRootCaName()

References $result, ensureMkcertExeExists(), Log\error(), Batch\exec(), Path\formatWindowsPath(), Path\getMkcertExe(), Path\getMkcertRootCaName(), and Log\info().

Referenced by createCrt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ensureSslDirExists()

ensureSslDirExists ( )
private

Ensures that the SSL directory exists, creating it if necessary.

Returns
string The SSL path.

Definition at line 50 of file class.openssl.php.

51 {
52 $sslPath = Path::getSslPath();
53 if (!is_dir($sslPath)) {
54 Log::info('SSL directory missing, creating: ' . $sslPath);
55 if (mkdir($sslPath, 0700, true)) {
56 @chmod($sslPath, 0700);
57 // Create .gitignore if the directory was just created
58 $gitignorePath = $sslPath . '/.gitignore';
59 if (!file_exists($gitignorePath)) {
60 file_put_contents($gitignorePath, '# git holder' . PHP_EOL);
61 }
62 } else {
63 Log::error('Failed to create SSL directory: ' . $sslPath);
64 }
65 } else {
66 // Even if directory exists, ensure .gitignore is present
67 $gitignorePath = $sslPath . '/.gitignore';
68 if (!file_exists($gitignorePath)) {
69 file_put_contents($gitignorePath, '# git holder' . PHP_EOL);
70 }
71 }
72
73 if (!is_readable($sslPath) || !is_writable($sslPath)) {
74 Log::warning('SSL directory is not fully accessible. Attempting to relax permissions: ' . $sslPath);
75
76 // Set permissive permissions for local dev environment (0755 allows owner RWX, group/others RX)
77 @chmod($sslPath, 0755);
78 clearstatcache(true, $sslPath);
79
80 if (!is_readable($sslPath) || !is_writable($sslPath)) {
81 Log::error('SSL directory is still not readable/writable after permission adjustment: ' . $sslPath);
82 }
83 }
84
85 return $sslPath;
86 }
static warning($data, $file=null)

References Log\error(), Path\getSslPath(), Log\info(), and Log\warning().

Referenced by createCrt(), getCrts(), and removeCrt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ existsCrt()

existsCrt ( $name)

Checks if a certificate with the specified name exists.

Parameters
string$nameThe name of the certificate.
Returns
bool True if the certificate exists, false otherwise.

Definition at line 376 of file class.openssl.php.

377 {
378 $ppkPath = Path::getSslPath() . '/' . $name . '.ppk';
379 $crtPath = Path::getSslPath() . '/' . $name . '.crt';
380
381 return is_file($ppkPath) && is_file($crtPath);
382 }

References Path\getSslPath().

Here is the call graph for this function:

◆ genSslCertificate()

genSslCertificate ( )

Displays a WinBinder GUI for generating an SSL certificate.

Definition at line 387 of file class.openssl.php.

388 {
389 global $bearsamppLang, $bearsamppWinbinder;
390
391 $initServerName = 'test.local';
392 $initDocumentRoot = Path::formatWindowsPath(Path::getSslPath());
393
394 $bearsamppWinbinder->reset();
395 $wbWindow = $bearsamppWinbinder->createAppWindow($bearsamppLang->getValue(Lang::GENSSL_TITLE), 490, 160, WBC_NOTIFY, WBC_KEYDOWN | WBC_KEYUP);
396
397 $wbLabelName = $bearsamppWinbinder->createLabel($wbWindow, $bearsamppLang->getValue(Lang::NAME) . ' :', 15, 15, 85, null, WBC_RIGHT);
398 $this->wbGenSslInputName = $bearsamppWinbinder->createInputText($wbWindow, $initServerName, 105, 13, 150, null);
399
400 $wbLabelDest = $bearsamppWinbinder->createLabel($wbWindow, $bearsamppLang->getValue(Lang::TARGET) . ' :', 15, 45, 85, null, WBC_RIGHT);
401 $this->wbGenSslInputDest = $bearsamppWinbinder->createInputText($wbWindow, $initDocumentRoot, 105, 43, 190, null, null, WBC_READONLY);
402 $this->wbGenSslBtnDest = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_BROWSE), 300, 43, 110);
403
404 $this->wbGenSslProgressBar = $bearsamppWinbinder->createProgressBar($wbWindow, 3, 15, 97, 275);
405 $this->wbGenSslBtnSave = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_SAVE), 300, 92);
406 $this->wbGenSslBtnCancel = $bearsamppWinbinder->createButton($wbWindow, $bearsamppLang->getValue(Lang::BUTTON_CANCEL), 387, 92);
407
408 $bearsamppWinbinder->setHandler($wbWindow, $this, 'genSslCertificateHandler');
409
410 $bearsamppWinbinder->mainLoop();
411 $bearsamppWinbinder->reset();
412 }
const GENSSL_TITLE
const BUTTON_SAVE

References $bearsamppLang, Lang\BUTTON_BROWSE, Lang\BUTTON_CANCEL, Lang\BUTTON_SAVE, Path\formatWindowsPath(), Lang\GENSSL_TITLE, Path\getSslPath(), Lang\NAME, and Lang\TARGET.

Here is the call graph for this function:

◆ genSslCertificateHandler()

genSslCertificateHandler ( $window,
$id,
$ctrl,
$param1,
$param2 )

Handler for the SSL certificate generation WinBinder GUI.

Definition at line 417 of file class.openssl.php.

418 {
419 global $bearsamppLang, $bearsamppOpenSsl, $bearsamppWinbinder;
420
421 switch ($id) {
422 case $this->wbGenSslBtnDest[WinBinder::CTRL_ID]:
423 $target = $bearsamppWinbinder->getText($this->wbGenSslInputDest[WinBinder::CTRL_OBJ]);
424 $target = $bearsamppWinbinder->sysDlgPath($window, $bearsamppLang->getValue(Lang::GENSSL_PATH), $target);
425 if ($target && is_dir($target)) {
426 $bearsamppWinbinder->setText($this->wbGenSslInputDest[WinBinder::CTRL_OBJ], $target . '\\');
427 }
428 break;
429 case $this->wbGenSslBtnSave[WinBinder::CTRL_ID]:
430 $name = $bearsamppWinbinder->getText($this->wbGenSslInputName[WinBinder::CTRL_OBJ]);
431 $target = $bearsamppWinbinder->getText($this->wbGenSslInputDest[WinBinder::CTRL_OBJ]);
432
433 $bearsamppWinbinder->setProgressBarMax($this->wbGenSslProgressBar, 3);
434 $bearsamppWinbinder->incrProgressBar($this->wbGenSslProgressBar);
435
436 $target = Path::formatUnixPath($target);
437 if ($bearsamppOpenSsl->createCrt($name, $target)) {
438 $bearsamppWinbinder->incrProgressBar($this->wbGenSslProgressBar);
439 $bearsamppWinbinder->messageBoxInfo(
440 sprintf($bearsamppLang->getValue(Lang::GENSSL_CREATED), $name),
442 $bearsamppWinbinder->destroyWindow($window);
443 } else {
444 $bearsamppWinbinder->messageBoxError($bearsamppLang->getValue(Lang::GENSSL_CREATED_ERROR), $bearsamppLang->getValue(Lang::GENSSL_TITLE));
445 $bearsamppWinbinder->resetProgressBar($this->wbGenSslProgressBar);
446 }
447 break;
448 case IDCLOSE:
449 case $this->wbGenSslBtnCancel[WinBinder::CTRL_ID]:
450 $bearsamppWinbinder->destroyWindow($window);
451 break;
452 }
453 }
const GENSSL_CREATED
const GENSSL_CREATED_ERROR

References $bearsamppLang, WinBinder\CTRL_ID, WinBinder\CTRL_OBJ, Path\formatUnixPath(), Lang\GENSSL_CREATED, Lang\GENSSL_CREATED_ERROR, Lang\GENSSL_PATH, and Lang\GENSSL_TITLE.

Here is the call graph for this function:

◆ getCrts()

getCrts ( )

Retrieves existing certificates from the SSL directory.

Returns
array List of certificate names.

Definition at line 460 of file class.openssl.php.

461 {
462 $sslPath = $this->ensureSslDirExists();
463 $certs = [];
464 if (is_dir($sslPath)) {
465 $files = glob($sslPath . '/*.crt');
466 if ($files !== false) {
467 foreach ($files as $file) {
468 $certs[] = basename($file, '.crt');
469 }
470 }
471 }
472 sort($certs);
473 return $certs;
474 }

References ensureSslDirExists().

Referenced by delSslCertificateHandler(), and rebuildAllCerts().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isExpired()

isExpired ( $name)

Checks if a certificate with the specified name is expired or about to expire.

Parameters
string$nameThe name of the certificate.
Returns
bool True if the certificate is expired or missing, false otherwise.

Definition at line 482 of file class.openssl.php.

483 {
484 $crtPath = Path::getSslPath() . '/' . $name . '.crt';
485 $pubPath = Path::getSslPath() . '/' . $name . '.pub';
486
487 if (!is_file($crtPath)) {
488 Log::trace('SSL certificate file missing: ' . $crtPath);
489 return true;
490 }
491
492 if (!is_file($pubPath)) {
493 Log::trace('SSL public certificate file missing: ' . $pubPath);
494 return true;
495 }
496
497 if (!extension_loaded('openssl')) {
498 Log::warning('OpenSSL extension not loaded. Cannot parse certificate for expiry check. Assuming NOT expired if file exists.');
499 return false;
500 }
501
502 $crtContent = file_get_contents($crtPath);
503 if ($crtContent === false) {
504 Log::error('Could not read certificate file: ' . $crtPath);
505 return true;
506 }
507
508 $certInfo = openssl_x509_parse($crtContent);
509 if ($certInfo === false) {
510 Log::error('Could not parse certificate: ' . $crtPath . '. OpenSSL error: ' . openssl_error_string());
511 return true;
512 }
513
514 if (isset($certInfo['validTo_time_t'])) {
515 $isExpired = $certInfo['validTo_time_t'] < time();
516 if ($isExpired) {
517 Log::trace('SSL certificate expired: ' . $name . ' (Expired on ' . date('Y-m-d H:i:s', $certInfo['validTo_time_t']) . ')');
518 }
519 return $isExpired;
520 }
521
522 Log::error('Could not find expiry date in certificate: ' . $crtPath);
523 return true;
524 }

References Log\error(), Path\getSslPath(), Log\trace(), and Log\warning().

Here is the call graph for this function:

◆ makeRootCa()

makeRootCa ( )

Creates a new Root CA and reinstalls it, then rebuilds all certificates.

Returns
bool True if successful.

Definition at line 93 of file class.openssl.php.

94 {
95 if (!$this->ensureMkcertExeExists()) {
96 return false;
97 }
98 $destPath = Path::getSslPath();
99 $mkcertExe = Path::getMkcertExe();
100
101 Log::info('Creating new Root CA and installing it...');
102
103 $rootCaPath = Path::getSslPath() . '/' . Path::getMkcertRootCaName();
104 $batch = 'SET "CAROOT=' . Path::formatWindowsPath(Path::getSslPath()) . '"' . PHP_EOL;
105 $batch .= '"' . $mkcertExe . '" -uninstall' . PHP_EOL;
106 $batch .= '"' . $mkcertExe . '" -install' . PHP_EOL;
107 $batch .= 'IF EXIST "' . Path::formatWindowsPath($rootCaPath) . '" (ECHO OK)' . PHP_EOL;
108
109 // Wait for the Root CA file to appear or timeout
110 $result = Batch::exec('mkcertMakeRootCa', $batch);
111
112 if (!file_exists($rootCaPath)) {
113 Log::error('Failed to create Root CA file at: ' . $rootCaPath);
114 return false;
115 }
116
117 // Display info about the new Root CA
118 $batch = 'SET "CAROOT=' . Path::formatWindowsPath(Path::getSslPath()) . '"' . PHP_EOL;
119 $batch .= '"' . $mkcertExe . '" -CAROOT' . PHP_EOL;
120 $caRootInfo = Batch::exec('mkcertCaRootInfo', $batch);
121 if ($caRootInfo && isset($caRootInfo[0])) {
122 Log::info('mkcert CAROOT is set to: ' . $caRootInfo[0]);
123 }
124
125 Log::info('Root CA created. Rebuilding all existing certificates and ensuring localhost exists...');
126
127 // Ensure localhost is created/rebuilt
128 $this->createCrt('localhost');
129
130 return $this->rebuildAllCerts();
131 }
createCrt($name, $destPath=null)

References $result, createCrt(), ensureMkcertExeExists(), Log\error(), Batch\exec(), Path\formatWindowsPath(), Path\getMkcertExe(), Path\getMkcertRootCaName(), Path\getSslPath(), Log\info(), and rebuildAllCerts().

Here is the call graph for this function:

◆ rebuildAllCerts()

rebuildAllCerts ( )

Rebuilds all existing certificates in the SSL directory.

Returns
bool True if all certificates were rebuilt successfully.

Definition at line 138 of file class.openssl.php.

139 {
140 $certs = $this->getCrts();
141 $success = true;
142
143 foreach ($certs as $cert) {
144 Log::info('Rebuilding certificate: ' . $cert);
145 if (!$this->createCrt($cert)) {
146 Log::error('Failed to rebuild certificate: ' . $cert);
147 $success = false;
148 }
149 }
150
151 return $success;
152 }

References createCrt(), Log\error(), getCrts(), and Log\info().

Referenced by makeRootCa().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ removeCrt()

removeCrt ( $name,
$destPath = null )

Removes a certificate with the specified name.

Parameters
string$nameThe name of the certificate.
string | null$destPathThe destination path where the certificate files are saved. If null, the default SSL path is used.
Returns
bool True if the certificate was removed successfully, false otherwise.

Definition at line 533 of file class.openssl.php.

534 {
535 if ($name === 'localhost') {
536 Log::warning('Attempted to remove protected "localhost" certificate. Operation cancelled.');
537 return false;
538 }
539 $destPath = empty($destPath) ? $this->ensureSslDirExists() : $destPath;
540
541 // Basic validation for name to prevent arbitrary file deletion
542 if (!preg_match('/^[a-zA-Z0-9._-]+$/', $name)) {
543 Log::error('Invalid certificate name for removal: ' . $name);
544 return false;
545 }
546
547 $ppkPath = $destPath . '/' . $name . '.ppk';
548 $crtPath = $destPath . '/' . $name . '.crt';
549 $pubPath = $destPath . '/' . $name . '.pub';
550
551 Log::info('Removing SSL certificate: ' . $name . ' from ' . $destPath);
552 return @unlink($ppkPath) && @unlink($crtPath) && @unlink($pubPath);
553 }

References ensureSslDirExists(), Log\error(), Log\info(), and Log\warning().

Here is the call graph for this function:

◆ validateCertificateName()

validateCertificateName ( $name)
private

Validates the certificate name to prevent command injection attacks. Requires names to start with alphanumeric character to prevent mkcert flag injection. Uses filesystem-safe whitelist (same as removeCrt) to support existing cert names and prevent CMD metacharacter injection. Allows: alphanumeric, dots, dashes, underscores.

Parameters
string$nameThe certificate name to validate.
Returns
bool True if the name is valid, false otherwise.

Definition at line 163 of file class.openssl.php.

164 {
165 if (empty($name)) {
166 return false;
167 }
168
169 // Filesystem-safe whitelist with mandatory alphanumeric first character:
170 // - Prevents CLI flag injection (leading `-`)
171 // - Prevents relative path traversal (leading `.`)
172 // - Allows remaining chars to be alphanumeric, dots, dashes, underscores
173 if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/', $name)) {
174 return false;
175 }
176
177 return true;
178 }

Referenced by createCrt().

Here is the caller graph for this function:

Field Documentation

◆ $rootCaName

$rootCaName = 'BearsamppRootCA'
private

Definition at line 26 of file class.openssl.php.

◆ $wbDelSslBtnCancel

$wbDelSslBtnCancel
private

Definition at line 25 of file class.openssl.php.

◆ $wbDelSslBtnDelete

$wbDelSslBtnDelete
private

Definition at line 24 of file class.openssl.php.

◆ $wbDelSslBtnDest

$wbDelSslBtnDest
private

Definition at line 22 of file class.openssl.php.

◆ $wbDelSslInputDest

$wbDelSslInputDest
private

Definition at line 21 of file class.openssl.php.

◆ $wbDelSslListCerts

$wbDelSslListCerts
private

Definition at line 20 of file class.openssl.php.

◆ $wbDelSslProgressBar

$wbDelSslProgressBar
private

Definition at line 23 of file class.openssl.php.

◆ $wbGenSslBtnCancel

$wbGenSslBtnCancel
private

Definition at line 18 of file class.openssl.php.

◆ $wbGenSslBtnDest

$wbGenSslBtnDest
private

Definition at line 15 of file class.openssl.php.

◆ $wbGenSslBtnSave

$wbGenSslBtnSave
private

Definition at line 17 of file class.openssl.php.

◆ $wbGenSslInputDest

$wbGenSslInputDest
private

Definition at line 14 of file class.openssl.php.

◆ $wbGenSslInputName

$wbGenSslInputName
private

Definition at line 13 of file class.openssl.php.

◆ $wbGenSslProgressBar

$wbGenSslProgressBar
private

Definition at line 16 of file class.openssl.php.


The documentation for this class was generated from the following file: