From 790016bd966b70b2835a711ec6c46c3eb30c6872 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Tue, 10 Jun 2008 09:32:17 +0000 Subject: [PATCH] Added configuration checker. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@624 44740490-163a-0410-bde0-09ae8108e29a --- dictionaries/errors.php | 8 + dictionaries/frontpage.php | 4 + templates/default/admin-config.php | 87 ++++++++++ www/admin/config.php | 269 +++++++++++++++++++++++++++++ www/index.php | 5 + 5 files changed, 373 insertions(+) create mode 100644 templates/default/admin-config.php create mode 100644 www/admin/config.php diff --git a/dictionaries/errors.php b/dictionaries/errors.php index b9e9437f2..d31a6067c 100644 --- a/dictionaries/errors.php +++ b/dictionaries/errors.php @@ -828,6 +828,14 @@ $lang = array( 'hr' => 'Izvorna vrijednost administratorske zaporke (auth.adminpassword) u konfiguraciji nije promjenjena, molimo promjenite zaporku.', 'hu' => 'MĂ©g nem lett megváltoztatva a karbantartĂłi jelszĂł (auth.adminpassword) a konfiguráciĂłs fájlban, kĂ©rjĂĽk, változtassa meg most! ', ), + 'title_READCONFIGTEMPLATES' => array ( + 'en' => 'Error reading config-templates directory', + 'no' => 'Feil ved lesing av config-templates katalogen', + ), + 'descr_READCONFIGTEMPLATES' => array ( + 'en' => 'An error occured while simpleSAMLphp was attempting to find the available files in the config-templates directory.', + 'no' => 'En feil oppstod mens simpleSAMLphp prøvde ĂĄ finne tilgjengelige filer i config-templates katalogen.', + ), ); diff --git a/dictionaries/frontpage.php b/dictionaries/frontpage.php index 7244b00f6..e9a08262f 100644 --- a/dictionaries/frontpage.php +++ b/dictionaries/frontpage.php @@ -481,6 +481,10 @@ $lang = array( 'hr' => 'OdrĹľavanje i konfiguriranje simpleSAMLphp-a', 'hu' => 'SimpleSAMLphp karbantartása Ă©s beállĂtása', ), + 'link_configcheck' => array ( + 'no' => 'simpleSAMLphp konfigurasjonskontroll', + 'en' => 'simpleSAMLphp configuraction check', + ), ); diff --git a/templates/default/admin-config.php b/templates/default/admin-config.php new file mode 100644 index 000000000..183a2d201 --- /dev/null +++ b/templates/default/admin-config.php @@ -0,0 +1,87 @@ +<?php + +$this->data['header'] = 'Configuration check'; + +if(array_key_exists('file', $this->data)) { + $this->data['header'] .= ' - ' . htmlspecialchars($this->data['file']); +} + +$this->includeAtTemplateBase('includes/header.php'); + +?> + +<div id="content"> +<h2><?php echo $this->data['header']; ?></h2> + +<?php +if(array_key_exists('files', $this->data)) { + /* File list. */ + echo('<p>Select configuration file to check:</p>'); + + echo('<ul>'); + foreach($this->data['files'] as $file) { + $fileName = htmlspecialchars($file['name']); + if($file['available']) { + $fileUrl = htmlspecialchars($this->data['url'] . '?file=' . urlencode($file['name'])); + echo('<li><a href="' . $fileUrl . '">' . $fileName . '</a></li>'); + } else { + $reason = htmlspecialchars($file['reason']); + echo('<li>' . $fileName . ' - ' . $reason . '</li>'); + } + } + echo('</ul>'); + +} else { + /* File details. */ + + $notices = $this->data['notices']; + $missing = $this->data['missing']; + $superfluous = $this->data['superfluous']; + + if(count($notices) > 0) { + echo('<h3>Notices</h3>'); + echo('<ul>'); + foreach($notices as $i) { + $type = $i['type']; + if($type === 'error') { + $image = 'bomb.png'; + } elseif($type === 'warning') { + $image = 'caution.png'; + } + $imageUrl = '/' . $this->data['baseurlpath'] . 'resources/icons/' . $image; + + echo('<p>'); + echo('<img style="display: inline; float: left; width: 1.7em; height: 1.7em;" src="' . htmlspecialchars($imageUrl) . '" alt="' . htmlspecialchars($type) . '" />'); + echo(htmlspecialchars($i['message'])); + echo('</p>'); + } + echo('</ul>'); + } + + if(count($missing) > 0) { + echo('<h3>Options missing from config file</h3>'); + echo('<ul>'); + foreach($missing as $i) { + echo('<li>' . htmlspecialchars($i) . '</li>'); + } + echo('</ul>'); + } + + if(count($superfluous) > 0) { + echo('<h3>Superfluous options in config file</h3>'); + echo('<ul>'); + foreach($superfluous as $i) { + echo('<li>' . htmlspecialchars($i) . '</li>'); + } + echo('</ul>'); + } + + if(count($notices) === 0 && count($missing) === 0 && count($superfluous) === 0) { + echo('<p>No errors found.</p>'); + } + + echo('<p><a href="' . htmlspecialchars($this->data['url']) . '">Go back to the file list</a></p>'); +} + +$this->includeAtTemplateBase('includes/footer.php'); +?> diff --git a/www/admin/config.php b/www/admin/config.php new file mode 100644 index 000000000..94af3fbf2 --- /dev/null +++ b/www/admin/config.php @@ -0,0 +1,269 @@ +<?php + +require_once('../_include.php'); + + +/* A list of notices which will be shown to the user - only used during file verification. */ +$notices = array(); + + +/** + * This function adds a warning to the list of notices. + * + * @param $message The warning message. + */ +function warning($message) { + global $notices; + + $notices[] = array( + 'type' => 'warning', + 'message' => $message, + ); +} + + +/** + * This function adds an error to the list of notices. + * + * @param $message The error message. + */ +function error($message) { + global $notices; + + $notices[] = array( + 'type' => 'error', + 'message' => $message, + ); +} + + + +/** + * Load a config file + * + * This function loads a configuration file. If the file isn't a standard configuration file + * it will return NULL. Parse errors will result in FALSE being returned. + * + * @param $file Full path to the configuration file. + * @return The array with the configuration values if successfull. NULL if $file isn't a standard + * configuration file. FALSE if there was an parse error. + */ +function loadConfigFile($file) { + assert('file_exists($file)'); + + /* Cache of loaded configuration files - to avoid loading and parsing the same file twice. */ + static $cache = array(); + + /* Check for file in cache. */ + if(array_key_exists($file, $cache)) { + return $cache[$file]; + } + + /* Load the file. */ + $data = file_get_contents($file); + + /* Set $config to a known value. This is used to detect whether $file updates the $config variable. */ + $config = FALSE; + + /* Strip out the php start and end tags. */ + $matches = array(); + if(!preg_match('/\s*<\?php(.*)\?>\s*/s', $data, $matches)) { + /* File doesn't start with <?php and end with ?>. */ + return FALSE; + } + $data = $matches[1]; + + /* Process the file. */ + $res = eval($data); + + if($res === FALSE) { + /* Parse error in file. */ + return FALSE; + } + + if($config === FALSE) { + /* $config not updated - this is not a standard config file. */ + $cache[$file] = NULL; + return NULL; + } + + $cache[$file] = $config; + return $config; +} + + +/** + * Determine whether the specified configuration file can be checked. + * + * @return TRUE if it can be checked, of a string with the reason if it can't be checked. + */ +function canCheckFile($file) { + global $configFiles; + global $configDir; + global $configTemplateDir; + + if(!in_array($file, $configFiles)) { + return 'not in the list of available config files'; + } + + if(!file_exists($configDir . $file)) { + return 'not added to config directory'; + } + + $configTemplateData = loadConfigFile($configTemplateDir . $file); + if($configTemplateData === FALSE) { + return 'parse error in template file'; + } + if($configTemplateData === NULL) { + return 'not a standard configuration file'; + } + + $configData = loadConfigFile($configDir . $file); + if($configData === FALSE) { + return 'parse error in configuration file'; + } + if($configData === NULL) { + return 'invalid configuration file - $config not defined in file'; + } + + return TRUE; +} + + +/** + * Does some checks on config.php + * + * @param $config The configuration data. + */ +function validate_config($config, &$errors, &$warnings) { + + if($config['auth.adminpassword'] === '123') { + error('auth.adminpassword should be changed from the default value.'); + } + + if($config['technicalcontact_email'] === 'na') { + warning('technicalcontact_email should be set to a email address users can contact for support.'); + } + +} + +/* Load configuration and session information. */ +$config = SimpleSAML_Configuration::getInstance(); +$session = SimpleSAML_Session::getInstance(); + +/* Check if the user is logged in with admin access. */ +if (!$session->isValid('login-admin') ) { + SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'auth/login-admin.php', + array('RelayState' => SimpleSAML_Utilities::selfURL()) + ); +} + +/* Find config directories. */ +$configDir = $config->getBaseDir() . 'config/'; +$configTemplateDir = $config->getBaseDir() . 'config-templates/'; + +/* Find all available configuration files. */ + +$configFiles = array(); + +$dirHandle = opendir($configTemplateDir); +if($dirHandle === FALSE) { + SimpleSAML_Utilities::fatalError($session->getTrackId(), 'READCONFIGTEMPLATES'); +} +while(($configFile = readdir($dirHandle)) !== FALSE) { + /* We are only interrested in .php-files in the directory. */ + if(substr($configFile, -4) !== '.php') { + continue; + } + + $configFiles[] = $configFile; +} + +closedir($dirHandle); + +if(array_key_exists('file', $_GET)) { + /* The user has selected a file. */ + $file = $_GET['file']; + + /* Can we check this file? */ + if(canCheckFile($file) !== TRUE) { + $file = NULL; + } +} else { + /* The user needs to select a file. */ + $file = NULL; +} + + +/* Initialize template page. */ +$et = new SimpleSAML_XHTML_Template($config, 'admin-config.php'); +$et->data['url'] = SimpleSAML_Utilities::selfURLNoQuery(); + +if($file === NULL) { + /* No file selected by user - find and show list of available config files. */ + $files = array(); + foreach($configFiles as $configFile) { + $canCheck = canCheckFile($configFile); + if($canCheck === TRUE) { + $available = TRUE; + $reason = ''; + } else { + $available = FALSE; + $reason = $canCheck; + } + $files[] = array( + 'name' => $configFile, + 'available' => $available, + 'reason' => $reason, + ); + } + + /* Show page. */ + $et->data['files'] = $files; + $et->show(); + + /* We are done - exit. */ + exit(); +} + +/* User has selected a configuration file. */ +$et->data['file'] = $file; + +/* If the code reaches this point, parse errors and such in $file should be handled. */ + +/* Load the configuration. */ +$templateData = loadConfigFile($configTemplateDir . $file); +$configData = loadConfigFile($configDir . $file); + + +/* Check if we have a validation function for this config file, and use it if we do. */ +$funcName = 'validate_' . substr($file, 0, -4); +if(is_callable($funcName)) { + call_user_func($funcName, $configData); +} +$et->data['notices'] = $notices; + + +/* Find keys in the template file which are missing in the config file. */ +$missing = array(); +foreach($templateData as $key => $value) { + if(!array_key_exists($key, $configData)) { + $missing[] = $key; + } +} +$et->data['missing'] = $missing; + + +/* Find keys in the config file which are missing in the template file. */ +$superfluous = array(); +foreach($configData as $key => $value) { + if(!array_key_exists($key, $templateData)) { + $superfluous[] = $key; + } +} +$et->data['superfluous'] = $superfluous; + + +$et->show(); + +?> \ No newline at end of file diff --git a/www/index.php b/www/index.php index bc2812b18..ea431fcbd 100644 --- a/www/index.php +++ b/www/index.php @@ -48,6 +48,11 @@ $links[] = array( 'href' => 'admin/phpinfo.php', 'text' => 'link_phpinfo'); +$links[] = array( + 'href' => 'admin/config.php', + 'text' => 'link_configcheck', + ); + $linksmeta = array(); -- GitLab