Permalink
Browse files

Added Keychain package, tests, documentation and command-line management

utility.
  • Loading branch information...
1 parent 3d84f34 commit 56895f7a5a89ab12ea86f13eb7de3e87047140a9 @eddieajau eddieajau committed Sep 14, 2012
View
@@ -0,0 +1,381 @@
+#!/usr/bin/env php
+<?php
+/**
+ * @package Joomla.Platform
+ *
+ * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later; see LICENSE
+ */
+
+define('_JEXEC', 1);
+define('JPATH_BASE', dirname(__FILE__));
+
+// Load the Joomla! Platform
+require_once realpath('../libraries/import.php');
+
+/**
+ * Keychain Manager
+ *
+ * @package Joomla.Platform
+ * @since 12.2
+ */
+class KeychainManager extends JApplicationCli
+{
+ /**
+ * @var boolean A flag if the keychain has been updated to trigger saving the keychain
+ * @since 12.2
+ */
+ protected $updated = false;
+
+ /**
+ * @var JKeychain The keychain object being manipulated.
+ * @since 12.2
+ */
+ protected $keychain = null;
+
+ /**
+ * Execute the application
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ public function execute( )
+ {
+ if (!count($this->input->args))
+ {
+ // Check if they passed --help in otherwise display short usage summary
+ if ($this->input->get('help', false) === false)
+ {
+ $this->out("usage: {$this->input->executable} [options] [command] [<args>]");
+ exit(1);
+ }
+ else
+ {
+ $this->displayHelp();
+ exit(0);
+ }
+ }
+
+ // For all tasks but help and init we use the keychain
+ if (!in_array($this->input->args[0], array('help', 'init')))
+ {
+ $this->loadKeychain();
+ }
+
+ switch ($this->input->args[0])
+ {
+ case 'init':
+ $this->initPassphraseFile();
+ break;
+ case 'list':
+ $this->listEntries();
+ break;
+ case 'create':
+ $this->create();
+ break;
+ case 'change':
+ $this->change();
+ case 'delete':
+ $this->delete();
+ break;
+ case 'read':
+ $this->read();
+ break;
+ case 'help':
+ $this->displayHelp();
+ break;
+ default:
+ $this->out('Invalid command.');
+ break;
+ }
+
+ if ($this->updated)
+ {
+ $this->saveKeychain();
+ }
+ exit(0);
+ }
+
+ /**
+ * Load the keychain from a file.
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function loadKeychain()
+ {
+ $keychain = $this->input->get('keychain', '', 'raw');
+ $publicKeyFile = $this->input->get('public-key', '', 'raw');
+ $passphraseFile = $this->input->get('passphrase', '', 'raw');
+
+ $this->keychain = new JKeychain;
+
+ if (file_exists($keychain))
+ {
+ if (file_exists($publicKeyFile))
+ {
+ $this->keychain->loadKeychain($keychain, $passphraseFile, $publicKeyFile);
+ }
+ else
+ {
+ $this->out('Public key not specified or missing!');
+ exit(1);
+ }
+ }
+ }
+
+ /**
+ * Save this keychain to a file.
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function saveKeychain()
+ {
+ $keychain = $this->input->get('keychain', '', 'raw');
+ $publicKeyFile = $this->input->get('public-key', '', 'raw');
+ $passphraseFile = $this->input->get('passphrase', '', 'raw');
+
+ if (!file_exists($publicKeyFile))
+ {
+ $this->out("Public key file specified doesn't exist: $publicKeyFile");
+ exit(1);
+ }
+
+ $this->keychain->saveKeychain($keychain, $passphraseFile, $publicKeyFile);
+ }
+
+ /**
+ * Initialise a new passphrase file.
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function initPassphraseFile()
+ {
+ $keychain = new JKeychain;
+
+ $passphraseFile = $this->input->get('passphrase', '', 'raw');
+ $privateKeyFile = $this->input->get('private-key', '', 'raw');
+
+ if (!strlen($passphraseFile))
+ {
+ $this->out('A passphrase file must be specified with --passphrase');
+ exit(1);
+ }
+
+ if (!file_exists($privateKeyFile))
+ {
+ $this->out("protected key file specified doesn't exist: $privateKeyFile");
+ exit(1);
+ }
+
+ $this->out('Please enter the new passphrase:');
+ $passphrase = $this->in();
+
+ $this->out('Please enter the passphrase for the protected key:');
+ $privateKeyPassphrase = $this->in();
+
+ $keychain->createPassphraseFile($passphrase, $passphraseFile, $privateKeyFile, $privateKeyPassphrase);
+ }
+
+ /**
+ * Create a new entry
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function create()
+ {
+ if (count($this->input->args) != 3)
+ {
+ $this->out("usage: {$this->input->executable} [options] create entry_name entry_value");
+ exit(1);
+ }
+
+ if ($this->keychain->exists($this->input->args[1]))
+ {
+ $this->out('error: entry already exists. To change this entry, use "change"');
+ exit(1);
+ }
+ $this->change();
+ }
+
+ /**
+ * Change an existing entry to a new value or create an entry if missing.
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function change()
+ {
+ if (count($this->input->args) != 3)
+ {
+ $this->out("usage: {$this->input->executable} [options] change entry_name entry_value");
+ exit(1);
+ }
+ $this->updated = true;
+ $this->keychain->setValue($this->input->args[1], $this->input->args[2]);
+ }
+
+ /**
+ * Read an entry from the keychain
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function read()
+ {
+ if (count($this->input->args) != 2)
+ {
+ $this->out("usage: {$this->input->executable} [options] read entry_name");
+ exit(1);
+ }
+
+ $key = $this->input->args[1];
+ $this->out($key . ': ' . $this->dumpVar($this->keychain->get($key)));
+ }
+
+ /**
+ * Get the string from var_dump
+ *
+ * @param mixed $var The variable you want to have dumped.
+ *
+ * @return string The result of var_dump
+ *
+ * @since 12.2
+ */
+ private function dumpVar($var)
+ {
+ ob_start();
+ var_dump($var);
+ $result = trim(ob_get_contents());
+ ob_end_clean();
+ return $result;
+ }
+
+ /**
+ * Delete an entry from the keychain
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function delete()
+ {
+ if (count($this->input->args) != 2)
+ {
+ $this->out("usage: {$this->input->executable} [options] delete entry_name");
+ exit(1);
+ }
+
+ $this->updated = true;
+ $this->keychain->deleteValue($this->input->args[1], null);
+ }
+
+ /**
+ * List entries in the keychain
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function listEntries()
+ {
+ foreach ($this->keychain->toArray() as $key => $value)
+ {
+ $line = $key;
+ if ($this->input->get('print-values'))
+ {
+ $line .= ': ' . $this->dumpVar($value);
+ }
+ $this->out($line);
+ }
+ }
+
+ /**
+ * Display the help information
+ *
+ * @return void
+ *
+ * @since 12.2
+ */
+ protected function displayHelp()
+ {
+/*
+COMMANDS
+
+ - list
+ - create entry_name entry_value
+ - change entry_name entry_value
+ - delete entry_name
+ - read entry_name
+*/
+
+ $help = <<<HELP
+Keychain Management Utility
+
+usage: {$this->input->executable} [--keychain=/path/to/keychain]
+ [--passphrase=/path/to/passphrase.dat] [--public-key=/path/to/public.pem]
+ [command] [<args>]
+
+OPTIONS
+
+ --keychain=/path/to/keychain
+ Path to a keychain file to manipulate.
+
+ --passphrase=/path/to/passphrase.dat
+ Path to a passphrase file containing the encryption/decryption key.
+
+ --public-key=/path/to/public.pem
+ Path to a public key file to decrypt the passphrase file.
+
+
+COMMANDS
+
+ list:
+ Usage: list [--print-values]
+ Lists all entries in the keychain. Optionally pass --print-values to print the values as well.
+
+ create:
+ Usage: create entry_name entry_value
+ Creates a new entry in the keychain called "entry_name" with the plaintext value "entry_value".
+ NOTE: This is an alias for change.
+
+ change:
+ Usage: change entry_name entry_value
+ Updates the keychain entry called "entry_name" with the value "entry_value".
+
+ delete:
+ Usage: delete entry_name
+ Removes an entry called "entry_name" from the keychain.
+
+ read:
+ Usage: read entry_name
+ Outputs the plaintext value of "entry_name" from the keychain.
+
+ init:
+ Usage: init
+ Creates a new passphrase file and prompts for a new passphrase.
+
+HELP;
+ $this->out($help);
+ }
+}
+
+try
+{
+ JApplicationCli::getInstance('KeychainManager')->execute();
+}
+catch (Exception $e)
+{
+ echo $e->getMessage() . "\n";
+ exit(1);
+}
Oops, something went wrong.

0 comments on commit 56895f7

Please sign in to comment.