function migrateAccountMap($nren_id, $username, $password, $ivector, $ap_name) { if (hasNewValues($nren_id)) { echo "It looks like NREN " . $nren_id . " " . "has been migrated already, please verify this and if not, " . "clean the fields in the database before venturing forth.\n"; } else { echo "Migrating NREN " . $nren_id . " to new schema.\n"; $u = "UPDATE nrens SET login_name=?, ap_name=?, password=?, ivector=? WHERE nren_id=?"; MDB2Wrapper::update($u, array('text', 'text', 'text', 'text', 'integer'), array($username, $ap_name, $password, $ivector, $nren_id)); } }
function getAccessTokenTimeout($idp_url) { $query = "SELECT reauth_timeout FROM nrens n, idp_map m " . "WHERE m.nren_id = n.nren_id AND m.idp_url = ?"; try { $res = MDB2Wrapper::execute($query, array('text'), array($idp_url)); } catch (ConfusaGenException $cge) { throw new CGE_AuthException("No NREN connected to IdP {$idp_url}!"); } if (count($res) == 1) { return $res[0]['reauth_timeout']; } else { return ConfusaConstants::$DEFAULT_REAUTH_TIMEOUT; } }
public function getCriticalErrors() { $query = "SELECT error_date, log_msg FROM critical_errors WHERE " . "is_resolved = false"; try { $res = MDB2Wrapper::execute($query, null, null); } catch (ConfusaGenException $e) { $this->tpl->assign('generalErrors', true); $this->tpl->assign('errorMessage', $e->getMessage()); return false; } foreach ($res as $row) { $this->logErrors[] = $row['error_date'] . " " . $row['log_msg']; } return true; }
/** 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; }
/** * getSubscriberByIO() find a subscriber in the database and decoraate a * Subscriber-object * * @param int $id the db-id for the subscriber * @param NREN $nren * @return Subscriber|null * @access public */ static function getSubscriberByID($id, $nren) { if (is_null($nren)) { return null; } if (is_null($id)) { return null; } try { $res = MDB2Wrapper::execute("SELECT name FROM subscribers WHERE subscriber_id=?", array('text'), array(Input::sanitizeText($id))); } catch (ConfusaGenException $cge) { echo $cge->getMessage(); return null; } if (count($res) != 1) { echo "wrong count"; return null; } return new Subscriber($res[0]['name'], $nren); }
/** * deleteFromDB() remove one (or all() CSR belonging to a person * * @param Person $person the owner of the CSR. * @param String|null $pubHash optional hash. If present, only * this will be removed * @return Boolean True if removed ok. * @access public */ static function deleteFromDB($person, $pubHash = null) { if (!isset($person)) { return false; } $remove = "DELETE FROM csr_cache WHERE common_name=:common_name"; $data['common_name'] = $person->getX509ValidCN(); if (isset($pubHash)) { $remove .= " AND auth_key=:auth_key"; $data['auth_key'] = $pubHash; } try { MDB2Wrapper::update($remove, null, $data); } catch (DBStatementException $dbse) { Logger::log_event(LOG_WARNING, __FILE__ . ":" . __LINE__ . " Coult not remove CSR from database. Server said: " . $dbse->getMessage()); return false; } catch (DBQueryException $dbqe) { Logger::log_event(LOG_WARNING, __FILE__ . ":" . __LINE__ . " Coult not remove CSR from database. Server said: " . $dbqe->getMessage()); return false; } return true; }
/** * 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; }
/** * deleteCertFromDB - delete a certificate from the database. */ public function deleteCertFromDB($key) { if (!isset($key) || $key == "") { return; } /* remove the certificate from the database */ try { MDB2Wrapper::update("DELETE FROM cert_cache WHERE auth_key=?", array('text'), array($key)); Logger::log_event(LOG_NOTICE, "Removed the certificate ({$key}) from the database "); } catch (DBStatementException $dbse) { $msg = __FILE__ . ":" . __LINE__ . " Error in query syntax."; Logger::log_event(LOG_NOTICE, $msg); $msg .= "<BR />Could not delete the certificate with hash: {$key}.<br />Try to do a manual deletion."; $msg .= "<BR />Server said: " . htmlentities($dbse->getMessage()); Framework::error_output($msg); /* Even though we fail, the certificate was * successfully revoked, thus the operation was * semi-successful. But, true should indicate that * *everything* went well */ return false; } catch (DBQueryException $dbqe) { $msg = __FILE__ . ":" . __LINE__ . " Query-error. Constraint violoation in query?"; Logger::log_event(LOG_NOTICE, $msg); $msg .= "<BR />Server said: " . htmlentities($dbqe->getMessage()); Framework::error_output($msg); return false; } return true; }
function delete_csr_from_db($person, $auth_key) { if (!$person->isAuth()) { return false; } /* Verify that the CSR is present */ try { $csr = get_csr_from_db_raw($person->getX509ValidCN(), $auth_key); } catch (CSRNotFoundException $csrnfe) { echo "No matching CSR found.<BR>\n"; $msg = "Could not delete CSR from ip " . $_SERVER['REMOTE_ADDR']; $msg .= " : " . stripslashes($person->getX509ValidCN()) . " Reason: not found"; Logger::log_event(LOG_NOTICE, $msg); return false; } catch (ConfusaGenException $cge) { $msg = "Error in deleting CSR (" . htmlentities($auth_key) . ")"; $msg .= "for user: "******" "; $msg .= "Too many hits!"; Framework::error_output($msg); Logger::log_event(LOG_ALERT, $msg); return false; } MDB2Wrapper::update("DELETE FROM csr_cache WHERE auth_key=? AND common_name=?", array('text', 'text'), array($auth_key, $person->getX509ValidCN())); $msg = "Dropping csr " . $auth_key . " "; $msg .= "for user " . stripslashes($person->getX509ValidCN()) . " (" . $_SERVER['REMOTE_ADDR'] . ") from csr_cache"; logger::log_event(LOG_NOTICE, $msg); return true; }
private function getRobotCert($serial) { $query = "SELECT * FROM robot_certs where subscriber_id=? AND serial=?"; $params = array('text', 'text'); $data = array($this->person->getSubscriber()->getDBID(), $serial); try { $res = MDB2Wrapper::execute($query, $params, $data); if (count($res) != 1) { return null; } return $res[0]; } catch (Exception $e) { Framework::error_output("Could not find cert. Server said: " . htmlentities($e->getMessage())); return null; } return null; }
/** * 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; }
/** * 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; }
function testMultipleNrenMaps() { MDB2Wrapper::setMode(MDB2Wrapper::NRENAccountError); $account = NRENAccount::get(new Person()); $this->assertFalse($account->read(), "NRENAccount received corrupted data but did not fail"); }
/** * An error considered critical for Confusa's execution has happened, try * to insert it into the DB, so error reporting tools and admins can handle * it. * * @param $log_level const integer The log level (EMERG, CRIT...) of the * log-event * @param $log_body string The log message itself */ static function insertCriticalErrorIntoDB($log_level, $log_body) { include_once 'MDB2Wrapper.php'; include_once 'confusa_gen.php'; $query = "INSERT INTO critical_errors(error_date, error_level, log_msg) "; $query .= "VALUES(current_timestamp,?,?)"; try { $res = @MDB2Wrapper::update($query, array('text', 'text'), array($log_level, $log_body)); } catch (ConfusaGenException $e) { /* log the exception... no, wait... */ } }
/** * Get the list of IdPs stored in the DB for this NREN. * * @param void * @return array|null an array with all IdP URLs or null if not found * @access public */ public function getIdPList() { $query = "SELECT m.idp_url FROM idp_map m " . "WHERE m.nren_id = ?"; try { $res = MDB2Wrapper::execute($query, array('text'), array($this->getID())); } catch (ConfusaGenException $cge) { Logger::log_event(LOG_NOTICE, __FILE__ . " " . __LINE__ . ": Could not " . "get the IdP list for NREN with ID " . $this->getID() . ". All IdP scoping will fail!"); } if (count($res) > 0) { $idpList = array(); foreach ($res as $row) { $idpList[] = $row['idp_url']; } } else { return null; } return $idpList; }
/** *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); } }
static function sanitizeText($input) { if (!isset($input) || empty($input)) { return null; } if (is_array($input)) { foreach ($input as $var => $val) { $output[$var] = Input::sanitizeText($val); } } $input = stripslashes($input); /* in text is feasible to want newlines, to format the appearance of the * text. Since it is undesired to directly insert newlines into the DB * convert them to <br /> tags. Direct HTML insertion has been dealt * with using htmlentities*/ /* allow <br /> tags with strip_tags, otherwise the <br />'s you insert * here will be stripped the next time the text is sanitized! */ $input = strtr(strip_tags($input, '<br>'), array("\n" => '<br />', "\r\n" => '<br />')); /* The following is a *HACK* * However, since we want to use the mysql_real_escape_string, * we have to make sure that the database has been * contacted. *sigh* * * Note that this *may* throw an exception from the database. */ if (!Input::$bootstrapped) { MDB2Wrapper::execute("SELECT current_timestamp()", null, null); Input::$bootstrapped = true; } /* Escape the string */ $output = mysql_real_escape_string($input); return $output; }
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); } }
/** * 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); }
/** * 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()); } }
private function updateNRENPrivacyNotice($nren, $new_text) { $query = "UPDATE nrens SET privacy_notice=? WHERE nren_id=?"; try { $res = MDB2Wrapper::update($query, array('text', 'text'), array($new_text, $nren->getID())); } catch (DBStatementException $dbse) { Framework::error_output("Problem updating the privacy-notice of your NREN! " . "Please contact an administrator to resolve this! " . "Server said " . htmlentities($dbse->getMessage())); return; } catch (DBQueryException $dbqe) { Framework::error_output("Problem updating the about text of your NREN, " . "probably related to the supplied data. " . "Please verify the data to be inserted! " . "Server said " . htmlentities($dbqe->getMessage())); return; } Logger::log_event(LOG_INFO, "Privacy-notice for NREN {$nren} was changed by " . $this->person->getEPPN() . " from " . $_SERVER['REMOTE_ADDR']); Framework::success_output($this->translateTag('l10n_suc_privnoticetext', 'stylist')); }
/** * 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; }
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)); }
/** * Return if this person may request a new certificate. This is dependant * on a few conditions: * - person is fully decorated * - 'confusa' entitlement is set * - subscriber of the person is in state 'subscribed' * * @return permission object containing * permissionGranted true/false based on whether the permission was granted * reasons array with reasons for granting/rejecting the permissions */ public function mayRequestCertificate() { $permission = new Permission(); $permission->setPermission(true); $translator = new Translator(); $translator->guessBestLanguage($this); if (empty($this->eppn)) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_malfeppn', 'reasons')); } if (empty($this->given_name)) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_nogivenname', 'reasons')); } if (empty($this->email)) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_noemailaddr', 'reasons')); } if (is_null($this->getNREN()->getCountry()) || $this->getNREN()->getCountry() == "") { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_nocountryname', 'reasons')); } $subscriberOrgName = $this->subscriber->getOrgName(); if (empty($subscriberOrgName)) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_malfsubsname', 'reasons')); } if (Config::get_config('capi_test') && Config::get_config('ca_mode') === CA_COMODO && $subscriberOrgName == ConfusaConstants::$CAPI_TEST_O_PREFIX) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_reas_malfsubsname', 'reasons')); } if (empty($this->entitlement) || !$this->testEntitlementAttribute(Config::get_config('entitlement_user'))) { $permission->setPermission(false); $permission->addReason(Config::get_config('entitlement_user') . " " . $translator->getTextForTag('l10n_reas_noentitlement', 'reasons')); } $query = "SELECT org_state FROM subscribers WHERE name=?"; /* Bubble up exceptions */ $res = MDB2Wrapper::execute($query, array('text'), array($this->subscriber->getIdPName())); if (count($res) == 0) { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_instunkn1', 'reasons') . " " . $this->subscriber->getIdPName() . " " . $translator->getTextForTag('l10n_instunkn2', 'reasons')); return $permission; } else { if (count($res) > 1) { throw new CGE_AuthException("More than one DB-entry with same subscriberOrgName " . $this->subscriber->getOrgName()); } } if ($res[0]['org_state'] !== 'subscribed') { $permission->setPermission(false); $permission->addReason($translator->getTextForTag('l10n_instnsubscr1', 'reasons') . " " . $this->subscriber->getIdPName() . " " . $translator->getTextForTag('l10n_instnsubscr2', 'reasons')); } return $permission; }
/** * createAdminPerson() Create a person-object based on the certificate * credentials passed via the client certificate. * * Ideally, this should be done via Confusa_Auth, however, since we do not have * a live Feide-session, but are basing the authetnication on an X.509 * certificate, the case is a corner, thus we do it here. * * @return Person|NULL the decorated person or NULL if the creation failed. */ function createAdminPerson() { global $log_error_code; /* * Try to find the certificate in the robot_certs-table. If we have a * match, we have a legit user and create a proxy-admin. * * If the query fails for some reason, we jumb out, returning null */ $fingerprint = openssl_x509_fingerprint($_SERVER['SSL_CLIENT_CERT'], true); if (is_null($fingerprint)) { return null; } try { $cert_res = MDB2Wrapper::execute("SELECT * FROM robot_certs WHERE fingerprint = ?", array('text'), array(trim($fingerprint))); } catch (DBStatementException $dbse) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) (line: " . __LINE__ . ")Error with syntax for robot_certs-query.(" . $dbse->getMessage() . ")"); return null; } catch (DBQueryException $dbqe) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Error with params (line (" . __LINE__ . ") in robot_certs-query.(" . $dbqe->getMessage() . ")"); return null; } switch (count($cert_res)) { case 0: Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}): Unauthenticated client connected. Refusing to establish connection. " . $_SERVER['SSL_CLIENT_I_DN']); echo "[{$log_error_code}] You are not authorized to use this API. This incident has been logged.\n"; return null; case 1: /* * We have to do the compare in a rather awkward way to ensure * that differences in spaces, newlines, tabs and whatnot are * removed. */ openssl_x509_export(openssl_x509_read($_SERVER['SSL_CLIENT_CERT']), $stored_admin_dump); openssl_x509_export(openssl_x509_read($cert_res[0]['cert']), $stored_client_dump); if ($stored_admin_dump != $stored_client_dump) { Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Got matching fingerprint ({$fingerprint}) " . "but actual certificates differ! Aborting"); echo "[{$code}] There were issues with your certificate. Cannot continue using this cert.\n"; echo "Please use another certificate for the time being.\n"; echo "This event has been logged.\n"; return null; } break; default: Logger::log_event(LOG_ALERT, "[RI] ({$log_error_code}) Several certs (" . count($cert_res) . ") in DB matching fingerprint ({$fingerprint}), cannot auth client."); return null; } /* * Get the details for the owner of the certificate, use this as a * basis for authenticating the person. * * It does not really matter which IdP-map we use, as long as we get one * that points to the correct NREN. This is probably not the 'correct' * way of using the idp_map, but atm, this is the only 'correct' way of * decorating the NREN-object. */ try { /* get admin */ $ares = MDB2Wrapper::execute("SELECT * FROM admins WHERE admin_id=?", array('text'), array($cert_res[0]['uploaded_by'])); if (count($ares) != 1) { /* no admin found. This should not be possible, but be * safe and test nevertheless */ return null; } /* get Subscriber */ $sres = MDB2Wrapper::execute("SELECT * FROM subscribers WHERE subscriber_id=?", array('text'), array($cert_res[0]['subscriber_id'])); if (count($sres) != 1) { /* No subscriber found */ return null; } /* get NREN */ $nres = MDB2Wrapper::execute("SELECT n.*,im.idp_url FROM nrens n LEFT JOIN idp_map im ON im.nren_id = n.nren_id WHERE n.nren_id=?", array('text'), array($sres[0]['nren_id'])); if (count($nres) < 1) { /* No nrens found at all, which means that the * subscriber is bogus. Since this is a foreign-key * constraint, we've run into a corrupt db. Let's hope * this'll never happen :-) */ Logger::log_event(LOG_EMERG, "Found subscriber (" . $sres[0]['subscriber_id'] . ":" . $sres[0]['name'] . ") without a corresponding NREN (" . $sres[0]['nren_id'] . "), you have a corrupt database"); } } catch (DBStatementException $dbse) { $msg = "[{$log_error_code}] Problem executing query. Is the database-schema outdated?. "; Logger::log_event(LOG_INFO, $msg . " Server said: " . $dbse->getMessage()); echo $msg . "<br />\nServer said: " . htmlentities($dbse->getMessage()) . "<br />\n"; return null; } catch (DBQueryException $dbqe) { /* FIXME */ $msg = "Could not find owner-details for certificate, probably issues with supplied data. "; $msg .= "Admin_id: " . htmlentities($cert_res[0]['uploaded_by']); Logger::log_event(LOG_INFO, $msg . " Server said: " . $dbqe->getMessage()); echo $msg . "<br />\nServer said: " . htmlentities($dbqe->getMessage()) . "<br />\n"; return null; } /* * Decorate person. */ $person = new Person(); if (isset($ares[0]['admin_name']) && $ares[0]['admin_name'] != "") { $person->setName($ares[0]['admin_name']); } else { $person->setName($ares[0]['admin']); } try { $person->setEPPN($ares[0]['admin']); } catch (CGE_CriticalAttributeException $cae) { echo "[{$log_error_code}] Problems with setting the unique identifier for robot-admin.<br />\n"; echo "Check the data in admins (admin_id: " . htmlentities($cert_res[0]['uploaded_by']) . ")<br />\n"; Logger::log_event(LOG_NOTICE, "[RI] ({$log_error_code}) Internal error? Suddenly provided admin-uid is not available."); return null; } $person->setAuth(true); $person->setNREN(new NREN($nres[0]['idp_url'])); $person->setSubscriber(new Subscriber($sres[0]['name'], $person->getNREN())); $person->setName($ares[0]['admin_name']); $person->setEmail($ares[0]['admin_email']); /* Robot authenticated, we can return the person and live happily ever * after */ Logger::log_event(LOG_NOTICE, "[RI]: Authenticated robot-client via cert {$fingerprint} belonging to " . $person->getEPPN()); return $person; }
public static function colExists($exists) { self::$colExists = $exists; }