Directory sotto controllo con Perl

folder_locked.png
Navigando per CPAN, l’imponente archivio dei moduli Perl, mentre cercavo delle funzioni per smanettare con i permessi sui file, mi sono imbattuto nel modulo File::Monitor, che permette di monitorare file e directory in cerca (o in attesa) di cambiamenti di qualsiasi tipo.
Capirete che questo genere di funzionalità puà rivelarsi molto utile qualora si volesse monitorare lo stato di una directory importante a cui nessuno dovrebbe apportare modifiche, come ad esempio le directory di installazione del vostro sito internet, le directory contenenti informazioni sugli utenti che dovrebbero essere modificate solo dall’amministratore di sistema o dal sistema stesso ecc.. .
Questo modulo offre una classe principale File::Monitor, a cui assegnare diversi elementi da controllare e grazie ad un sistema di gestione degli eventi, ad ogni occorrenza di un determinato tipo di evento, potrete eseguire una specifica serie di istruzioni (contenute in subroutine).
Ecco la lista gerarchizzata dei possibili tipi di evento:

change

created

deleted

metadata

time

mtime

ctime

perms

uid

gid

mode

size

directory

files_created

files_deleted

Ogni volta che File::Monitor rileva un cambiamento in uno dei suoi “bersagli”, incapsula le informazioni a riguardo in un oggetto di tipo Delta, da cui poi possiamo estrarle con dei semplici metodi.

Ecco un semplice esempio di come monitorare una directory in modo superficiale, senza controllare nel dettaglio i cambiamenti apportati ai files, naturalmente.

Questo esempio è molto esemplificato e se voleste scrivere uno script che controlli ogni aspetto dei vostri files, dovreste aggiungere istruzioni per ogni tipo di evento.

use File::Monitor;sub getDate() {

#Funzione che restituisce la data nel formato: gg/mm/aaaa--hh-mm-ss;

 	@time = localtime();

#è necessario aggiungere 1900 perchè localtime contiene il numero di anni passati dal 1900

 	$time[5] = $time[5]+1900;

#è necessario aggiungere 1 al mese perchè localtime conta i mesi a aprtire da 0

 	$time[4] = $time[4]+1;

 	return $time[3]."/".$time[4]."/".$time[5]."--".$time[2].":".$time[1].":".$time[0];

}

sub DIRchanged() {

#Ecco cosa facciamo quando la directory cambia

                open(FH,">>/tmp/dirMonitor.log") || die "ERRORE!!\t Impossibile aprire il log!!\n";

 	print "Data: ".&getDate()."\t";

 	print "ATTENZIONE!! La directory $DIR ha subito delle modifiche!!\n";

 	print FH "Data: ".&getDate()."\t";

 	print FH "ATTENZIONE!! La directory $DIR ha subito delle modifiche!!\n";

 	close(FH);

            }

#Oggetto fondamentale

my $monitor = File::Monitor->new();

#Prendiamo la directory da controllare, che è passata argomento

unless (-d $ARGV[0]) { die("ERRORE:\t La directory da monitorare specificata, non esiste!!\n\n")

$DIR = $ARGV[0];

$monitor->watch( {

        name        => $DIR,

        recurse     => 1,

        files       => 0

    } );

#Il primo scan on rileva cambiamenti ma raccoglie le informazioni sui files

$monitor->scan();

#Per ogni cambiamento, esegue i controlli che vogliamo

foreach my $change ($monitor->scan()) {

if ($change->is_event('changed')) {

&DIRchanged();

}

}

Per prima cosa ho incluso la libreria Monitor, poi ho definito due subroutine:
getDate(): formatta la data corrente in modo approfondito fino ai secondi
DIRchanged(): risponde all’evento changed modificando un file di log ed emettendo il segnale di allarme allo Standard Output

Creo l’oggetto monitor, e poi controllo che esista la directory da controllare passata come argomento da riga di comando, altrimenti termina con un messaggio di errore.

Il metodo watch(), assegna la directory da controllare e setta i flag che ne definiscono il comportamento:
recurse: Se settato a true e il flag base è una directory, scansiona ricorsivamente tutto l’albero directory sottostante alla directory specificata
files: Se settato a true e il flag base è una directory, scansiona tutti i file e directory sottostanti alla directory specificata, ma non ricorsivamente

In questo modo però solamente i nomi dei files e delle directory vengono controllati, per approfondire il controllo dobbiamo lavorare con i Delta Objects.

A questo punto, lanciamo il primo scan, che non rileva cambiamenti dei files in quanto stiamo facendo il primo controllo ed il monitor non ha ancora nessuna informazione a riguardo, ma si tratta della fase di acquisizione delle informazioni su di essi.

Tutti gli scan successivi restituiscono un oggetto di tipo Delta, su cui effettueremo i nostri test.

Perl ed il modulo Term::ReadLine

Vi siete mai chiesti come implementare un prompt dei comandi per le vostre applicazioni? Perl vi fornisce un modulo perfetto allo scopo, che in poche righe di codice (12 nel caso del nostro esempio) vi permette di configurare un terminale con tanto di storico dei comandi inseriti.
Buttiamoci subito nell’ analisi del codice:

##############Config########################
 my $PROMPTSTRING = '%PSH% >>>';
 my $PROMPTNAME = 'term';
 ##############Main########################
 use Term::ReadLine;
 my $term = new Term::ReadLine $PROMPTNAME;
 my $out = $term->OUT || \*STDOUT;
 while (defined($_ = $term->readline($PROMPTSTRING))) {
  my $result = eval($_);
  warn $@ if $@;
  chop($result);
  print $result, "\n" unless $@;
  $term->addhistory($_) if /\s/;
}

Le prime due istruzioni, impostano il messaggio che visualizzeremo nel prompt ed il nome del terminale, mentre la terza include il modulo perl che fornisce tutte le subroutines necessarie (si trova facilmente il deb nei repository Debian), non c’è bisogno che vi ricordi che senza quel modulo non funziona una mazza vero?.

Dopo l’inclusione del modulo inizia la parte interessante:
Creiamo l’oggetto Term::ReadLine ed impostiamo come output, la variabile $out, che conterrà l’output del prompt stesso e quello emesso dallo standard output.

Il ciclo while tiene vivo il terminale, salvando il comando immesso dall’utente nella variabile $_; quindi ad ogni ciclo, viene valutata la stringa $_ come se fosse una istruzione perl e viene eseguita come sottoprogramma (tutto questo grazie alla funzione eval() ).
Infine visualizziamo l’output oppure gli eventuali messaggi di errore per poi aggiungere il nostro comando alla history.

Per maggiori informazioni vi rimando a:

Prima release seria per eMule Log Checker

elalogo.png

Ho terminato la prima release seria di emule Log Checker (o Analyzer non fa differenza XD), in cui ho implementato alcune opzioni da riga di comando , l’opzione di help ed un mitico File README!!! 😀

È disponibile un archivio zip contenente lo script e la documentazione, basta cliccare sul link download

P.S. In caso decidiate di scaricare il file, vi sarei davvero grato se lasciaste un commento all’articolo di presentazione presente al sito bubbledev.altervista.org, giusto per rendermi conto del numero di downloads e per ricevere feedback da voi (potete anche utilizzare la mail)

Facilitarsi la vita con PHP e Smarty

smarty-logo-orange.gif

Se siete programmatori PHP e siete stanchi di dover utilizzare le solite funzioni printheader() e printfooter(), ma soprattutto stanchi di impastare il codice dentro tag html, dovete proprio darvi una svegliata…. esitono i Template Manager!!
Vediamo di dare una breve definizione di un template manager:
Una classe che si occupa di sostituire dei tag presenti all’interno di un template HTML (un template è un modello in cui inserire contenuti) con l’opportuno output.

In questo articolo prenderò come esempio il template engine che preferisco: Smarty.
Smarty è dotato di funzioni avanzate come le istruzioni condizionali ed i loop , (da inserire all’interno del codice di templating stesso, che possono tornare molto utili per modificare la struttura HTML in base all’output del proprio codice. Ad esempio, potremmo voler visualizzare nella nostra Homepage il form di login solo se l’utente non si è loggato, in caso contrario visualizzeremo una dashboard o un semplice menu utente. Quersto ed altro è possibile grazie a Smarty.

Ecco un semplice esempio di utilizzo di smarty per l’inserimento dei dati di un post all’interno di un template, utile per un blog:

<html>
<head>
<title> {$title} </title>
</head>
<body>
<div class="post">
<div class="cTitle">{$cTitle}</div>
<div class="cContent">{$cContent}</div>
<div class="cFooter">Scritto il {$cDate} da {$cAuthor}     <a href={$cID}>Commenti</a>({cCommentsCount})</div>
<div class="cTags">
{foreach from=$cTags item=tag}
<a href=sito.com/tags/{$tag}>{$tag}</a>,
{/foreach}
</div>
</body>
</html>

Ecco il codice php che fa funzionare il tutto 😉

//File index.php
<?
require("path/della/lib/smarty/Smarty.class.php");
$smarty = new smarty(); //La classe smarty
$template = "directory/index.tpl"; //Il file .tpl che contiene la definizione html dotat dei giusti tag
//Qui il codice che recupera i dati da un database
//Ordino i tutti i dati del post in un array associativo che si chiama $post :)
//Ecco la sequenza di assegnazione TAG-OUTPUT
$smarty->assign('cTitle',$post["title"]);
$smarty->assign('cContent',$post["content"]);
$smarty->assign('cDate',$post["date"]);
$smarty->assign('cAuthor',$post["author"]);
$smarty->assign('cTags',$post["tags"]);
$smarty->assign('cID',$post["id"]);
$smarty->assign('cCommentsCount',$post["CommentsCount"]);
$smarty->display($template); // La direttiva che visualizza il template con i tag formattati a dovere ?>

Questo esempio è molto semplice e non credo abbia bisogno di particolari spiegazioni, comunque prende dei dati e li formatta a dovere all’interno del template, la possibilità di creare tag condizionali permette di avere un solo template per diverse circostanze ed evitare un sovraffollamento di files. Se avete domande postate pure!cmq vi rimando alla documentazione ufficiale

Attacco DoS: Fork Bombing!!

Questa particolare tecnica di DoS, (Denial OF Service) in locale, consiste nella creazione di un numero sempre crescente di processi, con il preciso scopo di saturare la memoria della macchina vittima. Per ottenere questo risultato non sono necesarie particolari “numeri” 😉 basta sfruttare la chiamata a sistema fork().

Innanzitutto è importante conoscere il metodo di gestione della memoria del bersaglio, bisogna quindi essere a conscenza del sistema operativo che gira su quella data macchina, per poterne sfruttare i punti deboli.
Ad esempio nei sistemi UNIX, prima che un processo venga eseguito, è allo stato ready e risiede nell’hard disk, mentre per essere eseguito passa allo stato running e risiede nella memoria RAM. I dati e le istruzioni dei processi vengono salvati nelle cosiddette “pagine”, ovvero dei blocchi di memoria di dimenione fissa che impediscono ai processi di intaccare i dati di altri processi, durante la vita di un processo, non vengono caricate in RAM tutte le pagine che lo riguardano ma solamente quelle contenti dati ed istruzioni sensibili al funzionamento. Se il processo non trova la pagina desisderata, si verifica un Page Fault, ovveo il processo viene bloccato, la pagina viene caricata ed il processo viene ripristinato (Ho semplificato parecchio per brevità… magari scriverò un approfondimento in merito).

Cosa succede se il numero dei page fault aumenta a dismisura? Ecco il problema, si verifica il fenomeno detto Trashing: le risorse necessarie alla gestione dei Page Fault sono maggiori delle risorse necessarie al completamento dei compiti del processo. Questo comporta ovvi problemi: la saturazione delel risorse impedisce qualsiasi operazione, dal Login (che avviene tramite un processo) alla creazione di files…. l’unica soluzione è il reboot.

Ecco alcuni semplici esmepi di programmi e script che saturano le risorse della macchina che lo esegue:

Script Bash

:(){ :|:& };:

Script Perl

fork while fork;

Programma C

#include 
 
 int main()
 {
   while(1) { 
     fork(); 
   } 
   return 0; 
 }

Vedete che bastano poche istruzioni per dare parecchi problemi al processore…. comunque i recenti kernel, hanno limitato il numero di processi generabili dagli utenti normali, per saturare le risorse di un sistema, bisognerebbe ottenere i privilegi di R00T!!