FusionDirectory.php 7.60 KiB
<?php
/*
  This code is part of ldap-config-manager (https://www.fusiondirectory.org/)
  Copyright (C) 2020-2024  FusionDirectory
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
namespace FusionDirectory\Cli;
use Exception;
use SimpleXMLElement;
use SodiumException;
/**
 * Base class for interacting with FusionDirectory specifics
class FusionDirectory extends Application
  /**
   * Current values of variables
   * @var array<string,string>
  protected $vars;
  protected $configFilePath;
  /**
   * @var string path to the FusionDirectory secrets file containing the key to decrypt passwords
  protected string $secretsFilePath;
  public function __construct ()
    parent::__construct();
    // Variables to be set during script calling.
    $this->vars = [
      'fd_home'          => '/usr/share/fusiondirectory',
      'fd_config_dir'    => '/etc/fusiondirectory',
      'config_file'      => 'fusiondirectory.conf',
      'secrets_file'     => 'fusiondirectory.secrets',
      'fd_cache'         => '/var/cache/fusiondirectory',
      'fd_smarty_path'   => '/usr/share/php/smarty3/Smarty.class.php',
      'fd_spool_dir'     => '/var/spool/fusiondirectory',
      'locale_dir'       => 'locale',
      'class_cache'      => 'class.cache',
      'locale_cache_dir' => 'locale',
      'tmp_dir'          => 'tmp',
      'fai_log_dir'      => 'fai',
      'template_dir'     => 'template'
  /**
   * @return array[]
  public function getVarOptions (): array
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
return [ 'list-vars' => [ 'help' => 'List an example of a possible var to give to --set-var followed by --write-vars', 'command' => 'cmdListVars', ], 'set-var:' => [ 'help' => 'Set the variable value', 'command' => 'cmdSetVar', ], ]; } /** * Read variables.inc file from FusionDirectory and update variables accordingly */ protected function readFusionDirectoryVariablesFile (): void { if ($this->verbose()) { printf('Reading vars from %s' . "\n", $this->vars['fd_home'] . '/include/variables.inc'); } require_once($this->vars['fd_home'] . '/include/variables.inc'); $fd_cache = $this->removeFinalSlash(CACHE_DIR); $varsToSet = [ 'fd_config_dir' => $this->removeFinalSlash(CONFIG_DIR), 'config_file' => $this->removeFinalSlash(CONFIG_FILE), 'fd_smarty_path' => $this->removeFinalSlash(SMARTY), 'fd_spool_dir' => $this->removeFinalSlash(SPOOL_DIR), 'fd_cache' => $fd_cache, 'locale_cache_dir' => $this->removeFinalSlash(str_replace($fd_cache . '/', '', LOCALE_DIR)), 'tmp_dir' => $this->removeFinalSlash(str_replace($fd_cache . '/', '', TEMP_DIR)), 'template_dir' => $this->removeFinalSlash(str_replace($fd_cache . '/', '', CONFIG_TEMPLATE_DIR)), 'fai_log_dir' => $this->removeFinalSlash(str_replace($fd_cache . '/', '', FAI_LOG_DIR)), 'class_cache' => $this->removeFinalSlash(CLASS_CACHE), ]; foreach ($varsToSet as $var => $value) { if (isset($this->vars[$var])) { $this->vars[$var] = $value; } } } /** * @return void * Only print an example of variables that can be changed. */ protected function cmdListVars (): void { foreach ($this->vars as $key => $value) { printf("%-20s [%s]\n", $key, $value); } } /** * @param string $var * @return void * @throws Exception * Note : This allows to set var in the variables.php file in FD. * This method needs rework as multiple variables are not received, only a string. * (logic of multiple should be defined in parent class) */ protected function cmdSetVar (string $var): void { $varsToSet = []; if (preg_match('/^([^=]+)=(.+)$/', $var, $m)) { if (isset($this->vars[strtolower($m[1])])) { $varsToSet[strtolower($m[1])] = $m[2];
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} else { throw new Exception('Var "' . $m[1] . '" does not exists. Use --list-vars to get the list of vars.'); } } else { throw new Exception('Incorrect syntax for --set-var: "' . $var . '". Use var=value'); } if (isset($varsToSet['fd_home'])) { if ($this->verbose()) { printf('Setting var %s to "%s"' . "\n", 'fd_home', $this->removeFinalSlash($varsToSet['fd_home'])); } $this->vars['fd_home'] = $this->removeFinalSlash($varsToSet['fd_home']); } $this->readFusionDirectoryVariablesFile(); unset($varsToSet['fd_home']); foreach ($varsToSet as $var => $value) { if ($this->verbose()) { printf('Setting var %s to "%s"' . "\n", $var, $value); } $this->vars[$var] = $value; } } /** * Load locations information from FusionDirectory configuration file * @return array<array{tls: bool, uri: string, base: string, bind_dn: string, bind_pwd: string}> locations * @throws SodiumException * @throws Exception */ protected function loadFusionDirectoryConfigurationFile (): array { if ($this->verbose()) { printf('Loading configuration file from %s' . "\n", $this->configFilePath); } $secret = NULL; if (file_exists($this->secretsFilePath)) { if ($this->verbose()) { printf('Using secrets file %s' . "\n", $this->secretsFilePath); } $lines = file($this->secretsFilePath, FILE_SKIP_EMPTY_LINES); if ($lines === FALSE) { throw new Exception('Could not open "' . $this->secretsFilePath . '"'); } foreach ($lines as $line) { if (preg_match('/RequestHeader set FDKEY ([^ \n]+)\n/', $line, $m)) { $secret = sodium_base642bin($m[1], SODIUM_BASE64_VARIANT_ORIGINAL, ''); break; } } } // Note: this function is case sensitive with xml tags and attributes, FD is not $xml = new SimpleXMLElement($this->configFilePath, 0, TRUE); $locations = []; foreach ($xml->main->location as $loc) { $ref = $loc->referral[0]; $location = [ 'tls' => (isset($loc['ldapTLS']) && (strcasecmp((string)$loc['ldapTLS'], 'TRUE') === 0)), 'uri' => (string)$ref['URI'], 'base' => (string)($ref['base'] ?? $loc['base'] ?? ''), 'bind_dn' => (string)$ref['adminDn'], 'bind_pwd' => (string)$ref['adminPassword'], ]; if ($location['base'] === '') { if (preg_match('|^(.*)/([^/]+)$|', $location['uri'], $m)) { /* Format from FD<1.3 */ $location['uri'] = $m[1]; $location['base'] = $m[2]; } else {
211212213214215216217218219220221222223224225226227228229
throw new Exception('"' . $location['uri'] . '" does not contain any base!'); } } if ($secret !== NULL) { $location['bind_pwd'] = SecretBox::decrypt($location['bind_pwd'], $secret); } $locations[(string)$loc['name']] = $location; if ($this->verbose()) { printf('Found location %s (%s)' . "\n", (string)$loc['name'], $location['uri']); } } if (count($locations) < 1) { throw new Exception('No location found in configuration file'); } return $locations; } }