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
|
||||
|
||||
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");
|
||||
|
||||
// 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>
|
||||
<?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");
|
||||
|
||||
require_once("config.php");
|
||||
require_once("lib/util.php");
|
||||
require_once("lib/trans.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", ]
|
||||
|
||||
require_once("lib/macs.php");
|
||||
|
||||
function translator($mac) {
|
||||
global $mac_translation_table;
|
||||
|
@ -37,65 +34,7 @@ function translator($mac) {
|
|||
return $mac;
|
||||
}
|
||||
|
||||
|
||||
class Macs {
|
||||
|
||||
private $macs;
|
||||
|
||||
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();
|
||||
$macs = macs_get();
|
||||
$macs = array_map("translator", $macs);
|
||||
echo '["'.implode('", "', $macs).'"]';
|
||||
macs_purge();
|
||||
|
|
|
@ -34,8 +34,7 @@ USER=''
|
|||
PASSWORD=''
|
||||
|
||||
function usage {
|
||||
|
||||
echo "Usage: pamela-scanner [OPTIONS]
|
||||
echo "Usage: pamela-scanner [OPTIONS]
|
||||
|
||||
-i INTERFACE Interface to arp-scan. Defaults to [$IF].
|
||||
-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
|
||||
server, where all results are agregated. In short, pamela gives you an overview
|
||||
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 {
|
||||
check_if_root
|
||||
check_if_arpscan_installed
|
||||
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"
|
||||
exit 0
|
||||
}
|
||||
|
||||
function unregister {
|
||||
check_if_root
|
||||
echo "Unregistering pamela in cron: $PAM_CRON"
|
||||
rm "$PAM_CRON"
|
||||
exit 0
|
||||
}
|
||||
|
||||
TEMP=$(getopt -o 'hrqi:o:s:u:p:-n' "pamela arp scanner" -- "$@")
|
||||
if [ $? != 0 ] ; then echo "Could not parse parameters..." >&2 ; exit 1 ; fi
|
||||
eval set "$TEMP"
|
||||
while true
|
||||
do
|
||||
shift;
|
||||
[ -z "$1" ] && break;
|
||||
case "$1" in
|
||||
-i) IF="$2"; shift;;
|
||||
-o) OUT="$2"; shift;;
|
||||
-s) SLEEP="$2"; shift;;
|
||||
-u) USER="$2"; shift;;
|
||||
-p) PASSWORD="$2"; shift;;
|
||||
-r) REGISTER='r';;
|
||||
-q) unregister; break;;
|
||||
-h|'-?') usage; break;;
|
||||
*) echo "Unknown param: [$1]"; usage; exit 1;
|
||||
esac
|
||||
done
|
||||
function parse_params {
|
||||
TEMP=$(getopt -o 'hrqi:o:s:u:p:-n' "pamela arp scanner" -- "$@")
|
||||
if [ $? != 0 ] ; then echo "Could not parse parameters..." >&2 ; exit 1 ; fi
|
||||
eval set "$TEMP"
|
||||
while true
|
||||
do
|
||||
shift;
|
||||
[ -z "$1" ] && break;
|
||||
case "$1" in
|
||||
-i) IF="$2"; shift;;
|
||||
-o) OUT="$2"; shift;;
|
||||
-s) SLEEP="$2"; shift;;
|
||||
-u) USER="$2"; shift;;
|
||||
-p) PASSWORD="$2"; shift;;
|
||||
-r) REGISTER='r';;
|
||||
-q) unregister; exit 0;;
|
||||
-h|'-?') usage; exit 1;;
|
||||
*) echo "Unknown param: [$1]"; usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
# Register only after parsing all args
|
||||
if [ -n "$REGISTER" ]; then
|
||||
register
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
#register only after parsing all args
|
||||
[ -n "$REGISTER" ] && register
|
||||
function scan_and_upload {
|
||||
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" ]
|
||||
then
|
||||
echo "Must be root to run pamela-scanner"
|
||||
exit 1
|
||||
fi
|
||||
parse_params $@
|
||||
check_if_root
|
||||
check_if_arpscan_installed
|
||||
scan_and_upload
|
||||
|
||||
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");
|
||||
require_once("config.php");
|
||||
require_once("lib/util.php");
|
||||
|
||||
function echoln($str) {
|
||||
echo("$str\n");
|
||||
}
|
||||
require_once("lib/macs.php");
|
||||
|
||||
class Upload {
|
||||
|
||||
private $subnet;
|
||||
private $macs;
|
||||
|
||||
function __construct() {
|
||||
$this->subnet = getPost("sn");
|
||||
$this->macs = getPost("macs");
|
||||
}
|
||||
|
||||
private function parseAndValidate() {
|
||||
if ($this->subnet == NULL) {
|
||||
echoln("Missing or bad sn param");
|
||||
return false;
|
||||
}
|
||||
if ($this->macs == NULL) {
|
||||
echoln("Missing macs param");
|
||||
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);
|
||||
foreach($mcs as $mac) {
|
||||
if (preg_match("/^(([\dABCDEF]){2}:){5}([\dABCDEF]){2}$/i", $mac) == 1)
|
||||
|
@ -72,7 +47,10 @@ class Upload {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user