2222use OCA \Libresign \Service \CertificatePolicyService ;
2323use OCA \Libresign \Service \Crl \CrlRevocationChecker ;
2424use OCA \Libresign \Service \Install \InstallService ;
25+ use OCA \Libresign \Service \Process \ProcessManager ;
26+ use OCA \Libresign \Vendor \Symfony \Component \Process \Process ;
2527use OCP \Files \AppData \IAppDataFactory ;
2628use OCP \IAppConfig ;
2729use OCP \IConfig ;
3941 */
4042class CfsslHandler extends AEngineHandler implements IEngineHandler {
4143 public const CFSSL_URI = 'http://127.0.0.1:8888/api/v1/cfssl/ ' ;
44+ private const PROCESS_SOURCE = 'cfssl ' ;
4245
4346 /** @var Client */
4447 protected $ client ;
@@ -58,6 +61,7 @@ public function __construct(
5861 protected CrlMapper $ crlMapper ,
5962 protected LoggerInterface $ logger ,
6063 CrlRevocationChecker $ crlRevocationChecker ,
64+ private ProcessManager $ processManager ,
6165 ) {
6266 parent ::__construct (
6367 $ config ,
@@ -245,10 +249,11 @@ private function gencert(): void {
245249 $ configPath = $ this ->getCurrentConfigPath ();
246250 $ csrFile = $ configPath . '/csr_server.json ' ;
247251
248- $ cmd = escapeshellcmd ($ binary ) . ' gencert -initca ' . escapeshellarg ($ csrFile );
249- $ output = shell_exec ($ cmd );
252+ $ process = $ this ->createProcess ([$ binary , 'gencert ' , '-initca ' , $ csrFile ]);
253+ $ process ->run ();
254+ $ output = $ process ->getOutput ();
250255
251- if (!$ output ) {
256+ if (!$ process -> isSuccessful () || $ output === '' ) {
252257 throw new \RuntimeException ('cfssl without output. ' );
253258 }
254259
@@ -320,11 +325,26 @@ private function wakeUp(): void {
320325 throw new LibresignException ('CFSSL not configured. ' );
321326 }
322327 $ this ->cfsslServerHandler ->updateExpirity ($ this ->getCaExpiryInDays ());
323- $ cmd = 'nohup ' . $ binary . ' serve -address=127.0.0.1 '
324- . '-ca-key ' . $ configPath . DIRECTORY_SEPARATOR . 'ca-key.pem '
325- . '-ca ' . $ configPath . DIRECTORY_SEPARATOR . 'ca.pem '
326- . '-config ' . $ configPath . DIRECTORY_SEPARATOR . 'config_server.json > /dev/null 2>&1 & echo $! ' ;
327- shell_exec ($ cmd );
328+ $ process = $ this ->createProcess ([
329+ $ binary ,
330+ 'serve ' ,
331+ '-address=127.0.0.1 ' ,
332+ '-ca-key ' , $ configPath . DIRECTORY_SEPARATOR . 'ca-key.pem ' ,
333+ '-ca ' , $ configPath . DIRECTORY_SEPARATOR . 'ca.pem ' ,
334+ '-config ' , $ configPath . DIRECTORY_SEPARATOR . 'config_server.json ' ,
335+ ]);
336+ $ process ->setOptions (['create_new_console ' => true ]);
337+ $ process ->setTimeout (null );
338+ $ process ->disableOutput ();
339+ $ process ->start ();
340+
341+ $ pid = (int )($ process ->getPid () ?? 0 );
342+ if ($ pid > 0 ) {
343+ $ this ->processManager ->register (self ::PROCESS_SOURCE , $ pid , [
344+ 'uri ' => $ this ->getCfsslUri (),
345+ ]);
346+ }
347+
328348 $ loops = 0 ;
329349 while (!$ this ->portOpen () && $ loops <= 4 ) {
330350 sleep (1 );
@@ -349,17 +369,11 @@ private function portOpen(): bool {
349369 }
350370
351371 private function getServerPid (): int {
352- $ cmd = 'ps -eo pid,command| ' ;
353- $ cmd .= 'grep "cfssl.*serve.*-address"| '
354- . 'grep -v grep| '
355- . 'grep -v defunct| '
356- . 'sed -e "s/^[[:space:]]*//"|cut -d" " -f1 ' ;
357- $ output = shell_exec ($ cmd );
358- if (!is_string ($ output )) {
359- return 0 ;
360- }
361- $ pid = trim ($ output );
362- return (int )$ pid ;
372+ $ uri = $ this ->getCfsslUri ();
373+ return $ this ->processManager ->findRunningPid (
374+ self ::PROCESS_SOURCE ,
375+ fn (array $ entry ): bool => ($ entry ['context ' ]['uri ' ] ?? '' ) === $ uri ,
376+ );
363377 }
364378
365379 /**
@@ -381,6 +395,7 @@ private function stopIfRunning(): void {
381395 $ pid = $ this ->getServerPid ();
382396 if ($ pid > 0 ) {
383397 exec ($ this ->parseCommand ('kill -9 ' . $ pid ));
398+ $ this ->processManager ->unregister (self ::PROCESS_SOURCE , $ pid );
384399 }
385400 }
386401
@@ -452,8 +467,10 @@ private function checkBinaries(): array {
452467 ->setTip ('Run occ libresign:install --cfssl ' ),
453468 ];
454469 }
455- $ version = shell_exec ("$ binary version " );
456- if (!is_string ($ version ) || empty ($ version )) {
470+ $ process = $ this ->createProcess ([$ binary , 'version ' ]);
471+ $ process ->run ();
472+ $ version = $ process ->getOutput ();
473+ if (!$ process ->isSuccessful () || empty ($ version )) {
457474 return [
458475 (new ConfigureCheckHelper ())
459476 ->setErrorMessage (sprintf (
@@ -502,6 +519,13 @@ private function checkBinaries(): array {
502519 return $ return ;
503520 }
504521
522+ /**
523+ * @param string[] $command
524+ */
525+ protected function createProcess (array $ command ): Process {
526+ return new Process ($ command );
527+ }
528+
505529 /**
506530 * Get Authority Key Identifier from certificate (needed for CFSSL revocation)
507531 *
0 commit comments