Version 1.6

pull/50/head
sud0nick 2018-12-28 23:45:33 -05:00
parent a55c302c83
commit 4455ee1337
10 changed files with 456 additions and 16 deletions

View File

@ -69,12 +69,21 @@ class Papers extends Module
case 'buildCert':
$this->buildCert($this->request->parameters);
break;
case 'encryptKey':
$this->respond($this->encryptKey($this->request->keyName, $this->request->keyType, $this->request->keyAlgo, $this->request->keyPass));
break;
case 'decryptKey':
$this->respond($this->decryptKey($this->request->keyName, $this->request->keyType, $this->request->keyPass));
break;
case 'genSSHKeys':
$this->genSSHKeys($this->request->parameters);
break;
case 'loadCertificates':
$this->loadCertificates();
break;
case 'loadCertProps':
$this->loadCertificateProperties($this->request->certName);
break;
case 'downloadKeys':
$this->downloadKeys($this->request->parameters->name, $this->request->parameters->type);
break;
@ -288,6 +297,40 @@ class Papers extends Module
$this->respond(true, "Keys created successfully!");
}
private function encryptKey($keyName, $keyType, $algo, $pass) {
$retData = array();
$argString = "encryptKeys.sh --encrypt -k " . $keyName . " -a " . $algo . " -p " . $pass;
if ($keyType == "SSH") {
$argString .= " --ssh";
}
exec(__SCRIPTS__ . $argString, $retData);
$res = implode("\n", $retData);
if ($res != "Complete") {
$this->logError("Key Encryption Error", "The following error occurred:\n\n" . $res);
return false;
}
return true;
}
private function decryptKey($keyName, $keyType, $pass) {
$retData = array();
$argString = "decryptKeys.sh -k " . $keyName . " -p " . $pass;
if ($keyType == "SSH") {
$argString .= " --ssh";
}
exec(__SCRIPTS__ . $argString, $retData);
$res = implode("\n", $retData);
if ($res != "Complete") {
$this->logError("Key Decryption Error", "The following error occurred:\n\n" . $res);
return false;
}
return true;
}
/*
Generates an OpenSSL config file based on the passed in requirements ($req)
and returns the path to the file.
@ -327,6 +370,29 @@ class Papers extends Module
$this->respond(true,null,$certs);
}
private function loadCertificateProperties($cert) {
$retData = array();
$res = [];
exec(__SCRIPTS__ . "getCertInfo.sh -k " . $cert, $retData);
if (count($retData) == 0) {
$this->respond(false);
return false;
}
// Create a mapping of the values that can be passed back to the front end
foreach ($retData as $line) {
$parts = explode("=", $line, 2);
$key = $parts[0];
$val = $parts[1];
$res[$key] = $val;
}
// Return success and the contents of the tmp file
$this->respond(true, null, $res);
return true;
}
private function getKeys($dir) {
$keyType = ($dir == __SSLSTORE__) ? "TLS/SSL" : "SSH";
$keys = scandir($dir);
@ -603,7 +669,17 @@ class Papers extends Module
fclose($fh);
}
private function retrieveLog($logname, $type) {
$dir = ($type == "error") ? __LOGS__ : ($type == "help") ? __HELPFILES__ : __CHANGELOGS__;
switch($type) {
case "error":
$dir = __LOGS__;
break;
case "help":
$dir = __HELPFILES__;
break;
default:
$dir = __CHANGELOGS__;
break;
}
$data = file_get_contents($dir . $logname);
if (!$data) {
$this->respond(false);

View File

@ -0,0 +1,5 @@
December 28, 2018<br /></br >
- Added feature to encrypt/decrypt existing private keys<br />
- Added feature to view certificate properties in the web console<br />
- Fixed a bug that prevented error logs from loading in the web console<br />
- Removed null alert when enabling SSH keys<br />

View File

@ -1,5 +1,5 @@
<strong>Encrypted</strong><br />
Displays if the private key (.pem) is encrypted. Does not include encryption on .pfx containers.
Displays if the private key is encrypted. Does not include encryption on .pfx containers.
<br /><br />
<strong>PineSSL / PineSSH</strong><br />
@ -13,6 +13,15 @@ For SSH key pairs this button has two modes (the state does not change for TLS/S
</ul>
<br />
<strong>Encrypt / Decrypt</strong><br />
If this icon is highlighted green the private key is encrypted. Click the icon and enter the key's password to decrypt it.<br />
If the icon is not highlighted it is not encrypted. Click the icon, select an algorithm, and enter a password to encrypt it.
<br /><br />
<strong>View Certificate</strong><br />
View the human readable properties of the certificate.
<br /><br />
<strong>Download</strong><br />
Packages the keys in the selected row into a zip archive and downloads it.
<br /><br />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,72 @@
#!/bin/sh
# Author: sud0nick
# Date: Dec 2018
# Location of SSL keys
ssl_store="/pineapple/modules/Papers/includes/ssl/";
ssh_store="/pineapple/modules/Papers/includes/ssh/";
help() {
echo "Decryption script for OpenSSL keys";
echo "Usage: ./decryptKeys.sh <opts>";
echo "Use './decryptKeys.sh --examples' to see example commands";
echo '';
echo 'NOTE:';
echo "Current SSL store is at $ssl_store";
echo '';
echo 'Parameters:';
echo '';
echo -e '\t-k:\tName of key to be decrypted';
echo -e '\t-p:\tPassword to use to unlock the key';
echo -e '\t--ssh:\tThe key to encrypt is in the SSH store';
echo -e '\t--help:\tDisplays this help info';
echo '';
}
examples() {
echo '';
echo 'Examples:';
echo 'Decrypt private key:';
echo './decryptKeys.sh -k keyName -p password';
echo '';
echo '';
}
if [ "$#" -lt 1 ]; then
help;
exit;
fi
while [ "$#" -gt 0 ]
do
if [[ "$1" == "--examples" ]]; then
examples;
exit;
fi
if [[ "$1" == "--ssh" ]]; then
ssl_store=$ssh_store;
fi
if [[ "$1" == "--help" ]]; then
help;
exit;
fi
if [[ "$1" == "-k" ]]; then
KEY="$2";
fi
if [[ "$1" == "-p" ]]; then
PASS="$2";
fi
shift
done;
# Generate a password on the private key
openssl rsa -in $ssl_store$KEY.key -out $ssl_store$KEY.key -passin pass:"$PASS" 2>/dev/null;
if [[ $? != 0 ]]; then
echo "Bad Password";
exit;
fi
echo "Complete"

View File

@ -5,6 +5,7 @@
# Location of SSL keys
ssl_store="/pineapple/modules/Papers/includes/ssl/";
ssh_store="/pineapple/modules/Papers/includes/ssh/";
help() {
echo "Encryption/Export script for OpenSSL certificates";
@ -21,6 +22,7 @@ help() {
echo 'Encryption Options:';
echo '';
echo -e '\t--encrypt:\tMust be supplied to encrypt keys';
echo -e '\t--ssh:\tThe key to encrypt is in the SSH store';
echo -e '\t-a:\t\tAlgorithm to use for key encryption (aes256, 3des, camellia256, etc)';
echo -e '\t-p:\t\tPassword to use for encryption';
echo '';
@ -66,8 +68,11 @@ fi
if [[ "$1" == "--encrypt" ]]; then
ENCRYPT_KEYS=true;
fi
if [[ "$1" == "--ssh" ]]; then
ssl_store=$ssh_store;
fi
if [[ "$1" == "-a" ]]; then
ALGO="$2";
ALGO="$2";
fi
if [[ "$1" == "-k" ]]; then
KEY="$2";

View File

@ -0,0 +1,51 @@
#!/bin/sh
# Author: sud0nick
# Date: Dec 2018
# Location of SSL keys
ssl_store="/pineapple/modules/Papers/includes/ssl/";
help() {
echo "Get certificate properties via OpenSSL";
echo "Usage: ./getCertInfo.sh <opts>";
echo '';
echo 'NOTE:';
echo "Current SSL store is at $ssl_store";
echo '';
echo 'Parameters:';
echo '';
echo -e '\t-k:\tKey from which to retrieve properties';
echo '';
}
if [ "$#" -lt 1 ]; then
help;
exit;
fi
while [ "$#" -gt 0 ]
do
if [[ "$1" == "-k" ]]; then
KEY="$ssl_store$2.cer";
fi
shift
done;
ISSUER=$(openssl x509 -in $KEY -noout -issuer | sed 's/^[^=]*=//g');
FINGERPRINT=$(openssl x509 -in $KEY -noout -fingerprint | sed 's/^[^=]*=//g');
SUBJECT=$(openssl x509 -in $KEY -noout -subject | sed 's/^[^=]*=//g');
START_DATE=$(openssl x509 -in $KEY -noout -startdate | sed 's/^[^=]*=//g');
END_DATE=$(openssl x509 -in $KEY -noout -enddate | sed 's/^[^=]*=//g');
SERIAL=$(openssl x509 -in $KEY -noout -serial | sed 's/^[^=]*=//g');
ALT_NAMES=$(openssl x509 -in $KEY -noout -text | grep DNS | sed 's/^[^:]*://g');
echo "issuer=$ISSUER";
echo "fingerprint=$FINGERPRINT";
echo "subject=$SUBJECT";
echo "start=$START_DATE";
echo "end=$END_DATE";
echo "serial=$SERIAL";
echo "dns=$ALT_NAMES";

View File

@ -34,6 +34,13 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct
$scope.dependsProcessing = false;
$scope.selectedFiles = [];
$scope.uploading = false;
$scope.selectedKey = '';
$scope.certDecryptPassword = '';
$scope.encrypting = false;
$scope.decrypting = false;
$scope.viewCert = '';
$scope.selectedCert = '';
$scope.loadingCert = false;
$scope.checkDepends = (function(){
$api.request({
@ -159,6 +166,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct
action: 'buildCert',
parameters: params
},function(response) {
$scope.certKeyName = '';
$scope.getLogs();
$scope.showBuildThrobber = false;
$scope.loadCertificates();
@ -166,6 +174,94 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct
});
}
});
$scope.loadCertProps = (function(cert){
$scope.loadingCert = true;
$scope.viewCert = '';
$scope.selectedCert = cert;
$api.request({
module: 'Papers',
action: 'loadCertProps',
certName: cert
},function(response){
$scope.loadingCert = false;
if (response === false) {
$('#viewCert').modal('hide');
return;
}
$scope.viewCert = response.data;
});
});
$scope.selectKey = (function(key, type) {
$scope.certEncryptAlgo = "aes256";
$scope.certEncryptPassword = '';
$scope.selectedKey = key;
$scope.selectedKeyType = type;
});
$scope.encryptKey = (function(name, type, algo, pass) {
if (pass.length == 0) {
return;
}
$scope.encrypting = true;
$api.request({
module: 'Papers',
action: 'encryptKey',
keyName: name,
keyType: type,
keyAlgo: algo,
keyPass: pass
},function(response){
$scope.encrypting = false;
$scope.certEncryptPassword = '';
if (response.success === false) {
alert("Failed to encrypt key. Check the logs for more info.");
$scope.getLogs();
return;
}
$scope.loadCertificates();
$('#encryptModal').modal('hide');
});
});
$scope.decryptKey = (function(name, type, pass) {
if (pass.length == 0) {
return;
}
$scope.decrypting = true;
$api.request({
module: 'Papers',
action: 'decryptKey',
keyName: name,
keyType: type,
keyPass: pass
},function(response){
$scope.decrypting = false;
$scope.certDecryptPassword = '';
if (response.success === false) {
alert("Failed to decrypt key. Ensure you have entered the password correctly.");
$scope.getLogs();
return;
}
$scope.loadCertificates();
$('#decryptModal').modal('hide');
});
});
$scope.clearForm = (function() {
$scope.certKeyType = "tls_ssl";
@ -263,7 +359,6 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct
}
} else {
// Alert error
alert(response.message);
}
$scope.loadCertificates();
});
@ -350,6 +445,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct
parameters: log,
type: type
},function(response){
console.log(response);
if (response.success === true) {
$scope.currentLogData = $sce.trustAsHtml(response.data);
}

View File

@ -113,6 +113,14 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
<td>
<button type="button" class="btn btn-sm papers_hoverDanger" ng-show="data.Authorized==true" ng-click="revokeSSHKey(data.Name);"><img src="/modules/Papers/includes/icons/glyphicons-205-unlock.png"/></button>
<button type="button" class="btn btn-sm papers_hoverSuccess" ng-disabled="data.Encrypted == 'Yes' && data.KeyType == 'TLS/SSL'" ng-show="data.Authorized==false" ng-click="securePineapple(data.Name, data.KeyType);"><img src="/modules/Papers/includes/icons/glyphicons-204-lock.png"/></button>
<!-- Encrypt button -->
<button type="button" class="btn btn-sm papers_hoverSuccess" data-toggle="modal" data-target="#encryptModal" ng-show="data.Encrypted == 'No'" ng-click="selectKey(data.Name, data.KeyType);"><img src="/modules/Papers/includes/icons/glyphicons-45-keys.png"/></button>
<!-- Decrypt button -->
<button type="button" class="btn btn-sm btn-success papers_hoverDanger" data-toggle="modal" data-target="#decryptModal" ng-show="data.Encrypted == 'Yes'" ng-click="selectKey(data.Name, data.KeyType);"><img src="/modules/Papers/includes/icons/glyphicons-45-keys.png"/></button>
<button type="button" class="btn btn-sm papers_hoverInfo" ng-disabled="data.KeyType == 'SSH'" data-toggle="modal" data-target="#viewCert" ng-click="loadCertProps(data.Name);"><img src="/modules/Papers/includes/icons/glyphicons-28-search.png"/></button>
<button type="button" class="btn btn-sm papers_hoverInfo" ng-click="downloadKeys(data.Name, data.KeyType);"><img src="/modules/Papers/includes/icons/glyphicons-201-download.png"/></button>
<button type="button" class="btn btn-sm papers_hoverDanger" ng-click="deleteKeys(data.Name, data.KeyType);"><img src="/modules/Papers/includes/icons/glyphicons-17-bin.png"/></button>
</td>
@ -200,8 +208,8 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
<hr />
<div class="form-group" ng-show="certKeyType=='tls_ssl'" ng-hide="certKeyType=='ssh'">
<label class="col-md-2 control-label">Signature Algorithm</label>
<div class="col-md-8">
<select name="sigalgo" ng-model="certSigAlgo" required>
<div class="col-md-6">
<select class="form-control" style="width: auto" name="sigalgo" ng-model="certSigAlgo" required>
<option value="sha1">SHA-1</option>
<option value="sha256">SHA-256</option>
<option value="sha512">SHA-512</option>
@ -269,15 +277,12 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
<div class="form-group" ng-show="certKeyType=='tls_ssl'" ng-hide="certKeyType=='ssh'">
<label class="col-md-2 control-label">Algorithm</label>
<div class="col-md-8">
<select name="algo" ng-model="certEncryptAlgo">
<select class="form-control" style="width:auto" name="algo" ng-model="certEncryptAlgo">
<option value="aes128">AES 128</option>
<option value="aes192">AES 192</option>
<option value="aes256">AES 256</option>
<option value="des">DES</option>
<option value="des3">3DES</option>
<option value="camellia128">Camellia 128</option>
<option value="camellia192">Camellia 192</option>
<option value="camellia256">Camellia 256</option>
</select>
</div>
</div>
@ -298,15 +303,12 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
<div class="form-group">
<label class="col-md-2 control-label">Container Algorithm</label>
<div class="col-md-8">
<select name="containerAlgo" ng-model="certEncryptPKCS12Algo">
<select class="form-control" style="width:auto" name="containerAlgo" ng-model="certEncryptPKCS12Algo">
<option value="aes128">AES 128</option>
<option value="aes192">AES 192</option>
<option value="aes256">AES 256</option>
<option value="des">DES</option>
<option value="des3">3DES</option>
<option value="camellia128">Camellia 128</option>
<option value="camellia192">Camellia 192</option>
<option value="camellia256">Camellia 256</option>
</select>
</div>
</div>
@ -323,6 +325,62 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
</div>
</div>
<div id="viewCert" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h3>Certificate Properties: {{ selectedCert }}</h3>
</div>
<div class="modal-body">
<img ng-show="loadingCert" ng-hide="!loadingCert" src='/img/throbber.gif'/>
<table class="table table-striped" ng-show="!loadingCert" ng-hide="loadingCert">
<tbody>
<tr>
<td>Serial</td>
<td>{{ viewCert.serial }}</td>
</tr>
<tr>
<td>Subject</td>
<td>{{ viewCert.subject }}</td>
</tr>
<tr>
<td>Issuer</td>
<td>{{ viewCert.issuer }}</td>
</tr>
<tr>
<td>Subject Alt Names</td>
<td>{{ viewCert.dns }}</td>
</tr>
<tr>
<td>Start Date</td>
<td>{{ viewCert.start }}</td>
</tr>
<tr>
<td>End Date</td>
<td>{{ viewCert.end }}</td>
</tr>
<tr>
<td>Fingerprint</td>
<td>{{ viewCert.fingerprint }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div id="viewLogInfo" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
@ -336,7 +394,75 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() {
</div>
</div>
</div>
<div id="encryptModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h3>Key Encryption : {{ selectedKey }}</h3>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group">
<label class="col-md-3 control-label">Algorithm</label>
<div class="col-md-9">
<select class="form-control" style="width:auto" name="algo" ng-model="certEncryptAlgo">
<option value="aes128">AES 128</option>
<option value="aes192">AES 192</option>
<option value="aes256">AES 256</option>
<option value="des">DES</option>
<option value="des3">3DES</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Key Password</label>
<div class="col-md-9">
<input type="password" class="form-control" ng-model="certEncryptPassword">
</div>
</div>
<div class="form-group">
<div class="col-md-12 text-center">
<img ng-show="encrypting" ng-hide="!encrypting" src='/img/throbber.gif'/>
<button type="button" class="btn papers_hoverInfo" ng-show="!encrypting" ng-hide="encrypting" ng-disabled="certEncryptPassword == ''" ng-click="encryptKey(selectedKey, selectedKeyType, certEncryptAlgo, certEncryptPassword);" style="width: 250px">Encrypt</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="decryptModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h3>Key Decryption : {{ selectedKey }}</h3>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group">
<label class="col-md-3 control-label">Key Password</label>
<div class="col-md-9">
<input type="password" class="form-control" ng-model="certDecryptPassword">
</div>
</div>
<div class="form-group">
<div class="col-md-12 text-center">
<img ng-show="decrypting" ng-hide="!decrypting" src='/img/throbber.gif'/>
<button type="button" class="btn papers_hoverInfo" ng-show="!decrypting" ng-hide="decrypting" ng-disabled="certDecryptPassword == ''" ng-click="decryptKey(selectedKey, selectedKeyType, certDecryptPassword);" style="width: 250px">Decrypt</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading pointer" data-toggle="collapse" data-target="#papers_errorLogs">

View File

@ -6,5 +6,5 @@
"tetra"
],
"title": "Papers",
"version": "1.5"
"version": "1.6"
}