HackRoom
   Home  .  News  .  Wiki  .  Community  .  Programs  .  How-To  .  Projects  .  Admin   
 How-To

Cisco
FreeBSD
HTML
J2Me
Lastlog
Linux
Motori di ricerca
Threads
Proto ITA
Proto ENG

Login
Register

Powered by Apache

Powered by PHP

Powered by DokuWiki

Creative Commons License

Get Mozilla FireFox

HTML Validated

CSS Validated

Get Avira AntiVir

Acquista gli oggetti firmati HackRoom.

Effettua i tuoi pagamenti con PayPal.


Linux paper Lastlog  

di SDNS
L'utility lastlog permette di esaminare il file /var/log/lastlog, attraverso il quale si puo visualizzare l'ultimo login effettuato di ogni user. Le stesse informazioni sono memorizzate sul file /var/log/lastlog.
Il file lastlog e' una sorta di database sul quale, come detto in precedenza, viene memorizzato l'ultimo accesso di ogni user (non ci dilungheremo sulla sua funzionalita', per maggiori dettagli visualizzare il relativo manual page).
L'output del comando è il seguente:
  
bash-3.1# lastlog
UsernamePortFromLatest
rootpts/8osiris..Fri Jul 11 22:24:14 +0200 2008
bin**Never logged in**
daemon**Never logged in**
adm**Never logged in**
lp**Never logged in**
sync**Never logged in**
shutdown**Never logged in**
halt**Never logged in**
mail**Never logged in**
news**Never logged in**
uucp**Never logged in**
operator**Never logged in**
games**Never logged in**
ftp**Never logged in**
smmsp**Never logged in**
mysql**Never logged in**
rpc**Never logged in**
sshd**Never logged in**
gdm**Never logged in**
apache**Never logged in**
messagebus**Never logged in**
haldaemon**Never logged in**
pop**Never logged in**
nobody**Never logged in**

Ogni Username puo essere considerato come un'entry del database. La memorizzazione su tale file avviene per mezzo di una struttura definita in   
/usr/include/bits/utmp.h:
#define UT_LINESIZE 32
#define UT_NAMESIZE 32
#define UT_HOSTSIZE 256

/* The structure describing an entry in the database of previous logins.*/
struct lastlog
{
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
  int32_t ll_time;
#else
  __time_t ll_time;
#endif
  char ll_line[UT_LINESIZE];
  char ll_host[UT_HOSTSIZE];
};

tale struttura, costituisce la dimensione effettiva dell'entry riguardante l'user. La memorizzazione all'interno del file avviene in base alla dimensione della struttura, precedentemente indicata, e all'uid (User ID). Per ogni user (o entry) viene dedicata una certa quantità di spazio, precisamente 292 byte, che corrisponde alla dimensione della struttura lastlog (sizeof(struct lastlog)). Il posizionamento delle rispettive entry nel file non sono lasciate al caso, per esempio scritte in coda come avverrebbe in un normale database, la sua posizione all'interno del file è calcolata da "sizeof(struct lastlog) * uid". Per capire meglio possiamo procedere con un esempio:
Supponiamo di volerci loggare sul sistema mediante l'utility di amministrazione OpenSSH utilizzando il relativo client e proviamo a loggarci con l'user avente uid 1000, nello stesso momento possiamo vedere cosa avviene durante l'esecuzione del processo preso in considerazione, mediante il comando "strace -p pid" (per pid si intente il process ID del processo del demone sshd che si occupa della procedura di login).
Quindi, dopo esserci assicurati di avere il demone avviato, avviare una sessione di login con il seguente comando:
  
bash-3.1$ ssh username@192.168.1.3

in seguito verra richiesta la password, lasciarlo vuoto in quanto dobbiamo trovare il pid del processo che prenderemo in considerazione.
Per ottenere il seguente pid digitare il seguente comando:
  
bash-3.1$ ps aux | grep sshd
root 2456 0.0 0.0 3856 984 ? Ss Jul28 0:00 /usr/sbin/sshd
root 28485 0.1 0.0 5204 1784 ? Ss 18:38 0:00 sshd: username [priv]
sshd 28488 0.0 0.0 5204 1100 ? S 18:38 0:00 sshd: username [net]

il processo che prenderemo in considerazione è quello con il pid 28485, avviare in seguito l'utility strace relativa al processo, e procedere con il login, inserendo la password richiesta in modo tale che la scrittura del file /var/log/lastlog sia avvenuta.
Supponendo che l'user "username" abbia uid 1000 abbiamo ricavato dall'utility strace il seguente output:
  
user con uid 1000
stat64("/var/log/lastlog", {st_mode=S_IFREG|0644, st_size=292584, ...}) = 0
open("/var/log/lastlog", O_RDWR|O_CREAT|O_LARGEFILE, 0600) = 7
_llseek(7, 292000, [292000], SEEK_SET) = 0
write(7, "|\271wHpts/8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 292) = 292
close(7)

Come si puo vedere, si accedere al file in scrittura, poi si posiziona alla posizione 292000, che corrisponde a sizeof(struct lastlog) * uid, ovvero 292 * 1000 = 292000, che come potete vedere corrisponde alla posizione dove si trovano le informazioni dell'user richiesto. Ulteriori prove sono state fatte con appositi user creati con uid 1001, 1003, 10013 e 60000 (il massimo uid definito in /etc/login.defs).
  
user con uid 1001
stat64("/var/log/lastlog", {st_mode=S_IFREG|0644, st_size=292584, ...}) = 0
open("/var/log/lastlog", O_RDWR|O_CREAT|O_LARGEFILE, 0600) = 7
_llseek(7, 292292, [292292], SEEK_SET) = 0
write(7, "\23\274wHpts/5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 292) = 292
user con uid 1003
stat64("/var/log/lastlog", {st_mode=S_IFREG|0644, st_size=292584, ...}) = 0
open("/var/log/lastlog", O_RDWR|O_CREAT|O_LARGEFILE, 0600) = 7
_llseek(7, 292876, [292292], SEEK_SET) = 0
write(7, "\23\274wHpts/5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 292) = 292
user con uid 1013
stat64("/var/log/lastlog", {st_mode=S_IFREG|0644, st_size=292584, ...}) = 0
open("/var/log/lastlog", O_RDWR|O_CREAT|O_LARGEFILE, 0600) = 7
_llseek(7, 295796, [292292], SEEK_SET) = 0
write(7, "\23\274wHpts/5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 292) = 292

Si puo' notare che l'offset tra l'user con 1003 e l'user con uid 1013 varia di circa 2920 byte:
  
uid 1003 = 292876 -
uid 1013 = 295796 = 2920

che corrisponde a 292 * 10, ovvero lo spazio degli altri 10 user mancanti!!

E' da notare anche la differenza del file con user uid consegutivi e con uid uguale a 60000:
  
bash-3.1# du -b /var/log/lastlog
296088 /var/log/lastlog
bash-3.1# du -b /var/log/lastlog
17520292 /var/log/lastlog

Puo' sembrare che la memorizzazione del lastlog avvenga parallelamente al file /etc/passwd, ma è da precisare che la memorizzazione del lastlog avviene in ordine parallelo agli uid occupati, l'utilizzo del valore univoco UID per il calcolo dell'offset, permette di avere uno spazio dedicato per ogni user, ordinato, permettendo cosi ai programmi che utilizzano tale file di posizionarsi in maniera corretta alla posizione desiderata senza dover effettuare operazioni di ricerca.
E' da sottolineare che durante la prova con uid massimo consentito, lo spazio viene allocato alla posizione derivata da sizeof(struct lastlog) * uid, come detto in precedenza, ma nel caso in cui volessimo aggiungere un user con uid 5000, è da ricordare che lo spazio per tale user è gia stato allocato, quindi non ci sarebbe un'ulteriore utilizzo di memoria.
In breve, viene dedicato uno spazio per ogni user di 292 byte, nel caso in cui l'uid sia superiore ma non consecutivo all'ultimo presente, viene allocato spazio per gli user mancanti con i possibili uid non utilizzati.
Per poter aggiornare il file lastlog, quindi si puo procedere con l'apertura del file in scrittura e lettura , posizionarsi sulla posizione dell'user preso in considerazione, riempire la struttura manualmente o leggendo direttamente dal file, cambiare gli appositi valori, riposizionarsi sull'offset desiderato e in seguito scrivere sul file.

Powered by HackRoom

03