public function pre_process($person) { parent::pre_process($person); $res = false; if ($this->person->isAuth()) { if (isset($_GET['file_cert'])) { $authKey = Input::sanitizeCertKey($_GET['file_cert']); try { $cert = $this->ca->getCert($authKey); if (isset($cert) && $cert->isValid()) { include 'file_download.php'; download_file($cert->getPEMContent(), 'usercert.pem'); exit(0); } } catch (ConfusaGenException $cge) { Framework::error_output($this->translateMessageTag('downl_err_nodownload') . " " . htmlentities($cge->getMessage())); } } else { if (isset($_GET['cert_status'])) { $this->pollCertStatusAJAX(Input::sanitizeCertKey($_GET['cert_status'])); } else { if (isset($_GET['certlist_all'])) { $this->showAll = $_GET['certlist_all'] == "true"; } else { if (isset($_GET['revoke']) && $_GET['revoke'] == 'revoke_single') { $order_number = Input::sanitizeCertKey($_GET['order_number']); /* sanitized by checking inclusion in the REVOCATION_REASONS * array */ if (!array_key_exists('reason', $_GET)) { Framework::error_output($this->translateMessageTag('rev_err_singlenoreason')); return; } $reason = Input::sanitizeText(trim($_GET['reason'])); try { if (!isset($order_number) || !isset($reason)) { Framework::error_output("Revoke Certificate: Errors with parameters, not set properly"); } elseif (!$this->checkRevocationPermissions($order_number)) { Framework::error_output($this->translateMessageTag('rev_err_singlenoperm')); } elseif (!$this->ca->revokeCert($order_number, $reason)) { Framework::error_output($this->translateMessageTag('rev_err_notyet1') . htmlentities($order_number) . $this->translateMessageTag('rev_err_notyet2') . htmlentities($reason)); } else { Framework::message_output($this->translateMessageTag('rev_suc_single1') . htmlentities($order_number) . $this->translateMessageTag('rev_suc_single2')); if (Config::get_config('ca_mode') === CA_COMODO && Config::get_config('capi_test') === true) { Framework::message_output($this->translateTag('l10n_msg_revsim1', 'revocation')); } } } catch (ConfusaGenException $cge) { Framework::error_output($this->translateMessageTag('rev_err_singleunspec') . " " . htmlentities($cge->getMessage())); } } } } } } return false; }
function confusaErrorHandler($errno, $errstr, $errfile, $errline) { $msg = ""; $display_errors = ini_get('display_errors') == true || ini_get('display_errors') == "stdout"; switch ($errno) { case E_ERROR: case E_USER_ERROR: $msg = "PHP Fatal Error: {$errstr} in {$errfile} on line {$errline}"; if ($display_errors) { Framework::error_output($msg); } break; case E_WARNING: case E_USER_WARNING: $msg = "PHP Warning: {$errstr} in {$errfile} on line {$errline}"; if ($display_errors) { Framework::warning_output($msg); } break; case E_NOTICE: case E_USER_NOTICE: $msg = "PHP Notice: {$errstr} in {$errfile} on line {$errline}"; if ($display_errors) { Framework::message_output($msg); } break; case E_STRICT: $msg = "PHP Strict: {$errstr} in {$errfile} on line {$errline}"; break; default: $msg = "PHP Unknown: {$errstr} in {$errfile} on line {$errline}"; if ($display_errors) { Framework::message_output($msg); } break; } /* if logging is turned on, log the errors to the respective PHP log */ if (ini_get('log_errors') && error_reporting() & $errno) { error_log($msg); } return true; }
public function pre_process($person) { $res = true; $this->setPerson($person); $this->account = NRENAccount::get($this->person); /* If the caller is not a nren-admin or Confusa is not in online mode, we stop here */ if (!$this->person->isNRENAdmin() || Config::get_config('ca_mode') != CA_COMODO) { return false; } $login_name = false; $password = false; $ap_name = false; if (isset($_POST['account']) && $_POST['account'] === 'edit') { /* We must use POST as we may pass along a password and * we do not want to set that statically in the subject-line. */ if (isset($_POST['login_name'])) { $ln = $_POST['login_name']; $login_name = Input::sanitizeText(htmlspecialchars($ln)); if ($ln === $login_name) { $this->account->setLoginName($login_name); $res = false; } else { /* FIXME: l10n */ Framework::error_output("The new login_name contains illegal characters, dropping new login!"); } } /* Do not sanitize password, we should allow special characters and * stuff, we should url-encode it. If Comodo does not sanitize * their password, it's their business, not ours. */ if (isset($_POST['password']) && $_POST['password'] !== "") { $this->account->setPassword($_POST['password']); } if (isset($_POST['ap_name'])) { $ap = $_POST['ap_name']; $ap_name = Input::sanitizeText(htmlspecialchars($ap)); if ($ap === $ap_name) { $this->account->setAPName($ap_name); } else { /* FIXME: l10n */ Framework::error_output("Cleaned ap-name and it contains illegal characters, dropping new name!"); $res = false; } } /* should we validate? */ try { $validate = false; if (isset($_POST['verify_ca_cred']) && $_POST['verify_ca_cred'] === "yes") { $validate = true; } if ($this->account->save($validate)) { /* FIXME: l10n */ Framework::success_output("CA Account details successfully updated!"); } else { Framework::message_output("No changes to account-details, not updating."); } } catch (ConfusaGenException $cge) { /* FIXME: l10n */ Framework::error_output("Could not update account-data: " . $cge->getMessage()); } } parent::pre_process($person); return $res; }
/** * delSubscriber - remove the subscriber from the NREN and Confusa. * * This will remove the subscriber *permanently* along with all it's * affiliated subscriber admins (this is handled by the database-schema * with the 'ON DELETE CASCADE'. * * @param id String|integer the ID of the institution/subscriber in the database. * */ private function delSubscriber($id) { if (!isset($id) || $id === "") { Framework::error_output("Cannot delete subscriber with unknown id!"); } $nren = $this->person->getNREN(); /* * Make sure that we are deleting a subscriber from the current NREN. */ try { $query = "SELECT nren_id, subscriber FROM nren_subscriber_view "; $query .= "WHERE nren=? AND subscriber_id=?"; $res = MDB2Wrapper::execute($query, array('text', 'text'), array($this->person->getNREN(), $id)); } catch (DBQueryException $dbqe) { $errorTag = PW::create(); $msg = "Could not delete subscriber with ID {$id} from DB."; Logger::logEvent(LOG_NOTICE, "NRENAdmin", "delSubscriber()", $msg, __LINE__, $errorTag); Framework::message_output($msg . "<br />[{$errorTag}] Server said: " . htmlentities($dbqe->getMessage())); return false; } catch (DBStatementException $dbse) { $errorTag = PW::create(); $msg = "Could not delete subsriber with ID {$id} from DB, due to problems with the " . "statement. Probably this is a configuration error. Server said: " . $dbse->getMessage(); Logger::logEvent(LOG_NOTICE, "NRENAdmin", "delSubscriber()", $msg, __LINE__, $errorTag); Framework::message_output("[{$errorTag}]" . htmlentities($msg)); return false; } if (count($res) != 1) { Framework::error_output("Could not find a unique NREN/subscriber pair for subscriber with id " . htmlentities($id)); return false; } $nren_id = $res[0]['nren_id']; $subscriberName = $res[0]['subscriber']; if (!isset($nren_id) || $nren_id == "") { Framework::error_output("Could not get the NREN-ID for subscriber " . htmlentities($id) . "Will not delete subscriber (" . htmlentites($id) . ")."); return false; } /* * Revoke all certificates for subscriber */ $ca = CAHandler::getCA($this->person); $list = $ca->getCertListForPersons("", $subscriberName); $count = 0; foreach ($list as $key => $value) { try { if (isset($value['auth_key'])) { echo "<pre>\n"; print_r($value); echo "</pre>\n"; if ($ca->revokeCert($value['auth_key'], "privilegeWithdrawn")) { $count = $count + 1; } } } catch (CGE_KeyRevokeException $kre) { echo $kre->getMessage() . "<br />\n"; } Logger::logEvent(LOG_INFO, "NRENAdmin", "delSubscriber()", "Deleting subscriber, revoked {$count} issued certificates " . "for subscriber {$subscriberName}."); } MDB2Wrapper::update("DELETE FROM subscribers WHERE subscriber_id = ? AND nren_id = ?", array('text', 'text'), array($id, $nren_id)); Logger::logEvent(LOG_INFO, "NRENAdmin", "delSubscriber()", "Deleted subscriber with ID {$id}.\n"); $msg = $this->translateTag('l10n_suc_deletesubs1', 'nrenadmin') . htmlentities($subscriberName) . $this->translateTag('l10n_suc_deletesubs2', 'nrenadmin') . " " . htmlentities($id) . ". " . $this->translateTag('l10n_suc_deletesubs3', 'nrenadmin') . " " . $count . " " . $this->translateTag('l10n_suc_deletesubs4', 'nrenadmin'); Framework::success_output($msg); }
/** * Retrieve a certificate from a remote endpoint (e.g. Comodo). * * @params key either an order-number that can be used to retrieve a * certificate directly or an auth-key with which we can * retrieve the order-number * @param key The order-number or an auth_key that can be transformed * to order_number. * @access public * @throws ConfusaGenException */ public function getCert($key) { $key = $this->transformToOrderNumber($key); Logger::log_event(LOG_DEBUG, "Trying to retrieve certificate with order number " . $key . " from the Comodo collect API. " . $this->owner_string); $collect_endpoint = ConfusaConstants::$CAPI_COLLECT_ENDPOINT . "?loginName=" . $this->account->getLoginName() . "&loginPassword="******"&orderNumber=" . $key . "&queryType=2" . "&responseMimeType=application/x-x509-user-cert"; $data = CurlWrapper::curlContact($collect_endpoint); $STATUS_PEND = "0"; $STATUS_OK = "2"; /* Parse the status response from the remote API */ $status = substr($data, 0, 1); $cert = false; switch ($status) { case $STATUS_OK: $cert = new Certificate(substr($data, 2)); break; case $STATUS_PEND: Framework::message_output("The certificate is being processed and is not yet available"); return null; default: /* extract the error status code which is longer than one character */ $error_parts = explode("\n", $data, 2); /* potential error: response does not contain status code */ if (is_numeric($error_parts[0])) { $msg = $this->capiErrorMessage($error_parts[0], $error_parts[1]); throw new CGE_ComodoAPIException("Received error message {$data} {$msg}\n"); } else { $msg = "Received an unexpected response from the remote API!n" . "Maybe Confusa is not properly configured?\n"; throw new CGE_ComodoAPIException($msg); } } return $cert; }
private function resetNRENMailTpl($nren) { $tpl_file = Config::get_config('custom_mail_tpl') . $nren . '/custom.tpl'; if (file_exists($tpl_file)) { $success = unlink($tpl_file); if ($success === false) { Framework::error_output("Could not reset the notification mail template!" . "Please contact an IT-administrator."); } } Framework::message_output($this->translateTag('l10n_suc_mailreset', 'stylist')); }
public function start() { /* From OWASP (prevent clickjacking): * * This new (nonstandard) X-FRAME-OPTIONS header is used to mark * responses that shouldn't be framed. There are two options with * X-FRAME-OPTIONS. The first is DENY, which prevents everyone from * framing the content. * * This can also be done by apache itself: * a2enmod headers * Add to the Virtualhost, directory that hosts confusa: * Header set X-Frame-Options "DENY" */ header('X-Frame-Options: DENY'); /* * Strict-Transport-Security (RFC 6797) * Once page has been accessed over HTTPS and this header was present, * confirmant browsers will force subsequent requests over HTTPS aswell. */ header('Strict-Transport-Security: max-age=31536000'); /* Set tpl object to content page */ $this->contentPage->setTpl($this->tpl); /* check the authentication-thing, catch the login-hook * This is done via confusa_auth */ try { $this->authenticate(); } catch (CGE_CriticalAttributeException $cae) { $msg = "<b>" . $this->contentPage->translateMessageTag('fw_error_critical_attribute1') . "</b><br /><br />"; $msg .= htmlentities($cae->getMessage()) . "<br /><br />"; $msg .= $this->contentPage->translateMessageTag('fw_error_critical_attribute2'); Framework::error_output($msg); $this->renderError = true; } catch (MapNotFoundException $mnfe) { $msg = $this->contentPage->translateMessageTag('fw_error_map_notfound'); /* if user is admin */ if ($this->person->isNRENAdmin()) { $msg .= "<br /><br />"; $msg .= "<a href=\"attributes.php?mode=admin&anticsrf=" . Framework::getAntiCSRF() . "\">"; $msg .= $this->contentPage->translateMessageTag('fw_error_map_updatemap'); $msg .= "</>\n"; } Framework::error_output($msg); $this->renderError = true; } catch (ConfusaGenException $cge) { Framework::error_output($this->contentPage->translateMessageTag('fw_error_auth') . htmlentities($cge->getMessage())); $this->renderError = true; } if ($this->isCSRFAttempt()) { Framework::error_output($this->contentPage->translateMessageTag('fw_anticsrf_msg')); $this->tpl->assign('instance', Config::get_config('system_name')); $this->tpl->assign('errors', self::$errors); $this->tpl->display('site.tpl'); exit(0); } /* Create a new anti CSRF token and export to the template engine */ $this->current_anticsrf = self::getAntiCSRF(); $this->tpl->assign('ganticsrf', 'anticsrf=' . $this->current_anticsrf); $this->tpl->assign('panticsrf', '<input type="hidden" name="anticsrf" value="' . $this->current_anticsrf . '" />'); /* * Try to run the pre-processing */ try { $res = $this->contentPage->pre_process($this->person); if ($res) { $this->tpl->assign('extraHeader'); } } catch (CGE_RemoteCredentialException $rce) { $msg = $this->contentPage->translateMessageTag('fw_error_remote_credential1'); $msg .= "<i>" . htmlentities($rce->getMessage()) . "</i><br /><br />"; if ($this->person->isNRENAdmin()) { $msg .= "<div style=\"text-align: center\">"; $msg .= self::translateMessageTag('fw_error_remote_credential2') . "</div>"; } else { $msg .= Framework::error_output($this->contentPage->translateMessageTag('fw_error_remote_credential3')); $this->renderError = true; } Framework::warning_output($msg); } catch (KeyNotFoundException $knfe) { $this->renderError = true; $errorTag = PW::create(8); $msg = "[{$errorTag}] " . $this->contentPage->translateMessageTag('fw_keynotfound1'); Logger::logEvent(LOG_NOTICE, "Framework", "start()", "Config-file not properly configured: " . $knfe->getMessage(), __LINE__, $errorTag); $msg .= htmlentities($knfe->getMessage()); $msg .= "<br />" . $this->contentPage->translateMessageTag('fw_keynotfound2'); Framework::error_output($msg); } catch (Exception $e) { Framework::error_output($this->contentPage->translateMessageTag('fw_unhandledexp1') . "<br />" . htmlentities($e->getMessage())); $this->renderError = true; } /* ---------------------------------------------------------------- * Admin messages, trigger on missing elements */ if ($this->person->isNRENAdmin()) { $this->triggerAdminIssues(); } /* Mode-hook, to catch mode-change regardless of target-page (not only * index) */ if (isset($_GET['mode'])) { $new_mode = NORMAL_MODE; if (htmlentities($_GET['mode']) == 'admin') { $new_mode = ADMIN_MODE; } $this->person->setMode($new_mode); } $this->tpl->assign('title_logo', $this->contentPage->translateMessageTag('l10n_title_logo')); $this->tpl->assign('person', $this->person); $this->tpl->assign('subscriber', $this->person->getSubscriber()); $this->tpl->assign('nren', $this->person->getNREN()); $this->tpl->assign('is_online', Config::get_config('ca_mode') === CA_COMODO); /* If we have a renderError, do not allow the user-page to * render, otherwise, run it, and catch all unhandled exception * * The general idea, is that the process() should be * self-contained wrt to exceptions. * * A NREN admin is supposed to be able to "fix stuff" such as for instance * CGE_CriticalAttributeExceptions and should hence see the pages also if * renderError is set. */ if (!$this->renderError || $this->person->isNRENAdmin()) { try { $this->applyNRENBranding(); $this->contentPage->process($this->person); } catch (KeyNotFoundException $knfe) { $errorTag = PW::create(8); $msg = "[{$errorTag}] " . $this->contentPage->translateMessageTag('fw_keynotfound1'); Logger::logEvent(LOG_NOTICE, "Framework", "start()", "Config-file not properly configured: " . $knfe->getMessage(), __LINE__, $errorTag); $msg .= htmlentities($knfe->getMessage()); $msg .= "<br />" . $this->contentPage->translateMessageTag('fw_keynotfound2'); Framework::error_output($msg); } catch (Exception $e) { Logger::logEvent(LOG_INFO, "Framework", "start()", "Unhandleded exception when running contentPage->process()", __LINE__); Framework::error_output($this->contentPage->translateMessageTag('fw_unhandledexp1') . "<br />\n" . htmlentities($e->getMessage())); } } else { $nren = $this->person->getNREN(); if (isset($nren)) { /* if all else fails, at least give the user some recovery information */ Framework::message_output($this->contentPage->translateMessageTag('fw_unrecoverable_nren') . htmlentities($this->person->getEPPN())); } else { $errorTag = PW::create(); Framework::error_output("[{$errorTag}] " . $this->contentPage->translateMessageTag('fw_unrecoverable_nonren')); Logger::logEvent(LOG_WARNING, "Framework", "start()", "User contacting us from " . $_SERVER['REMOTE_ADDR'] . " tried to login from IdP that appears to have no NREN-mapping!", __LINE__, $errorTag); } } $this->tpl->assign('logoutUrl', 'logout.php'); // see render_menu($this->person) $this->tpl->assign('menu', $this->tpl->fetch('menu.tpl')); $this->tpl->assign('errors', self::$errors); $this->tpl->assign('messages', self::$messages); $this->tpl->assign('successes', self::$successes); $this->tpl->assign('warnings', self::$warnings); if (Config::get_config('debug')) { $db_debug_res = ""; $db_debug_res .= "<address>\n"; $db_debug_res .= "During this session, we had "; $db_debug_res .= MDB2Wrapper::getConnCounter() . " individual DB-connections.<br />\n"; $db_debug_res .= "</address>\n"; $this->tpl->assign('db_debug', $db_debug_res); } $this->tpl->display('site.tpl'); if (!$this->renderError) { $this->contentPage->post_process($this->person); } }
/** * Revoke a list of certificates possibly belonging to more than one end-entity * based on an array of auth_keys stored in the session. Based on the number of * certificates that are going to be revoked, this may take some time. * * @param string $reason The reason for revocation (as in RFC 3280) * */ private function revoke_list($reason) { if (Config::get_config('ca_mode') === CA_COMODO && Config::get_config('capi_test') === true) { Framework::message_output($this->translateTag('l10n_msg_revsim1', 'revocation')); } $auth_keys = CS::getSessionKey('auth_keys'); CS::deleteSessionKey('auth_keys'); if (is_null($auth_keys)) { Framework::error_output("Lost session! Please log-out of Confusa, " . "log-in again and try again!\n"); return; } $num_certs = count($auth_keys); $num_certs_revoked = 0; Logger::log_event(LOG_INFO, "Trying to revoke {$num_certs} certificates." . "Administrator contacted us from " . $_SERVER['REMOTE_ADDR'] . " in a bulk (list) revocation request."); foreach ($auth_keys as $auth_key) { try { if (!$this->ca->revokeCert($auth_key, $reason)) { Framework::error_output("Could not revoke certificate " . htmlentities($auth_key) . "."); } else { $num_certs_revoked = $num_certs_revoked + 1; } } catch (ConfusaGenException $cge) { Framework::error_output($cge->getMessage()); } } Logger::log_event(LOG_INFO, "Successfully revoked {$num_certs_revoked} certificates out of {$num_certs}. " . "Administrator contacted us from " . $_SERVER['REMOTE_ADDR'] . " in a bulk (list) revocation request."); Framework::message_output($this->translateTag('l10n_suc_revoke1', 'revocation') . " " . $num_certs_revoked . " " . $this->translateTag('l10n_suc_revoke2', 'revocation') . " " . $num_certs); }