function __construct($person) { parent::__construct($person); $this->attributes = array(); $this->idp = ""; $personIndex = 0; try { $personIndex = (int) Config::get_config('bypass_id'); } catch (KeyNotFoundException $knfe) { Logger::log_event(LOG_NOTICE, __FILE__ . ":" . __LINE__ . " bypass_id not set in config. Using default ID."); } switch ($personIndex) { case 0: $this->attributes = array('cn2' => array('John Doe'), 'eduPersonPrincipalName' => array('*****@*****.**'), 'mail2' => array('*****@*****.**'), 'country' => array('NN'), 'organization' => array('o=Hogwarts, dc=hsww, dc=wiz'), 'nren' => array('testnren'), 'eduPersonEntitlement2' => array('urn:mace:feide.no:sigma.uninett.no:confusa')); $this->idp = "idp.example.org"; break; case 1: $this->attributes = array('cn2' => array('Jane Doe'), 'eduPersonPrincipalName' => array('*****@*****.**'), 'mail2' => array('*****@*****.**', '*****@*****.**', '*****@*****.**'), 'country' => array('NN'), 'organization' => array('o=Barad, dc=Dur'), 'nren' => array('testnren'), 'eduPersonEntitlement2' => array('urn:mace:feide.no:sigma.uninett.no:confusaAdmin', 'urn:mace:feide.no:sigma.uninett.no:confusa')); $this->idp = "idp.example.org"; break; case 2: default: $this->attributes = array('cn2' => array('Ola Nordmann'), 'eduPersonPrincipalName' => array('*****@*****.**', '*****@*****.**', '*****@*****.**'), 'mail2' => array('*****@*****.**'), 'country' => array('NO'), 'organization' => array('o=Hogwarts, dc=hsww, dc=wiz'), 'nren' => array('testnren'), 'eduPersonEntitlement2' => array('urn:mace:feide.no:sigma.uninett.no:confusa')); $this->idp = "idp.example.org"; break; } }
public function process() { if (!$this->person->isNRENAdmin() && !$this->person->isSubscriberAdmin()) { Logger::log_event(LOG_NOTICE, "User " . stripslashes($this->person->getX509ValidCN()) . " tried to access the NREN-area"); $this->tpl->assign('reason', 'You are not an NREN or subscriber-admin'); $this->tpl->assign('content', $this->tpl->fetch('restricted_access.tpl')); return; } if (isset($_GET['attr_value'])) { /* no need for sanitization, only used in array lookup & does not go * into the DB */ $this->handleAttrValueAJAX($_GET['attr_value']); return; } $this->tpl->assign('handle_map', true); if ($this->person->isNRENAdmin()) { $map = $this->person->getNREN()->getMap(); } else { if ($this->person->isSubscriberAdmin()) { /* This will get the Subscriber-map if available, * otherwise it will return the NREN-map. */ $map = $this->person->getMap(); } } $auth = AuthHandler::getAuthManager($this->person); if (isset($map['epodn'])) { $epodn = implode(', ', $auth->getAttributeValue($map['epodn'])); $this->tpl->assign('epodn', $epodn); } else { $this->tpl->assign('epodn', ''); } if (isset($map['cn'])) { $cn = implode(', ', $auth->getAttributeValue($map['cn'])); $this->tpl->assign('cn', $cn); } else { $this->tpl->assign('cn', ''); } if (isset($map['mail'])) { $mail = implode(', ', $auth->getAttributeValue($map['mail'])); $this->tpl->assign('mail', $mail); } else { $this->tpl->assign('mail', ''); } if (isset($map['entitlement'])) { $entitlement = implode(', ', $auth->getAttributeValue($map['entitlement'])); $this->tpl->assign('entitlement', $entitlement); } else { $this->tpl->assign('entitlement', ''); } $this->tpl->assign('map', $map); $this->tpl->assign('keys', AuthHandler::getAuthManager($this->person)->getAttributeKeys($this->person->isNRENAdmin())); $this->tpl->assign('content', $this->tpl->fetch('attributes.tpl')); }
public function process() { if (Config::get_config('cert_product') == PRD_PERSONAL) { $this->tpl->assign('cps', ConfusaConstants::$LINK_PERSONAL_CPS); } else { $this->tpl->assign('cps', ConfusaConstants::$LINK_ESCIENCE_CPS); } Logger::log_event(LOG_INFO, "User acknowledged session: " . CS::getSessionKey('hasAcceptedAUP')); $this->tpl->assign('aup_session_state', CS::getSessionKey('hasAcceptedAUP')); $this->tpl->assign('privacy_notice_text', $this->person->getNREN()->getPrivacyNotice($this->person)); $this->tpl->assign('content', $this->tpl->fetch('confirm_aup.tpl')); }
/** * Constructor * * Note that the person is tied to a OAuth datastore here */ function __construct($person = NULL) { parent::__construct($person); /* Find the path to simpelsamlphp and run the autoloader */ try { $sspdir = Config::get_config('simplesaml_path'); } catch (KeyNotFoundException $knfe) { echo "Cannot find path to simplesaml. This install is not valid. Aborting.<br />\n"; Logger::log_event(LOG_ALERT, "Trying to instantiate simpleSAMLphp without a configured path."); exit(0); } require_once $sspdir . '/lib/_autoload.php'; SimpleSAML_Configuration::setConfigDir($sspdir . '/config'); $this->oauthStore = new OAuthDataStore_Confusa(); $this->oauthServer = new sspmod_oauth_OAuthServer($this->oauthStore); $hmac_method = new OAuthSignatureMethod_HMAC_SHA1(); $this->oauthServer->add_signature_method($hmac_method); $req = OAuthRequest::from_request(); list($consumer, $this->accessToken) = $this->oauthServer->verify_request($req); $this->isAuthenticated = isset($this->accessToken); }
public function process() { if (!$this->person->isNRENAdmin()) { Logger::log_event(LOG_NOTICE, "User " . stripslashes($this->person->getX509ValidCN()) . " tried to access the NREN-area"); $this->tpl->assign('reason', 'You are not an NREN-admin'); $this->tpl->assign('content', $this->tpl->fetch('restricted_access.tpl')); return; } $this->tpl->assign('nren_maint_msg', $this->person->getNREN()->getMaintMsg()); /* set maint-mode msg */ if ($this->person->getNREN()->getMaintMode() === "y") { $this->tpl->assign('maint_mode_msg', $this->translateTag('l10n_nren_maint_mode_enabled', 'portal_config')); } else { $this->tpl->assign('maint_mode_msg', $this->translateTag('l10n_nren_maint_mode_disabled', 'portal_config')); } /* set the radio-buttons */ $this->tpl->assign('maint_mode_v', array('y', 'n')); $this->tpl->assign('maint_mode_t', array(' enabled', ' disabled')); $this->tpl->assign('maint_mode_selected', $this->person->getNREN()->getMaintMode()); $this->tpl->assign('maint_mode', $this->person->getNREN()->getMaintMode() === 'y'); $this->tpl->assign('content', $this->tpl->fetch('portal_config.tpl')); }
public static function curlContactCert($url, $key, $cert, $keypw = false, $postData = null) { if (is_null($key) || is_null($cert) || $key === "" || $cert === "") { throw new ConfusaGenException("Empty key or certificate received " . "when using curlContactCert(). " . "Aborting curl-transfer to url: {$url}"); } if (is_null($postData) || !is_array($postData) || count($postData) == 0) { return false; } /* Do basic URL filtering */ $curlurl = Input::sanitizeURL($url); if (is_null($curlurl) || $curlurl === "" || filter_var($curlurl, FILTER_VALIDATE_URL) === false) { Logger::log_event(LOG_NOTICE, "invalid URL (" . $curlurl . "), aborting curl-fetch."); return false; } Logger::log_event(LOG_DEBUG, "Contacting {$curlurl} using cert AuthN"); /* key should be encrypted, if not, do not use it (not safe!) */ $start = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; if (substr($key, 0, strlen($start)) !== $start) { Logger::log_event(LOG_NOTICE, "Trying to use curlContactCert with unecrypted private key, aborting."); return false; } $rkey = openssl_pkey_get_private($key, $keypw); if ($rkey === false) { Logger::log_event(LOG_NOTICE, "Could not parse private key for CurlContactCert, aborting"); return false; } if (!openssl_x509_check_private_key($cert, $rkey)) { Logger::log_event(LOG_NOTICE, "Provided key and certificate is not a pair, cannot continue."); /* throw exception? */ return false; } $rcert = new Certificate($cert); if (!$rcert->isValid()) { $logline = "Certificate (" . $rcert->getHash() . ") has expired, cannot use this. Aborting curl."; Logger::log_event(LOG_NOTICE, $logline); return false; } if (!file_exists("/tmp/" . $rcert->getHash() . ".key") || !file_exists("/tmp/" . $rcert->getHash() . ".crt")) { if (file_put_contents("/tmp/" . $rcert->getHash() . ".key", $key) === false) { Logger::log_event(LOG_NOTICE, "Could not write key to file"); } if (file_put_contents("/tmp/" . $rcert->getHash() . ".crt", $cert) === false) { Logger::log_event(LOG_NOTICE, "Could not write cert to file"); } } $options = array(CURLOPT_URL => $curlurl, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_SSLKEY => "/tmp/" . $rcert->getHash() . ".key", CURLOPT_SSLCERT => "/tmp/" . $rcert->getHash() . ".crt", CURLOPT_SSLKEYPASSWD => $keypw, CURLOPT_HEADER => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => 1, CURLOPT_CONNECTTIMEOUT => 15); $channel = curl_init(); curl_setopt_array($channel, $options); $data = curl_exec($channel); $status = curl_errno($channel); curl_close($channel); if ($status !== 0) { throw new ConfusaGenException("Could not connect properly to remote " . "endpoint {$curlurl} using cert-based authN! " . "Maybe the Confusa instance is misconfigured? " . "Please contact an administrator!"); } return $data; }
/** getCountriesIdP() return all countries and IdP present in the database * * @params void * @return array list of available countries with corresponding IdP(s) * @access private */ private function getCountriesIdP() { if (isset($this->cidp)) { return $this->cidp; } try { $res = MDB2Wrapper::execute("SELECT idp_url, country, name FROM nrens n " . "LEFT JOIN idp_map im ON n.nren_id = im.nren_id", NULL, NULL); } catch (ConfusaGenException $cge) { Logger::log_event(LOG_WARNING, "Could not get IdP-URLs from the database, " . "make sure DB-connection is properly configured\n"); Framework::error_output($this->translateTag('l10n_err_db_select', 'disco')); return array(); } $this->cidp = array(); foreach ($res as $key => $value) { if (!isset($this->cidp[$value['country']])) { $this->cidp[$value['country']] = array(); } $this->cidp[$value['country']][] = $value['idp_url']; } return $res; }
/** * Update the contact information for a subscriber to a new value * * @param $contact_email string A general subscriber-mail address * @param $contact_phone string The (main) phone number of the subscriber * @param $resp_name string The name of a responsible person at the subscr. * @param $resp_email string e-mail address of a responsible person * @param $help_url string URL of the subscriber's helpdesk * @param $help_email string e-mail address of the subscriber's helpdesk * @param $language string the language code for the subscriber's preferred * language */ private function updateSubscriberContact($language) { $subscriber = $this->person->getSubscriber(); $subscriber->setEmail($contact_email); $subscriber->setPhone($contact_phone); $subscriber->setRespName($resp_name); $subscriber->setRespEmail($resp_email); $subscriber->setHelpURL($help_url); $subscriber->setHelpEmail($help_email); $subscriber->setLanguage($language); try { $subscriber->save(); } catch (ConfusaGenException $cge) { Framework::error_output($this->translateTag('l10n_err_updatesubscr', 'contactinfo') . " " . htmlentities($cge->getMessage())); Logger::log_event(LOG_INFO, "[sadm] Could not update " . "contact of subscriber {$subscriber}: " . $cge->getMessage()); } Framework::success_output($this->translateTag('l10n_suc_updatesubscr', 'contactinfo') . " " . htmlentities($subscriber->getIdPName()) . "."); Logger::log_event(LOG_DEBUG, "[sadm] Updated contact for subscriber {$subscriber}."); }
/** * Synchronize the changes in the subscriber object to the database or * freshly store the subscriber in the DB * * @param $forcedSynch boolean if true, UPDATE the db even if no the object * is not explicitly marked as having changed * @throws ConfusaGenException INSERT/UPDATE of the subscriber failed for * some reason * @access public */ public function save($forcedSynch = false) { if (!$this->isValid()) { return false; } if ($this->pendingChanges || $forcedSynch) { $query = "UPDATE subscribers SET "; if (!is_null($this->getEmail())) { $query .= " subscr_email=:subscr_email, "; $data['subscr_email'] = $this->getEmail(); } if (!is_null($this->getPhone())) { $query .= " subscr_phone=:subscr_phone, "; $data['subscr_phone'] = $this->getPhone(); } if (!is_null($this->getRespName())) { $query .= "subscr_resp_name=:subscr_resp_name, "; $data['subscr_resp_name'] = $this->getRespName(); } if (!is_null($this->getRespEmail())) { $query .= "subscr_resp_email=:subscr_resp_email, "; $data['subscr_resp_email'] = $this->getRespEmail(); } if (!is_null($this->getState())) { $query .= "org_state=:org_state, "; $data['org_state'] = $this->getState(); } if (!is_null($this->getComment())) { $query .= "subscr_comment=:subscr_comment, "; $data['subscr_comment'] = $this->getComment(); } if (!is_null($this->getLanguage())) { $query .= "lang=:lang, "; $data['lang'] = $this->getLanguage(); } if (!is_null($this->getHelpURL())) { $query .= "subscr_help_url=:subscr_help_url, "; $data['subscr_help_url'] = $this->getHelpURL(); } if (!is_null($this->getHelpEmail())) { $query .= "subscr_help_email=:subscr_help_email, "; $data['subscr_help_email'] = $this->getHelpEmail(); } $query = substr($query, 0, -2) . " WHERE subscriber_id=:subscriber_id"; $data['subscriber_id'] = $this->getDBID(); try { MDB2Wrapper::update($query, null, $data); Logger::log_event(LOG_NOTICE, "Updated data for subscriber (" . $this->getDBID() . ") " . $this->getOrgName()); } catch (DBStatementException $dbse) { $msg = __CLASS__ . "::" . __FUNCTION__ . "(" . __LINE__ . ") "; $msg .= "Cannot connect properly to database, some internal error. "; $msg .= "Make sure the DB is configured correctly." . $dbse->getMessage(); throw new ConfusaGenException($msg); } catch (DBQueryException $dbqe) { $msg = __CLASS__ . "::" . __FUNCTION__ . "(" . __LINE__ . ") "; $msg .= "Cannot connect properly to database, "; $msg .= "errors with supplied data."; throw new ConfusaGenException($msg); } $this->pendingChanges = false; return true; } return false; }
/** * downloadArchive() pack the RI-library in a zip-file and present it as * a file to download. * * @param : void * @return : Boolean True if no errors were encountered. */ private function downloadArchive() { require_once 'file_download.php'; $confusa_client = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/Confusa_Client.py"); $parser = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/Parser.py"); $https_client = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/HTTPSClient.py"); $timeout = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/Timeout.py"); $readme = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/README"); $license = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/LICENSE"); $gplv3 = file_get_contents(Config::get_config('install_path') . "/COPYING"); $init = file_get_contents(Config::get_config('install_path') . "/extlibs/XML_Client/__init__.py"); $zip = new ZipArchive(); $name = tempnam($ZIP_CACHE, "XML_Cli_"); $zip->open($name, ZipArchive::OVERWRITE); $zip->addFromString("XML_Client/Confusa_Client.py", $confusa_client); $zip->addFromString("XML_Client/Parser.py", $parser); $zip->addFromString("XML_Client/HTTPSClient.py", $https_client); $zip->addFromString("XML_Client/Timeout.py", $timeout); $zip->addFromString("XML_Client/README", $readme); $zip->addFromString("XML_Client/LICENSE", $license); $zip->addFromString("XML_Client/COPYING", $gplv3); $zip->addFromString("XML_Client/__init__.py", $init); if ($zip->numFiles != 8) { Logger::log_event(LOG_NOTICE, " Could not add all RI-library files to ZIP-archive."); Framework::error_output("Error creating archive. Cannot send"); return False; } if ($zip->close()) { $contents = file_get_contents($name); download_zip($contents, "XML_Client.zip"); } unlink($name); Logger::log_event(LOG_NOTICE, "Sending XML_Client.zip to " . $this->person->getEPPN()); return True; }
/** * Guess the "best" language for a user. This should be called whenever a * decorated person object is availabe. * The "best" language is determined by the following order of steps: * * 1.) If there is already a language set (this->language) take that one. * Thus the language settings can be functionaly overriden, e.g. in * the framework. * 2.) The language stored in the cookie of the user dominates over everything else * Thus, manually changing the language only means setting a cookie. * 3.) Try to take the language set by the subscriber, if the user is logged in * 4.) If the subscriber-language is NULL, take the language set by the NREN, * if the user is logged in * 5.) If the user is not logged in and no session variable is set, take the * first available language from the user's language accept-headers * 6.) If none of the languages in the user's accept header is available, * take the default language of the Confusa instance (usually but not necessarily English) * * @param $person Person-oject (Decorated) Person, from the subscriber or * NREN of which translator can deduce the * best language * @return void */ public function guessBestLanguage($person) { if ($this->languageOverridden) { return; } if (isset($_COOKIE['language'])) { $cookielang = Input::sanitizeLangCode($_COOKIE['language']); $this->language = $cookielang; return; } if ($person->isAuth()) { if (!is_null($person->getSubscriber())) { try { $query = "SELECT lang FROM subscribers WHERE name=?"; $res = MDB2Wrapper::execute($query, array('text'), array($person->getSubscriber()->getIdPName())); if (isset($res[0]['lang'])) { setCookie('language', $res[0]['lang']); $this->language = $res[0]['lang']; return; } $query = "SELECT lang FROM nrens WHERE name=?"; $res = MDB2Wrapper::execute($query, array('text'), array($person->getNREN())); if (isset($res[0]['lang'])) { setCookie('language', $res[0]['lang']); $this->language = $res[0]['lang']; return; } } catch (DBQueryException $dbqe) { Logger::log_event(LOG_WARNING, "Could not query subscriber/NREN default language. " . "Falling back to system language default! " . $dbqe->getMessage()); } catch (DBStatementException $dbse) { Logger::log_event(LOG_WARNING, "Could not query subscriber/NREN default language. " . "Falling back to system default! " . $dbse->getMessage()); } } } $sspdir = Config::get_config('simplesaml_path'); /* turn off warnings to keep the page header tidy */ $level = error_reporting(E_ERROR); /* poll the accept languages only, if we can load simplesamlphp * simplesamlphp *should* always be enabled (otherwise no authN :)), * But there can be configurations in bypass auth-mode without a working * simplesamlphp instance */ if (file_exists($sspdir . "/lib/_autoload.php")) { require_once $sspdir . '/lib/_autoload.php'; $accept_languages = SimpleSAML_Utilities::getAcceptLanguage(); $available_languages = Config::get_config('language.available'); if (empty($accept_languages)) { Logger::log_event(LOG_DEBUG, "Simplesamlphp instance seems to be not " . "configured, or not configured properly. Translator " . "will not use the browser's accept-header to determine " . "language settings."); } foreach ($accept_languages as $key => $value) { if (array_search($key, $available_languages) === FALSE) { continue; } else { $this->language = $key; return; } } } /* turn on warnings again */ error_reporting($level); $this->language = $this->defaultLanguage; return; }
/** * Delete the NREN logo for the given position within Confusa. This will * really delete the physical file containing the logo. * * @param $position string a position from * ConfusaConstants::$ALLOWED_IMG_POSITIONS * @param $nren string the name of the NREN, whose custom-logo should be * removed * @return void */ private function deleteLogo($position, $nren) { $basepath = Config::get_config('custom_logo') . $nren . "/custom_"; $basepath .= $position . "."; $result = FALSE; foreach (ConfusaConstants::$ALLOWED_IMG_SUFFIXES as $sfx) { $logoName = $basepath . $sfx; if (file_exists($logoName)) { $result = unlink($logoName); break; } } if ($result === FALSE) { Framework::error_output($this->translateTag('l10n_error_delete_logo', 'stylist')); Logger::log_event(LOG_INFO, "[nadm] Error when trying to delete " . "NREN logo {$logoName}, for NREN {$nren}."); } else { Framework::success_output($this->translateTag('l10n_success_delete_logo', 'stylist')); } }
public function revokeCert($key, $reason) { /* TODO: method stub * * At a first glance there seems to be no revoke function in php-openssl. * shell_exec('openssl ca -revoke...') would be possible but... eew... * Generously leaving this decision to Henrik ;-) * */ $cmd = "./../cert_handle/revoke_cert.sh {$key} " . ConfusaConstants::$OPENSSL_CRL_FILE; $res = exec($cmd, $output, $return); foreach ($output as $line) { $msg .= $line . "<BR />\n"; } if ((int) $return != 0) { Logger::log_event(LOG_NOTICE, "Problems revoking certificate for " . $this->getFullDN() . "({$key})"); throw new CGE_KeyRevokeException($msg); } Logger::log_event(LOG_NOTICE, "Revoked certificate {$key} for user " . $this->getFullDN()); if (!$this->deleteCertFromDB($key)) { Logger::log_event(LOG_NOTICE, "Could not delete certificate ({$key}) from database, revocation only partially completed."); } return true; }
function new_access_token($requestToken, $consumer) { $data = $this->getAuthorizedData($requestToken->key); if (isset($data[ConfusaConstants::$OAUTH_VALIDITY_ATTRIBUTE])) { $validity = $data[ConfusaConstants::$OAUTH_VALIDITY_ATTRIBUTE]; } else { $validity = ConfusaConstants::$DEFAULT_REAUTH_TIMEOUT; } /* need the validity in seconds */ $validity = $validity * 60; Logger::log_event(LOG_DEBUG, '[OAuthDataStore_Confusa] OAuth new_access_token(' . $requestToken . ',' . $consumer . ')'); $token = new OAuthToken(SimpleSAML_Utilities::generateID(), SimpleSAML_Utilities::generateID()); $this->store->set('access', $token->key, $consumer->key, $token, $validity); return $token; }
/** * MDB2Wrapper::create() create the connection (connect and initialize) * * This function will retrieve the database-credentials from the * config-file. From this, it will connect tot he database and store the * connection so the other functions can use it. * * At the moment, this is hard-coded to mysql (see the naming * below), but if we should ever change to another database, this is the * place to add the logic). * */ private static function create() { $uname = Config::get_config('mysql_username'); $passwd = Config::get_config('mysql_password'); $host = Config::get_config('mysql_host'); $db = Config::get_config('mysql_db'); $dsn = "mysql://{$uname}:{$passwd}@{$host}/{$db}"; $options = array('debug' => 2, 'result_buffering' => true); MDB2Wrapper::$conn = MDB2::factory($dsn, $options); if (PEAR::isError(MDB2Wrapper::$conn)) { Logger::log_event(LOG_WARNING, MDB2Wrapper::$conn->getMessage()); /* FIXME l10n, better error-reporting */ echo "Cannot connect to database: " . MDB2Wrapper::$conn->getMessage() . "<br>\n"; die(MDB2Wrapper::$conn->getMessage()); } }
/** * decoratePerson - get the supplied attributes and add to the correct * fields in person * * This function is a bit fragile. The reason for this, is that it needs * to 'bootstrap' the map for person-identifier (e.g. ePPN) * through various encodings. * * One way would be to add a specific mapping for all known NRENs, but * we'd rather add a generic approach and just try the known encodings * and see if we find something there. * * If, for some reason, a new NREN/IdP fails to correctly decorate the * person-object, the problem most likely starts here. * * @author Henrik Austad <*****@*****.**> * @author Thomas Zangerl <*****@*****.**> * * @throws CGE_CriticalAttributeException If an attribute without which Confusa * really can not work is not found * @throws MapNotFoundException If the NREN-map is not found * * @param array $attributes * @param String $idp * @throws MapNotFoundException */ protected function decoratePerson($attributes, $idp) { $cnPrefix = ""; $oPrefix = ""; if (Config::get_config('capi_test')) { $cnPrefix = ConfusaConstants::$CAPI_TEST_CN_PREFIX; $oPrefix = ConfusaConstants::$CAPI_TEST_O_PREFIX; } if (is_null($idp)) { throw new CGE_CriticalAttributeException("Need the URL of the IdP in order to create an NREN-object!"); } if (is_null($attributes)) { throw new CGE_CriticalAttributeException("Cannot find <b>any</b> attributes!"); } /* From the IdP, find the NREN-details */ $this->person->setNREN(new NREN($idp)); if (is_null($this->person->getNREN()) || !$this->person->getNREN()->isValid()) { $msg = "Could not map from the identity provider to the NREN. "; $msg .= "Probably the idp_map in the database is not configured for your idp ({$idp}) "; $msg .= "Please tell an administrator about that problem!"; throw new CGE_CriticalAttributeException($msg); } $nren_id = $this->person->getNREN()->getID(); Logger::logEvent(LOG_INFO, "Confusa_Auth", "decoratePerson(..., {$idp})", "Decorating person with map from NREN {$nren_id}."); $map = $this->person->getMap(); /* Normal mapping, this is what we want. */ if ($this->mapSanityCheck($map)) { /* Now that we have the NREN-map, reiterate getMap() in * case we can find the subscriber-map. */ $this->person->setSubscriber(new Subscriber($attributes[$map['epodn']][0], $this->person->getNREN())); $new_map = $this->person->getMap(); if ($this->mapSanityCheck($new_map)) { $map = $new_map; } $eppn = Input::sanitizeEPPN($attributes[$map['eppn']][0]); $this->person->setEPPN($eppn); if (!is_null($map['eppn'])) { $this->person->setEPPNKey($map['eppn']); } if (!is_null($map['cn'])) { if (array_key_exists($map['cn'], $attributes)) { $cn = mysql_real_escape_string($attributes[$map['cn']][0]); $this->person->setName($cnPrefix . $cn); } } /* end map has cn */ if (!is_null($map['mail'])) { if (array_key_exists($map['mail'], $attributes)) { $mail = Input::sanitizeEmail($attributes[$map['mail']]); $this->person->setEmail($mail); } } /* go through and add the relevant entitlement-parts. * TODO: cleanup this and move to person::setEntitlement() */ if (!is_null($map['entitlement'])) { if (array_key_exists($map['entitlement'], $attributes)) { $entitlements = $attributes[$map['entitlement']]; } } if (isset($entitlements)) { $namespace = Config::get_config('entitlement_namespace'); foreach ($entitlements as $key => $entitlementValue) { $pos = strpos($entitlementValue, $namespace); /* Note: we *must* check for both false *and* * type, as we want pos to be 0 */ if ($pos === false || (int) $pos != 0) { continue; } else { $val = explode(":", $entitlementValue); if (count($val) !== count(explode(":", $namespace)) + 1) { Framework::error_output("Error with namespace, too many objects in namespace (" . count($val) . ")"); continue; } /* only set the part *after* * entitlement-namespace */ $entitlement = Input::sanitizeEntitlement($val[count($val) - 1]); /* is the entitlement a valid entitlement? */ if ($entitlement == Config::get_config('entitlement_user') || $entitlement == Config::get_config('entitlement_admin')) { $this->person->setEntitlement($entitlement); } } } } } else { /* At this point we're on shaky ground as we have to * 'see if we can find anything' * * no map is set, can we find the ePPN in there? */ $eppnKey = $this->findEPPN($attributes); if (!is_null($eppnKey)) { $eppn = Input::sanitizeEPPN($eppnKey['value']); $this->person->setEPPN($eppn); $this->person->setEPPNKey($eppnKey['key']); } /* is ePPN registred as NREN admin (from bootstrap) */ if ($this->person->isNRENAdmin()) { if (is_array($map)) { Logger::log_event(LOG_WARNING, "Map for NREN {$nren_id} ({$idp}) corrupted. " . "Contains empty fields, consider dropping the map."); } $msg = "No NREN map found!"; if (Config::get_config('debug')) { $msg .= "Raw-dump of supplied attributes:<br />\n"; $msg .= "<br /><pre>\n"; foreach ($attributes as $key => $val) { $tabs = "\t"; if (strlen($key) < 8) { $tabs .= "\t\t"; } else { if (strlen($key) < 16) { $tabs .= "\t"; } } $msg .= htmlentities("{$key}{$tabs}{$val[0]}") . "\n"; } $msg .= "</pre><br />\n"; } throw new MapNotFoundException($msg); } } }
/** * isCSRFAttempt() - test to see if the current connection is an CSRF * * If a GET or POST is set, the client tries to send data to the * portal, and we must make sure that the user is not being fooled by a * malicious site. * * @param void * @return boolean status indicating if a detectable * @access private */ private function isCSRFAttempt() { if (!empty($_GET) || !empty($_POST)) { $facsrft = null; if (isset($_GET) && array_key_exists('anticsrf', $_GET)) { $facsrft = Input::sanitizeAntiCSRFToken($_GET['anticsrf']); } else { if (isset($_POST) && array_key_exists('anticsrf', $_POST)) { $facsrft = Input::sanitizeAntiCSRFToken($_POST['anticsrf']); } else { if (isset($_GET) && array_key_exists('return', $_GET)) { /* handle SSP redirect to idp_select */ $res = self::getCSRFRandToken(urldecode(urldecode($_GET['return']))); Logger::log_event(LOG_WARNING, "Handling SSP redirect - " . $res['csrf'] . "\n"); if (is_array($res)) { $facsrft = $res['full']; } } } } if (!self::validateACSRFT($facsrft)) { $msg = "Got a GET/POST request without the correct anticsrf tag."; $msg .= "Supplied: {$facsrft} (res: " . $res['full'] . ")"; if (array_key_exists('HTTP_REFERER', $_SERVER)) { $msg .= " Referer was " . $_SERVER['HTTP_REFERER']; } Logger::log_event(LOG_WARNING, "[Anti CSRF] {$msg}"); return true; } } /* no detectable CSRF attempt */ return false; }
/** * save() store updated results to the database, encrypting the password * before storage. */ public function save($validate = true) { if (!$this->changed) { return false; } if ($validate && !CAHandler::getCA($this->person)->verifyCredentials($this->login_name, $this->password)) { /* FIXME: l10n */ throw new ConfusaGenException("Invalid username/password, Comodo will not accept!"); } /* We create a new ivector every time we save the password */ $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB); $iv = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); $cryptpw = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, Config::get_config('capi_enc_pw'), base64_encode($this->password), MCRYPT_MODE_CFB, $iv)); if (MDB2Wrapper::testColumn('nrens', 'login_name') && MDB2Wrapper::testColumn('nrens', 'password') && MDB2Wrapper::testColumn('nrens', 'ivector') && MDB2Wrapper::testColumn('nrens', 'ap_name')) { $sql = " UPDATE nrens SET login_name=?, password=?, ivector=?, ap_name=?"; $sql .= " WHERE nren_id = ?"; Logger::log_event(LOG_DEBUG, "Using the new database-schema for account-details"); } else { if (isset($this->account_id)) { $sql = "UPDATE account_map SET login_name=?, password=?, ivector=?, ap_name=?"; $sql .= " WHERE nren_id = ?"; } else { $sql = "INSERT INTO account_map (login_name, password, ivector, ap_name, nren_id) "; $sql .= "VALUES(?, ?, ?, ?, ?)"; } } $params = array('text', 'text', 'text', 'text', 'integer'); $data = array($this->login_name, $cryptpw, base64_encode($iv), $this->ap_name, $this->nren->getID()); try { MDB2Wrapper::update($sql, $params, $data); Logger::log_event(LOG_NOTICE, "account-data updated for NREN " . $this->nren->getID()); } catch (DBQueryException $dqe) { $errorTag = PW::create(); Logger::log_event(LOG_ERR, "Could not update the login-account with ID " . $this->account_id . " for " . $this->nren->getID() . "(" . $this->login_name . ")"); return false; } catch (DBStatementException $dse) { $errorTag = PW::create(); Logger::log_event(LOG_ERR, "Could not update the login-account for NREN " . $this->nren->getID() . " to new value {$login_name} " . $dse->getMessage()); return false; } $this->changed = false; return true; }
/** * 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); }
private function deleteAdmin($admin, $level) { /* does the current user have the rights? */ try { $query = "SELECT a.* FROM admins a LEFT JOIN nrens n on n.nren_id = a.nren"; $query .= " WHERE (a.admin=? OR a.admin=?) AND n.name=?"; $res = MDB2Wrapper::execute($query, array('text', 'text', 'text'), array($admin, $this->person->getEPPN(), $this->person->getNREN())); switch (count($res)) { case 0: Framework::error_output("Did not find neither the admin to delete or the current admin in the database. Cannot continue."); return; case 1: if ($res[0]['admin'] != $admin) { Framework::error_output("Cannot find the admin to delete in the admins-table. Cannot continue."); return; } break; case 2: $id = 0; if ($res[1]['admin'] == $admin) { $id = 1; } $nrenID = $res[$id]['nren']; $subscriberID = $res[$id]['subscriber']; break; default: Framework::error_output("Too many hits in the database. Cannot decide where to go from here."); return; } } catch (DBStatementException $dbse) { $msg = "Cannot find id-values in the database due to server problems. Server said: " . htmlentities($dbse->getMessage()); Framework::error_output($msg); return; } catch (DBQueryException $dbqe) { $msg = "Cannot find id-values due to data inconsistency. Server said: " . htmlentities($dbqe->getMessage()); Framework::error_output($msg); return; } /* Find the admin-level of both admins and make sure that the * enforcer (the admin performing the deletion) has the rights * to do so. */ if ($res[0]['admin'] == $admin) { $targetLevel = (int) $res[0]['admin_level']; $enforcerLevel = (int) $res[1]['admin_level']; } else { $targetLevel = (int) $res[1]['admin_level']; $enforcerLevel = (int) $res[0]['admin_level']; } if ($enforcerLevel < $targetLevel) { Framework::error_output("Cannot delete admin with higher admin-level."); return; } if ($targetLevel == NREN_ADMIN) { $query = "DELETE FROM admins WHERE admin=? AND nren=?"; $params = array('text', 'text'); $data = array($admin, $nrenID); } else { $query = "DELETE FROM admins WHERE admin=? AND nren=? AND subscriber=?"; $params = array('text', 'text', 'text'); $data = array($admin, $nrenID, $subscriberID); } try { MDB2Wrapper::update($query, $params, $data); Logger::log_event(LOG_INFO, "Successfully deleted admin {$admin} with level {$targetLevel}"); } catch (DBStatementException $dbse) { Framework::error_output("Could not delete the admin because the statement was bad " . "Please contact an administrator. Server said " . htmlentities($dbse->getMessage())); Logger::log_event(LOG_NOTICE, __FILE__ . ":" . __LINE__ . ": Problem occured when trying to delete " . "admin {$admin} with level {$level}: " . $dbse->getMessage()); } catch (DBQueryException $dbqe) { Framework::error_output("Could not delete the admin because of problems with the " . "received data. Server said " . htmlentities($dbqe->getMessage())); Logger::log_event(LOG_INFO, __FILE__ . ":" . __LINE__ . ": Problem occured when tyring to delete " . "admin {$admin} with level {$level}: " . $dbqe->getMessage()); } Framework::success_output($this->translateTag('l10n_suc_deleteadm1', 'admin') . " " . htmlentities($admin)); }
/** *After the CSR has been uploaded to the Comodo certificate apply API, it * must be authorized by the user. * Call the authorize endpoint in the API and update the respective DB entry. */ private function capiAuthorizeCSR() { $authorize_endpoint = ConfusaConstants::$CAPI_AUTH_ENDPOINT; $postfields_auth = $this->bs_pf(); $postfields_auth["orderNumber"] = $this->order_number; $data = CurlWrapper::curlContact($authorize_endpoint, "post", $postfields_auth); Logger::log_event(LOG_DEBUG, "Authorizing CSR " . $this->order_number . " for signing."); /* the only formal restriction we have is if the API returns 0 for the query */ if (substr($data, 0, 1) == "0") { /* update the database-entry to reflect the autorization-state */ MDB2Wrapper::update("UPDATE order_store SET authorized='authorized' WHERE order_number=?", array('text'), array($this->order_number)); Logger::log_event(LOG_NOTICE, "Authorized certificate with order number " . $this->order_number . ". " . $this->owner_string); } else { Logger::log_event(LOG_WARNING, "Error authorizing CSR " . $this->order_number . " " . "Server said " . $error_parts[0] . " (" . $error_parts[1] . ")"); $msg = "Received an error when authorizing the CSR with orderNumber " . $this->order_number . $data . "\n"; $error_parts = explode("\n", $data, 2); $msg .= $this->capiErrorMessage($error_parts[0], $error_parts[1]); throw new CGE_ComodoAPIException($msg); } }
/** * parseRevList() work through a list of eppns and revoke certificates for those users * * @param list Array list of ePPNs for users to revoke * @param admin Person the admin owning the client-certiticate * * @return Array of a list of persons coupled to the number of revoked * certificates. */ static function parseRevList($list, $admin) { $revokedUsers = array(); $ca = CAHandler::getCA($admin); foreach ($list as $value) { /* Get eppn from value*/ $uid = $value['uid']; if (!isset($uid) || $uid == "") { echo "Need the UID. This is a REQUIRED attribute.<br />\n"; break; } /* Search after matches for cn and subscriber */ $list = $ca->getCertListForEPPN($uid, $admin->getSubscriber()->getOrgName()); Logger::log_event(LOG_DEBUG, "[Robot] Got list (" . count($list) . " in total) of certs for {$uid} to revoke."); $count = 0; if (count($list) > 0) { foreach ($list as $key => $value) { try { if ($ca->revokeCert($value['auth_key'], "privilegeWithdrawn")) { $count = $count + 1; } } catch (CGE_KeyRevokeException $kre) { echo htmlentities($kre->getMessage()) . "<br />\n"; } } /* end foreach() uid-list */ $revokedUsers[] = array('eppn' => $uid, 'count' => $count); } } /* end foreach() */ return $revokedUsers; }
function print_csr_details($person, $auth_key) { try { $csr = get_csr_from_db_raw($person->getX509ValidCN(), $auth_key); } catch (CSRNotFoundException $csrnfe) { $msg = "Error with auth-token (" . htmlentities($auth_key) . ") - not found. "; $msg .= "Please verify that you have entered the correct auth-url and try again."; $msg .= "If this problem persists, try to upload a new CSR and inspect the fields carefully"; Framework::error_output($msg); return false; } catch (ConfusaGenException $cge) { $msg = "Too menu returns received. This can indicate database inconsistency."; Framework::error_output($msg); Logger::log_event(LOG_ALERT, "Several identical CSRs (" . $auth_token . ") exists in the database for user " . stripslashes($person->getX509ValidCN())); return false; } $subj = openssl_csr_get_subject($csr['csr'], false); echo "<table class=\"small\">\n"; echo "<tr><td>AuthToken</td><td>" . $csr['auth_key'] . "</td></tr>\n"; /* Print subject-elements */ foreach ($subj as $key => $value) { echo "<tr><td>{$key}</td><td>{$value}</td></tr>\n"; } echo "<tr><td>Length:</td><td>" . csr_pubkey_length($csr['csr']) . " bits</td></tr>\n"; echo "<tr><td>Uploaded </td><td>" . $csr['uploaded_date'] . "</td></tr>\n"; echo "<tr><td>From IP: </td><td>" . Output::formatIP($csr['from_ip'], true) . "</td></tr>\n"; echo "<tr><td></td><td></td></tr>\n"; echo "<tr><td>[ <A HREF=\"" . $_SERVER['PHP_SELF'] . "?delete_csr={$auth_key}\">Delete from Database</A> ]</td>\n"; echo "<td>[ <A HREF=\"" . $_SERVER['PHP_SELF'] . "?sign_csr={$auth_key}\">Approve for signing</A> ]</td></tr>\n"; echo "</table>\n"; echo "<BR>\n"; return true; }
public static function getCA($person) { if (!isset(CAHandler::$ca)) { if (Config::get_config('cert_product') == PRD_PERSONAL) { /* if no NREN object is set, we can not know anything about the days */ if (!is_object($person->getNREN())) { $days = min(ConfusaConstants::$CAPI_VALID_PERSONAL); } else { $days = $person->getNREN()->getCertValidity(); } } else { if (Config::get_config('cert_product') == PRD_ESCIENCE) { $days = ConfusaConstants::$CAPI_VALID_ESCIENCE; } else { throw new ConfusaGenException("Confusa's configured product-mode is " . "illegal! Must be one of: PRD_ESCIENCE, " . "PRD_PERSONAL. Please contact an IT " . "administrator about that!"); } } switch ((int) Config::get_config('ca_mode')) { case CA_STANDALONE: require_once 'CA_Standalone.php'; CAHandler::$ca = new CA_Standalone($person, $days); break; case CA_COMODO: require_once 'CA_Comodo.php'; if (Config::get_config('capi_test') == TRUE) { $days = ConfusaConstants::$CAPI_TEST_VALID_DAYS; } CAHandler::$ca = new CA_Comodo($person, $days); break; default: /* This is going to produce a *lot* of errors, * but it should also catch the attention of * the operators. */ Logger::log_event(LOG_ALERT, "Tried to instantiate CA " . Config::get_config('ca_mode') . " but this is unknow. Config-file has errors. Check the ca_mode."); return null; } } return CAHandler::$ca; }
/** * Check if the person that called "revoke" on auth_key may revoke the respective * certificate, i.e. whether the certificate is issued to the person herself. * * @param $auth_key mixed The auth_key for which to check * @return boolean true, if revocation of the passed key is permitted */ private function checkRevocationPermissions($auth_key) { try { $info = $this->ca->getCertInformation($auth_key); if (is_null($info)) { Framework::error_output($this->translateTag('l10n_err_ordnum_notfound', 'download')); return false; } $cn = $this->person->getX509ValidCN(); $subscriber = $this->person->getSubscriber()->getOrgName(); if (stripslashes($info['cert_owner']) === stripslashes($cn) && $info['organization'] === $subscriber) { return true; } } catch (ConfusaGenException $cge) { Framework::error_output($this->translateTag('l10n_err_retrieval_fail', 'download') . ' ' . htmlentities($cge->getMessage())); Logger::log_event(LOG_INFO, "[norm] Revoking certificate " . "with key {$auth_key} failed, because permissions could not be " . "determined!"); } return false; }
/** * getCertFromDB() take the registred Certificate and find a match in * the DB * * Robot_Certificates are used for authenticating remote * clients. Therefore, we will *always* start the object with a * certificate. * * The authN-mechanism lies in whether or not the certicate is also * present in the database. * * @param Boolean $db_authoriative the values in the database is * authorative (overwrite local values if * present). * @return Boolean flag indicating if the certificate was found and * it matches the current @access private */ private function getCertFromDB($db_authorative = false) { $fp = $this->getFingerprint(); if (!$fp) { return false; } try { $query = "SELECT * FROM robot_certs WHERE fingerprint=?"; $res = MDB2Wrapper::execute($query, array('text'), array($fp)); if (count($res) == 1) { if ($res[0]['cert'] == $this->getPEMContent()) { if ($db_authorative) { $this->db_id = Input::sanitize($res[0]['id']); $this->owner = Input::sanitize($res[0]['uploaded_by']); $this->subscriber = Input::sanitize($res[0]['subscriber_id']); $this->lwsent = Input::sanitize($res[0]['last_warning_sent']); $this->uploaded_date = Input::sanitize($res[0]['uploaded_date']); } return true; } } return false; } catch (DBStatementException $dbse) { Logger::log_event(LOG_NOTICE, "Corrupted statement in query (" . __FILE__ . ":" . __LINE__ . " " . $dbse->getMessage()); } catch (DBQueryException $dbqe) { Logger::log_event(LOG_NOTICE, "Corrupted content in query (" . __FILE__ . ":" . __LINE__ . " " . $dbqe->getMessage()); } return false; }
/** * getFromQuery() run the query and create a new NREN * * @param String $query the query * @param Array $params * @param Array $data * @access private */ private function getFromQuery($query, $params, $data) { try { $res = MDB2Wrapper::execute($query, $params, $data); if (count($res) == 0) { return false; } /* loop through the resultset and return an NREN for * the first entry with idp_url. * * If we get multiple hits, there's no way we can adapt * to this, so we default to _the_first_valid_entry_ */ foreach ($res as $key => $r) { if (array_key_exists('idp_url', $r)) { return new NREN($r['idp_url']); } } } catch (DBStatementException $dbse) { Logger::log_event(LOG_ALERT, __FILE__ . ":" . __LINE__ . " problem with db-statement when finding NREN. " . $dbse->getMessage()); } catch (DBQueryException $dbqe) { Logger::log_event(LOG_ALERT, __FILE__ . ":" . __LINE__ . " Query-error when finding NREN. " . $dbqe->getMessage()); } return false; }
/** * getAdminStatus() get the admin-level from the database * * This function assumes isAuth() has been verified. * * @param void * @return Integer value indication the admin-level */ private function getAdminStatus() { if (isset($this->adminStatus)) { return $this->adminStatus; } $adminRes = NORMAL_USER; if (!$this->isAuth()) { $this->adminStatus = NORMAL_USER; return NORMAL_USER; } /* if the database is riddled with errors, do not run through the * test once more, just bail */ if ($this->adminDBError) { $this->adminStatus = NORMAL_USER; return NORMAL_USER; } require_once 'MDB2Wrapper.php'; $errorCode = PW::create(8); $query = "SELECT * FROM admins WHERE admin=:admin AND nren=:nren_id AND "; $query .= "((admin_level='2' AND (idp_url='' OR ISNULL(idp_url) OR idp_url=:idp_url)) OR "; $query .= "((admin_level='1' OR admin_level='0') AND subscriber=:subscriber_id))"; $params = array(); $params['admin'] = $this->eppn; $params['nren_id'] = $this->nren->getID(); $params['idp_url'] = $this->nren->getIdP(); $params['subscriber_id'] = -1; if (!is_null($this->getSubscriber())) { $params['subscriber_id'] = $this->getSubscriber()->getDBID(); } $res = MDB2Wrapper::execute($query, null, $params); $size = count($res); if ($size == 1) { $adminRes = $res[0]['admin_level']; if ($this->getName(false) != $res[0]['admin_name'] || $this->getEmail(false) != $res[0]['admin_email']) { try { MDB2Wrapper::update("UPDATE admins SET admin_name=?, admin_email=? WHERE admin_id=?", array('text', 'text', 'text'), array($this->getName(false), $this->getEmail(false), $res[0]['admin_id'])); } catch (DBStatementException $dbse) { $msg = "[{$errorCode}] Database not properly set. Missing fields in the admins-table."; Logger::log_event(LOG_ALERT, __FILE__ . ":" . __LINE__ . $msg); Framework::error_output($msg . "<br />Server said: " . $dbse->getMessage()); $this->adminDBError = true; } catch (DBQueryException $dbqe) { Logger::log_event(LOG_INFO, "[{$errorCode}] Could not update data for admin." . $dbqe->getMessage()); Framework::error_output("[{$errorCode}] Could not update data for admin. Problems with keys. Server said: " . $dbqe->getMessage()); $this->adminDBError = true; } catch (Exception $e) { $msg = "Could not update admin-data. Unknown error. Server said: " . $e->getMessage(); Framework::error_output($msg); Logger::Log_event(LOG_INFO, $msg); $this->adminDBError = true; } } } $this->adminStatus = $adminRes; return $adminRes; }
/** * printXMLRes() Print the returned array as a valid ConfusaRobot XML-file * * @param $resArray Array of data to print * @param $type String indicating the class of output */ function printXMLRes($resArray, $type = 'userList') { /* lets hope that the header has not yet been set so we can trigger * proper XML headers */ global $admin; $element_count = 0; $xml = new SimpleXMLElement("<ConfusaRobot></ConfusaRobot>"); $xml->addAttribute("date", date("Y-m-d H:i:s")); $xml->addAttribute("subscriber", $admin->getSubscriber()->getOrgName()); $xml->addAttribute("version", "1.0"); $element = null; switch (strtolower($type)) { case 'userlist': $element = $xml->addChild("userList"); break; case 'revokelist': $element = $xml->addChild("revokedCerts"); break; default: Logger::log_event(LOG_NOTICE, "Unknown XML-list-type ({$type}), aborting."); return; } if (isset($resArray) && is_array($resArray) && count($resArray) > 0) { foreach ($resArray as $value) { $le = $element->addChild('listElement'); $le->addAttribute('uid', htmlentities($value['uid'])); if (isset($value['count'])) { $le->addAttribute('count', $value['count']); } if (isset($value['fullDN'])) { $le->addAttribute('fullDN', $value['fullDN']); } $element_count += 1; } } $xml->addAttribute("elementCount", $element_count); Logger::log_event(LOG_DEBUG, "Returning list with {$element_count} entries."); header("content-type: text/xml"); echo $xml->asXML(); }
/** * Test whether the CSR in $content contains a public key that is * blacklisted (due to the Debian prime number generator flaw). * * If the key is blacklisted, this method will throw an exception * @param $content String containing CSR to be tested * @throws ConfusaGenException if key is blacklisted */ static function testBlacklist($content) { $shellContent = Input::sanitizeBase64(escapeshellarg($content)); $fp = popen("echo {$shellContent} | openssl-vulnkey -", "r"); if (!$fp) { Logger::log_event(LOG_ALERT, __CLASS__ . "::testBlacklist()", " Could not open process file-pointer in order to test for blacklisted CSR!"); /* if we cannot open openssl-vulnkey, we must assume that all uploaded * keys are blacklisted */ /* FIXME: add l10n */ throw new ConfusaGenException("Could not verify CSR against blacklist!"); } $res = fread($fp, 1024); fclose($fp); if (stripos($res, "not blacklisted", 0) === 0) { return; } else { if (stripos($res, "COMPROMISED", 0) === 0) { throw new ConfusaGenException("Key is blacklisted!"); } } Logger::log_event(LOG_DEBUG, __CLASS__ . "::testBlacklist()", " Unknown return ({$res}) value from shell"); }