/** * After loading the Security bolt in place, configure it. */ public function tightenSecurityBolt() { static $tightened = false; if ($tightened) { // This was already run once. return; } $state = State::instance(); $db = isset($this->db) ? $this->db : \Airship\get_database(); $this->airship_auth = Gears::get('Authentication', $state->keyring['auth.password_key'], $db); $this->airship_perms = Gears::get('Permissions', $db); }
$script = ROOT . '/CommandLine/continuum.php'; /** * @security Make sure this is never compromised: */ \shell_exec('php -dphar.readonly=0 ' . \escapeshellarg($script) . ' >/dev/null 2>&1 &'); \file_put_contents(ROOT . '/tmp/last_update_check.txt', time()); } /** * Let's load the latest gear for our autoloader */ define('CABIN_NAME', $active['name']); define('CABIN_DIR', ROOT . '/Cabin/' . $active['name']); // Turn all of this cabins' Landings and Blueprints into gears: require ROOT . '/cabin_gears.php'; $lens->addGlobal('ACTIVE_CABIN', \CABIN_NAME); $autoPilot = Gears::get('AutoPilot', $active, $lens, $dbPool); if ($autoPilot instanceof AutoPilot) { $autoPilot->setActiveCabin($active, $state->active_cabin); } // Load everything else: require ROOT . '/symlinks.php'; require ROOT . '/motifs.php'; require ROOT . '/security.php'; require ROOT . '/email.php'; $state->autoPilot = $autoPilot; /** * Final step: Let's turn on the autopilot */ if (!empty($state->universal['debug'])) { try { \error_reporting(E_ALL);
if (\file_exists(ROOT . '/config/Cabin/' . $active['name'] . '/twig_vars.json')) { $_settings = \Airship\loadJSON(ROOT . '/config/Cabin/' . $active['name'] . '/twig_vars.json'); $lens->addGlobal('SETTINGS', $_settings); } // Now let's load all the lens.php files, which are added by Gadgets: foreach ($lensLoad as $incl) { include $incl; } /** * Let's load up the databases */ $dbPool = []; require ROOT . '/database.php'; // Airship manifest: $manifest = \Airship\loadJSON(ROOT . '/config/manifest.json'); $state->manifest = $manifest; $htmlpurifier = new \HTMLPurifier(\HTMLPurifier_Config::createDefault()); $state->HTMLPurifier = $htmlpurifier; /** * Load up all of the keys used by the application: */ require_once ROOT . '/keys.php'; /** * Set up the logger */ require_once ROOT . '/config/logger.php'; /** * Automatic security updates */ $hail = Gears::get('Hail', new HTTPClient($state->universal['guzzle'])); $state->hail = $hail;
/** * Process account recovery * * @param array $post * @return bool */ protected function processRecoverAccount(array $post) : bool { $username = $post['forgot_passphrase_for']; $airBrake = Gears::get('AirBrake'); if (IDE_HACKS) { $airBrake = new AirBrake(); } $failFast = $airBrake->failFast($username, $_SERVER['REMOTE_ADDR'], $airBrake::ACTION_RECOVER); if ($failFast) { $this->lens('recover_account', ['form_message' => \__('You are doing that too fast. Please wait a few seconds and try again.')]); } elseif (!$airBrake->getFastExit()) { $delay = $airBrake->getDelay($username, $_SERVER['REMOTE_ADDR'], $airBrake::ACTION_RECOVER); if ($delay > 0) { \usleep($delay * 1000); } } try { $recoverInfo = $this->acct->getRecoveryInfo($username); } catch (UserNotFound $ex) { // Username not found. Is this a harvester? $airBrake->registerAccountRecoveryAttempt($username, $_SERVER['REMOTE_ADDR']); $this->log('Password reset attempt for nonexistent user.', LogLevel::NOTICE, ['username' => $username]); return false; } if (!$recoverInfo['allow_reset'] || empty($recoverInfo['email'])) { // Opted out or no email address? Act like the user doesn't exist. $airBrake->registerAccountRecoveryAttempt($username, $_SERVER['REMOTE_ADDR']); return false; } $token = $this->acct->createRecoveryToken((int) $recoverInfo['userid']); if (empty($token)) { return false; } $state = State::instance(); if (IDE_HACKS) { $state->mailer = new Sendmail(); $state->gpgMailer = new GPGMailer($state->mailer); } $message = (new Message())->addTo($recoverInfo['email'], $username)->setSubject('Password Reset')->setFrom($state->universal['email']['from'] ?? 'no-reply@' . $_SERVER['HTTP_HOST'])->setBody($this->recoveryMessage($token)); try { if (!empty($recoverInfo['gpg_public_key'])) { // This will be encrypted with the user's public key: $state->gpgMailer->send($message, $recoverInfo['gpg_public_key']); } else { // This will be sent as-is: $state->mailer->send($message); } } catch (InvalidArgumentException $ex) { return false; } return true; }
/** * Translation (lookup table based on a key) * * @param string $key * @param mixed ...$params * @return string */ function trk(string $key, ...$params) : string { static $gear = null; if ($gear === null) { $gear = Gears::get('Translation'); } if (!empty($params)) { \array_walk($params, '\\Airship\\LensFunctions\\get_purified'); } $state = State::instance(); return $gear->lookup($key, (string) ($state->lang ?? 'en-us'), ...$params); }
<?php declare (strict_types=1); use Airship\Engine\{Gears, Hail, Keyggdrasil, State}; /** * Keyggdrasil updater -- either throw this in a cronjob or let it get * triggered every time a page loads after enough time has elapsed * * @global State $state * @global Hail $hail */ \ignore_user_abort(true); \set_time_limit(0); require_once \dirname(__DIR__) . '/bootstrap.php'; if (\is_readable(ROOT . '/config/databases.json')) { /** * Initialize the channel updater service */ $channels = \Airship\loadJSON(ROOT . '/config/channels.json'); $database = \Airship\get_database(); $state->logger->info('Keyggdrasil started'); $keyUpdater = Gears::get('TreeUpdater', $hail, $database, $channels); if (IDE_HACKS) { $keyUpdater = new Keyggdrasil($hail, $database, $channels); } $keyUpdater->doUpdate(); $state->logger->info('Keyggdrasil concluded'); } else { // We can't update keys without a place to persist the changes }
/** * Is this user an administrator? * * @param int $userID * @return bool * @throws \Airship\Alerts\Database\DBException */ function is_admin(int $userID = 0) : bool { static $perm = null; if ($perm === null) { $perm = Gears::get('Permissions', \Airship\get_database()); if (!$perm instanceof Permissions) { return false; } } if ($userID < 1) { $userID = \Airship\LensFunctions\userid(); } return $perm->isSuperUser($userID); }
<?php declare (strict_types=1); use Airship\Engine\{Gears, Hail, State}; /** * @global State $state * @global Hail $hail */ // Always check for changes to channel keys before initiating update require_once __DIR__ . '/channel.php'; /** * Initialize the automatic updater service * @var \Airship\Engine\Continuum */ $autoUpdater = Gears::get('AutoUpdater', $hail); if (IDE_HACKS) { // Just for the sake of auto-completion: $autoUpdater = new \Airship\Engine\Continuum($hail); } $state->logger->info('Automatic update started'); try { $autoUpdater->doUpdateCheck(); } catch (\Throwable $ex) { $state->logger->critical('Tree update failed: ' . \get_class($ex), \Airship\throwableToArray($ex)); exit(255); } $state->logger->info('Automatic update concluded'); \Airship\clear_cache(); exit(0);