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));
    }
}
Beispiel #2
0
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;
    }
}
Beispiel #3
0
 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;
 }
Beispiel #4
0
 /** 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;
 }
Beispiel #5
0
 /**
  * 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);
 }
Beispiel #6
0
 /**
  * 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;
 }
Beispiel #7
0
 /**
  * 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;
 }
Beispiel #8
0
 /**
  * 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;
 }
Beispiel #9
0
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;
}
Beispiel #10
0
 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;
 }
Beispiel #11
0
 /**
  * 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;
 }
Beispiel #12
0
 /**
  * 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;
 }
Beispiel #13
0
 function testMultipleNrenMaps()
 {
     MDB2Wrapper::setMode(MDB2Wrapper::NRENAccountError);
     $account = NRENAccount::get(new Person());
     $this->assertFalse($account->read(), "NRENAccount received corrupted data but did not fail");
 }
Beispiel #14
0
 /**
  * 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... */
     }
 }
Beispiel #15
0
 /**
  * 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;
 }
Beispiel #16
0
 /**
  *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);
     }
 }
Beispiel #17
0
 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;
 }
Beispiel #18
0
 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);
     }
 }
Beispiel #19
0
 /**
  * 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);
 }
Beispiel #20
0
 /**
  * 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());
     }
 }
Beispiel #21
0
 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'));
 }
Beispiel #22
0
 /**
 * 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;
 }
Beispiel #23
0
 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));
 }
Beispiel #24
0
 /**
  * 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;
 }
Beispiel #25
0
/**
 * 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;
}
Beispiel #26
0
 public static function colExists($exists)
 {
     self::$colExists = $exists;
 }