sqlite instead of file system to store macs
This commit is contained in:
parent
ebff21147c
commit
b08f87e9e5
6
.htaccess
Normal file
6
.htaccess
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Addtype application/octet-stream .ttf .otf
|
||||||
|
AddType application/vnd.ms-fontobject .eot
|
||||||
|
|
||||||
|
RewriteRule (.*).php $1
|
||||||
|
RewriteRule (.*).hmtl $1
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
define("OUTPUT_SERVER_DIRECTORY", "/home/sandbender/www/pamela-trans/uploads");
|
// Number of seconds a mac address file is valid. If it's older it will be removed.
|
||||||
define("MACFILE_TTL", "3600");
|
define("MACFILE_TTL", "3600");
|
||||||
|
|
||||||
|
// Where the db is located for the sqlite db. The file does not have to exist.
|
||||||
|
// The directory does need to exist though, and the directory must be writable.
|
||||||
|
define("SQLITE_DB", "/home/sandbender/www/pamela/db/pamela.sql");
|
||||||
|
|
||||||
|
// sql create statement for mac table
|
||||||
|
define("CREATE_MAC_TABLE_SQL", "create table macs (mac text unique on conflict replace, committime integer);");
|
||||||
|
|
11
lib/db.php
Normal file
11
lib/db.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
require_once("config.php");
|
||||||
|
|
||||||
|
function get_db() {
|
||||||
|
static $db = NULL;
|
||||||
|
if ($db == NULL) {
|
||||||
|
$db = sqlite_open(SQLITE_DB);
|
||||||
|
}
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
26
lib/macs.php
Normal file
26
lib/macs.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
require_once("lib/db.php");
|
||||||
|
|
||||||
|
function macs_get() {
|
||||||
|
$results = array();
|
||||||
|
$db = get_db();
|
||||||
|
$q = sqlite_query($db, "select mac from macs where committime > strftime('%s','now') - ".MACFILE_TTL);
|
||||||
|
if (!$q) return $results;
|
||||||
|
while(sqlite_has_more($q)) {
|
||||||
|
$row = sqlite_fetch_array($q, SQLITE_ASSOC);
|
||||||
|
$results[] = $row['mac'];
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
function macs_add($mac) {
|
||||||
|
$db = get_db();
|
||||||
|
$mac = sqlite_escape_string($mac);
|
||||||
|
$q = sqlite_exec($db, "insert into macs values (\"$mac\", strftime('%s','now'))");
|
||||||
|
if (!$q) return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
function macs_purge() {
|
||||||
|
$db = get_db();
|
||||||
|
return sqlite_exec($db, "delete from macs where committime <= strftime('%s','now') - ".MACFILE_TTL);
|
||||||
|
}
|
|
@ -95,4 +95,8 @@ function script($source) {
|
||||||
<script type="text/javascript" src="<?=$source?>"></script>
|
<script type="text/javascript" src="<?=$source?>"></script>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
function echoln($str) {
|
||||||
|
echo("$str\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
71
macs.php
71
macs.php
|
@ -24,11 +24,8 @@ header("Cache-Control: no-cache");
|
||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
require_once("config.php");
|
require_once("config.php");
|
||||||
require_once("lib/util.php");
|
|
||||||
require_once("lib/trans.php");
|
require_once("lib/trans.php");
|
||||||
|
require_once("lib/macs.php");
|
||||||
// [ "00:01:e8:04:99:be", "00:05:4e:40:1e:97", "00:0c:f1:16:10:ba", "00:0c:f1:1d:dc:70", "00:0e:35:96:c7:ff", "00:11:85:6a:1f:ec", ]
|
|
||||||
|
|
||||||
|
|
||||||
function translator($mac) {
|
function translator($mac) {
|
||||||
global $mac_translation_table;
|
global $mac_translation_table;
|
||||||
|
@ -37,65 +34,7 @@ function translator($mac) {
|
||||||
return $mac;
|
return $mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$macs = macs_get();
|
||||||
class Macs {
|
$macs = array_map("translator", $macs);
|
||||||
|
echo '["'.implode('", "', $macs).'"]';
|
||||||
private $macs;
|
macs_purge();
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
$this->macs = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function readFile($filename) {
|
|
||||||
$mcs = file_get_contents($filename);
|
|
||||||
$this->macs = array_merge($this->macs, explode(',', $mcs));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function readFiles($directory) {
|
|
||||||
$macFiles = scandir($directory);
|
|
||||||
foreach ($macFiles as $macFile) {
|
|
||||||
if (preg_match("/.+\.macs$/", $macFile) != 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$filename = "$directory/$macFile";
|
|
||||||
|
|
||||||
// data is too old, remove
|
|
||||||
if (filemtime($filename) + MACFILE_TTL < time()) {
|
|
||||||
unlink($filename);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->readFile($filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function cleanUp() {
|
|
||||||
$this->macs = array_unique($this->macs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function translate() {
|
|
||||||
$this->macs = array_map("translator", $this->macs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createJson() {
|
|
||||||
if (count($this->macs) < 1) {
|
|
||||||
echo '[]';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '["';
|
|
||||||
echo implode('", "', $this->macs);
|
|
||||||
echo '"]';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run() {
|
|
||||||
$this->readFiles(OUTPUT_SERVER_DIRECTORY);
|
|
||||||
$this->cleanUp();
|
|
||||||
$this->translate();
|
|
||||||
$this->createJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$macs = new Macs();
|
|
||||||
$macs->run();
|
|
||||||
|
|
|
@ -34,8 +34,7 @@ USER=''
|
||||||
PASSWORD=''
|
PASSWORD=''
|
||||||
|
|
||||||
function usage {
|
function usage {
|
||||||
|
echo "Usage: pamela-scanner [OPTIONS]
|
||||||
echo "Usage: pamela-scanner [OPTIONS]
|
|
||||||
|
|
||||||
-i INTERFACE Interface to arp-scan. Defaults to [$IF].
|
-i INTERFACE Interface to arp-scan. Defaults to [$IF].
|
||||||
-o URL The url of the pamela upload script (including /upload.php).
|
-o URL The url of the pamela upload script (including /upload.php).
|
||||||
|
@ -51,71 +50,85 @@ webserver where you get a visual representation of the mac addresses present.
|
||||||
Multiple people on multiple lans can run pamela together against the same
|
Multiple people on multiple lans can run pamela together against the same
|
||||||
server, where all results are agregated. In short, pamela gives you an overview
|
server, where all results are agregated. In short, pamela gives you an overview
|
||||||
of how big the shared network is."
|
of how big the shared network is."
|
||||||
|
}
|
||||||
|
|
||||||
exit 1
|
function check_if_root {
|
||||||
|
if [ "$(id -ru)" != "0" ]
|
||||||
|
then
|
||||||
|
echo "Must be root to run pamela-scanner"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_if_arpscan_installed {
|
||||||
|
if [ -z "$(which arp-scan)" ]
|
||||||
|
then
|
||||||
|
echo "ENOARPSCAN: Could not find arp-scan, please install it"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function register {
|
function register {
|
||||||
|
check_if_root
|
||||||
|
check_if_arpscan_installed
|
||||||
echo "Registering pamela in cron: $PAM_CRON"
|
echo "Registering pamela in cron: $PAM_CRON"
|
||||||
echo "*/2 * * * * root [ -x \"$PAM_SCRIPT\" ] && \"$PAM_SCRIPT\" -i \"$IF\" -o \"$OUT\" -u \"$USER\" -p \"$PASSWORD\" >> \"$PAM_LOG\"" > "$PAM_CRON"
|
echo "*/2 * * * * root [ -x \"$PAM_SCRIPT\" ] && \"$PAM_SCRIPT\" -i \"$IF\" -o \"$OUT\" -u \"$USER\" -p \"$PASSWORD\" >> \"$PAM_LOG\"" > "$PAM_CRON"
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function unregister {
|
function unregister {
|
||||||
|
check_if_root
|
||||||
echo "Unregistering pamela in cron: $PAM_CRON"
|
echo "Unregistering pamela in cron: $PAM_CRON"
|
||||||
rm "$PAM_CRON"
|
rm "$PAM_CRON"
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMP=$(getopt -o 'hrqi:o:s:u:p:-n' "pamela arp scanner" -- "$@")
|
function parse_params {
|
||||||
if [ $? != 0 ] ; then echo "Could not parse parameters..." >&2 ; exit 1 ; fi
|
TEMP=$(getopt -o 'hrqi:o:s:u:p:-n' "pamela arp scanner" -- "$@")
|
||||||
eval set "$TEMP"
|
if [ $? != 0 ] ; then echo "Could not parse parameters..." >&2 ; exit 1 ; fi
|
||||||
while true
|
eval set "$TEMP"
|
||||||
do
|
while true
|
||||||
shift;
|
do
|
||||||
[ -z "$1" ] && break;
|
shift;
|
||||||
case "$1" in
|
[ -z "$1" ] && break;
|
||||||
-i) IF="$2"; shift;;
|
case "$1" in
|
||||||
-o) OUT="$2"; shift;;
|
-i) IF="$2"; shift;;
|
||||||
-s) SLEEP="$2"; shift;;
|
-o) OUT="$2"; shift;;
|
||||||
-u) USER="$2"; shift;;
|
-s) SLEEP="$2"; shift;;
|
||||||
-p) PASSWORD="$2"; shift;;
|
-u) USER="$2"; shift;;
|
||||||
-r) REGISTER='r';;
|
-p) PASSWORD="$2"; shift;;
|
||||||
-q) unregister; break;;
|
-r) REGISTER='r';;
|
||||||
-h|'-?') usage; break;;
|
-q) unregister; exit 0;;
|
||||||
*) echo "Unknown param: [$1]"; usage; exit 1;
|
-h|'-?') usage; exit 1;;
|
||||||
esac
|
*) echo "Unknown param: [$1]"; usage; exit 1;;
|
||||||
done
|
esac
|
||||||
|
done
|
||||||
|
# Register only after parsing all args
|
||||||
|
if [ -n "$REGISTER" ]; then
|
||||||
|
register
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
#register only after parsing all args
|
function scan_and_upload {
|
||||||
[ -n "$REGISTER" ] && register
|
echo $(date)" scanning..."
|
||||||
|
NETMASK="$(ip -4 addr show "$IF" | egrep -o "brd [0-9\.]+" | egrep -o "[0-9\.]+")"
|
||||||
|
MACS=""
|
||||||
|
NUM_MACS=0
|
||||||
|
for M in $(arp-scan -R -i 10 --interface "$IF" --localnet | awk '{ print $2 }' | grep :.*: | sort | uniq)
|
||||||
|
do
|
||||||
|
[ -n "$MACS" ] && MACS="$MACS,$M" || MACS="$M";
|
||||||
|
let "NUM_MACS=NUM_MACS+1"
|
||||||
|
done
|
||||||
|
POST="sn=$NETMASK&macs=$MACS"
|
||||||
|
RESULT=$(wget "$OUT" -O - --quiet --post-data "$POST" --user "$USER" --password "$PASSWORD" || echo "wget error: $?")
|
||||||
|
if [ -n "$RESULT" ]
|
||||||
|
then
|
||||||
|
echo Error uploading results:
|
||||||
|
echo "$RESULT"
|
||||||
|
fi
|
||||||
|
echo $(date)" Uploaded $NUM_MACS mac addresses..."
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$(id -ru)" != "0" ]
|
parse_params $@
|
||||||
then
|
check_if_root
|
||||||
echo "Must be root to run pamela-scanner"
|
check_if_arpscan_installed
|
||||||
exit 1
|
scan_and_upload
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$(which arp-scan)" ]
|
|
||||||
then
|
|
||||||
echo "ENOARPSCAN: Could not find arp-scan, please install it"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $(date)" scanning..."
|
|
||||||
NETMASK="$(ip -4 addr show "$IF" | egrep -o "brd [0-9\.]+" | egrep -o "[0-9\.]+")"
|
|
||||||
MACS=""
|
|
||||||
NUM_MACS=0
|
|
||||||
for M in $(arp-scan -R -i 10 --interface "$IF" --localnet | awk '{ print $2 }' | grep :.*: | sort | uniq)
|
|
||||||
do
|
|
||||||
[ -n "$MACS" ] && MACS="$MACS,$M" || MACS="$M";
|
|
||||||
let "NUM_MACS=NUM_MACS+1"
|
|
||||||
done
|
|
||||||
POST="sn=$NETMASK&macs=$MACS"
|
|
||||||
RESULT=$(wget "$OUT" -O - --quiet --post-data "$POST" --user "$USER" --password "$PASSWORD" || echo "wget error: $?")
|
|
||||||
if [ -n "$RESULT" ]
|
|
||||||
then
|
|
||||||
echo Error uploading results:
|
|
||||||
echo "$RESULT"
|
|
||||||
fi
|
|
||||||
echo $(date)" Uploaded $NUM_MACS mac addresses..."
|
|
||||||
|
|
32
upload.php
32
upload.php
|
@ -19,48 +19,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
header("Content-type: text/plain");
|
header("Content-type: text/plain");
|
||||||
require_once("config.php");
|
|
||||||
require_once("lib/util.php");
|
require_once("lib/util.php");
|
||||||
|
require_once("lib/macs.php");
|
||||||
function echoln($str) {
|
|
||||||
echo("$str\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
class Upload {
|
class Upload {
|
||||||
|
|
||||||
private $subnet;
|
|
||||||
private $macs;
|
private $macs;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
$this->subnet = getPost("sn");
|
|
||||||
$this->macs = getPost("macs");
|
$this->macs = getPost("macs");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseAndValidate() {
|
private function parseAndValidate() {
|
||||||
if ($this->subnet == NULL) {
|
|
||||||
echoln("Missing or bad sn param");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($this->macs == NULL) {
|
if ($this->macs == NULL) {
|
||||||
echoln("Missing macs param");
|
echoln("Missing macs param");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match("/^(\d{1,3}\.){3}\d{1,3}$/", $this->subnet) != 1) {
|
|
||||||
echoln("subnet ($this->subnet) is not valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$snParts = explode('.', $this->subnet);
|
|
||||||
foreach($snParts as $part) {
|
|
||||||
$i = intvaldef($part, -1);
|
|
||||||
if (($i >= 0) && ($i <= 255))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
echoln("subnet ($this->subnet) contains invalid parts ($part)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mcs = explode(',', $this->macs);
|
$mcs = explode(',', $this->macs);
|
||||||
foreach($mcs as $mac) {
|
foreach($mcs as $mac) {
|
||||||
if (preg_match("/^(([\dABCDEF]){2}:){5}([\dABCDEF]){2}$/i", $mac) == 1)
|
if (preg_match("/^(([\dABCDEF]){2}:){5}([\dABCDEF]){2}$/i", $mac) == 1)
|
||||||
|
@ -72,7 +47,10 @@ class Upload {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function writeMacs() {
|
private function writeMacs() {
|
||||||
file_put_contents(OUTPUT_SERVER_DIRECTORY."/$this->subnet.macs", $this->macs);
|
$mcs = explode(',', $this->macs);
|
||||||
|
foreach($mcs as $mac) {
|
||||||
|
macs_add($mac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run() {
|
public function run() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user