mercoledì 5 ottobre 2011

Come autenticarsi in Linux senza password con le chiavi SSH

SSH è un fantastico strumento per gli amministratori di sistema. Consente di eseguire comandi da remoto, copiare file in rete, creare dei tunnel e tutto sfruttando i più robusti algoritmi di cifratura. Inoltre consente di stabilire delle rigide politiche riguardo l'autenticazione, come gli host o i PC da autenticare, utenti, ecc.
Quello di cui vi vorremmo parlare oggi è la possibilità di OpenSSH di autenticare un utente in base a uno scambio di chiavi, senza che venga richiesta la password e senza che questo possa rendere meno sicuro il nostro sistema. Di solito infatti siamo abituati a inserire una password per accedere a un sistema. Il concetto è quello di inserire una chiave pubblica (possedendo solo noi la corrispondente chiave privata) all'interno della configurazione di SSH sull'host remoto sul quale vorremmo autenticarci. In questo modo al tentativo di connessione SSH controllerà se la nostra chiave privata e la chiave pubblica lì presente fanno parte della stessa coppia e, in caso positivo, ci darà accesso al sistema.
Trovare una chiave privata a partire da una pubblica è infatti praticamente impossibile, e certamente più difficile di trovare una password. Se la mancanza di richiesta di password vi sconvolge pensate che comunque per assegnarla al server sarà necessario il login: non è quindi un'operazione che possono svolgere tutti, ma solo coloro che hanno già le giuste credenziali di accesso.
In pratica genereremo una coppia di chiavi, una pubblica e una privata. Quella pubblica verrà copiata sul server. Quando il server ci chiederà chi siamo, il nostro client genererà una firma a partire dalla nostra chiave pubblica. Il server, in possesso della chiave pubblica, può controllare se quella firma è stata generata da una chiave privata corrispondente alla chiave pubblica in suo possesso. In caso positivo verrà dato accesso al sistema.
Generiamo quindi la coppia di chiavi con il comando ssh-keygen, ci verrà chiesto di inserire un percorso (va bene anche quello proposto di default) e una passphrase (che sarà bene inserire e non usare una vuota a me no che non si voglia utilizzare degli automatismi in tale caso è opportuna lasciarla vuota) per la generazione delle chiavi:
[utente@linuxbox1 ~]$ ssh-keygen -b 2048 -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/utente/.ssh/id_rsa):
Created directory '/home/utente/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/utente/.ssh/id_rsa.
Your public key has been saved in /home/utente/.ssh/id_rsa.pub.
The key fingerprint is:
90:98:4f:f5:69:39:57:5d:46:83:a4:a2:d6:63:3c:25 utente@linuxbox1

A questo punto dovremmo copiare la chiave pubblica sul server SSH. Questa essendo pubblica può essere letta da chiunque, senza problemi di sicurezza. Per copiarla possiamo usare anche scp, programma per la copia di SSH. Ipotizzando che il server si chiami linuxbox2 e che l'utente si chiami utente2, il comando sarà:
[utente@linuxbox1 ~]$ scp /home/utente/.ssh/id_rsa.pub utente2@linuxbox2:.

Ci verrà chiesta la password di utente2 e il file id_rsa.pub, contenente la chiave pubblica, verrà copiata nella home di utente2 su linuxbox2. A questo punto facciamo il login su linuxbox2 (ovviamente come utente2), e copiamo il contenuto del file appena copiato nel file /home/utente2/.ssh/authorized_keys:


cat /home/utente2/id_rsa.pub >> /home/utente2/.ssh/authorized_keys
altro sistema per copiare la mia chiave pubblica su un server remoto (al quale ho un accesso):

ssh-copy-id -i ~/.ssh/id_rsa.pub username@macchina.remota
oppure utilizzando il protocollo ssh
creare una directory ~/.ssh come utente2 su Linuxbox2. (La directory potrebbe gia' esistere, il che va bene...):
utente@linuxbox1:~> ssh utente2@linuxbox2 mkdir -p .ssh
utente2@linuxbox2's password:
Ora appendi la nuova chive pubblica di utente su utente2@linuxbox2:.ssh/authorized_keys ed inserisci la password di utente2 per l'ultima volta:
utente@linuxbox1:~> cat .ssh/id_rsa.pub | ssh utente2@linuxbox2 'cat >> .ssh/authorized_keys'
utente2@linuxbox2's password:


A questo punto basterà provare a collegarsi dall'host linuxbox1 su linuxbox2 per connettersi a patto di inserire la passphrase scelta :
ssh utente2@linuxbox2

Backup incrementale con tar

Una funzionalità di tar non molto usata è quella degli archivi incrementali. E’ invece una funzionalità che può risultare molto utile in alcune strategie di backup, quando, ad esempio, si esegue un ciclo di backup su base settimanale ma non si vuole o non si può fare un backup completo ogni giorno.
Supponiamo ad esempio di voler fare il backup della directory /home/documenti salvando l’archivio in /var/backup. Il comando da dare è:
tar zcvf /var/backup/documenti-`date +%s`.tgz --listed-incremental=/var/log/documenti.tarlog /home/documenti
Viene cioè creato un’archivio dal nome documenti-.tgz (per esempio: documenti-1180427502.tgz), che contiene tutto quello che c’è in /home/documenti. La scelta di aggiungere la data in formato unix è totalmente arbitraria e serve solo come promemoria. Può essere usata al suo posto la data in formato normale usando +%F al posto di +%s.
Viene inoltre creato un file di log (/var/log/documenti.tarlog) che servirà a tar nei successivi backup per capire cosa è cambiato in /home/documenti e cosa va quindi inserito nei successivi backup.
Nei successivi archivi creati con lo stesso comando verranno inseriti solo i file nuovi o modificati e verrà aggiornato il file di log.
Cancellando il file di log e rilanciando il comando viene ricreato un archivio completo. Tutti gli archivi creati, quelli completi e quelli incrementali, hanno il grosso vantaggio di poter essere trattati individualmente, cioè non c’è bisogno della presenza del file di log per poter estrarre i files e le directory in essi contenuti.

Nella pratica se la directory /var/backup viene salvata ogni notte dei giorni lavorativi su supporto esterno (tape, cd/dvd, nas etc.) un semplicissimo script /usr/local/bin/backup_documenti.sh che utilizzi la funzionalità incrementale di tar potrebbe essere scritto in questo modo:

#!/bin/sh
# Cancella i vecchi archivi presenti
rm /var/backup/documenti-*.tgz
# prepara il nuovo archivio, completo se il file di log
#non esiste, altrimenti incrementale
tar zcvf /var/backup/documenti-`date +%s`.tgz --listed-incremental=/var/log/documenti.tarlog /home/documenti

Ovviamente se serve avere il file completo e gli incrementali la cancellazione degli archivi la facciamo nello script che parte il lunedì.
Lo scipt va lanciato tramite cron ogni giorno prima che il sistema di backup archivi la directory sul supporto esterno. Il primo giorno della settimana, prima che venga archiviata la directory dei documenti, sempre tramite cron, viene cancellato il file di log, in modo che il primo backup della settimana sia sempre completo.
Le righe da inserire in un crontab possono essere simili a queste:


#lunedì sera alle 21 cancello il file di log prima
#che cominci l'archiviazione
0 21 * * 1 rm -f /var/log/documenti.tarlog
# dal lunedì al venerdì alle 22 viene preparato
#il file archivio
0 22 * * 1-5 /usr/local/bin/backup_documenti.sh

martedì 4 ottobre 2011

Come rimuovere la password per le Macro VBA da Excel
Pubblicato da Alberto Armida | sabato 28 agosto 2010 | | Etichette: software, sviluppo
Un mio cliente mi contatta, chiedendomi di modificare un Excel utilizzato in azienda composto da alcune paginette più alcune Macro di VBA. Cerco di accedere alle Macro e... sorpresa! Richiesta di password di protezione VBA di Excel!!!

"Poco male" - penso. Contatto il cliente e mi sento rispondere: "Eh no... la password non gliela so dire. Questo foglio è stato fatto da una persona che ora non lavora più per noi. Ma tanto voi informatici ci mettete 10 minuti..." (chissà come mai la gente pensa che noi programmatori abbiamo la bacchetta magica o il dono dell'onniscienza... mah!)

Mi metto quindi alla ricerca di un modo per sproteggere questo dannato file: rivolgo una preghiera a San Google, che mi ritorna una serie di link che rimandano tutti a software a pagamento... no, grazie! Non intendo sborsare un minimo di 39$ per togliere una password!
Analizzando il file ed utilizzando quel poco di documentazione circa il formato XLS che Microsoft ha rilasciato... mi si accende una lampadina!!!

Aprite con il vostro editor esadecimale preferito il documento "vittima" (io utilizzo Notepad++ con il plugin Hex Editor)
Dal menù "Plugins", selezionate "Hex Editor", quindi "View in HEX" (CTRL+ALT+SHIFT+H, se preferite le scorciatoie da tastiera)
Dal menù "Cerca", selezionate "Cerca" e compilate la maschera come indicato in figura (cercate quindi "DPB" in formato Unicode)
Una volta localizzata la stringa, cambiatela in "DPx" (attenzione alle maiuscole e minuscole, è importante)
Salvate e chiudete l'editor
Aprite ora il vostor file Excel e rispondete "Sì" a questo messaggio di errore

Ora premete ALT+F11 per accedere al codice VBA del progetto. Vi verrà mostrato un "Errore imprevisto (40230)", non ve ne preoccupate e cliccate "OK" sino a che non si aprirà la maschera dell'editor VB di Excel
Ora dovreste già vedere gli oggetti VBA che compongono il progetto, ma non abbiamo ancora finito. Dal menù "Strumenti" selezionate "Proprietà di VBA Project", scheda "Protezione" e, se selezionato, deselezionate "Proteggi progetto dalla visualizzazione" ed inserite una nuova password per proteggere il foglio. (di fatto, state forzando Excel a riscrivere correttamente la sezione del file relativa alla protezione).
Confermate premendo "OK", salvate e chiudete il foglio di lavoro.
Ora potete riaprire il foglio e, se lo reputate neccessario, eliminate la password (tornando nella maschera sopra riportata), in modo da non avere più la richiesta quando cercate di visualizzare le proprietà del progetto.

Semplice, efficace... e soprattutto economico! Almeno 39$ risparmiati. :)

PS: ovviamente quando sopra riportato è puramente a fini didattici o per accedere a vostri Excel dei quali avete dimenticato la password o per i quali siete stati esplicitamente autorizzati dal legittimo proprietario.

Eseguire automaticamente script all'avvio di Ubuntu

Per poter creare uno script che venga automaticamente lanciato ad ogni avvio di Ubuntu, dobbiamo creare un file .sh nella cartella /etc/init.d/ che però deve avere come intestazione un blocco di sintassi rigida compreso tra

### BEGIN INIT INFO
### END INIT INFO
questo è il blocco di codice che deve essere inserito

### BEGIN INIT INFO
# Provides: scriptname
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO

Quindi:
sudo nano /etc/init.d/nomescript.sh
Scriviamo all’interno del file lo scirpt che vogliamo sia lanciato, diamo i permessi di esecuzione:
sudo chmod a+x /etc/init.d/nomescript.sh
ed infine lo lanciamo:
sudo update-rc.d -f nomescript.sh defaults

Ora lo script verrà eseguito ad ogni avvio della macchina e fermato al suo spegnimento

se noi volessimo invece che lo script venga solo avviato all'avvio (99 è il numero di priorità più alto il numero più tardi viene eseguito)
sudo update-rc.d -f myscript.sh start 99 2 3 4 5.
se volessimo che sia avviato al riavvio e allo spegnimento
sudo update-rc.d -f myscript.sh start 90 0 6.
oppure che venga fermato al riavvio e allo spegnimento
sudo update-rc.d -f myscript.sh stop 90 0 6.
altra possibilità è inserire lo script direttamente in /etc/rcN.d ovvero in rc2.d rc3.d ... rc5.d per avviarlo alla partenza e in rc0.d rc1.d rc6.d per il reboot e shutdown chiamando il file con S per start k per stop seguito dalla priorità.

In genere su Linux sono utilizzati i seguenti livelli:

Runlevel 0 : /etc/rc.d/rc0.d Questo runlevel avvia la sequenza di arresto del sistema (shutdown)
Runlevel 1: /etc/rc.d/rc1.d Questo runlevel rappresenta la modalità singolo utente, nessun altro utente può collegarsi, il servizio di rete è disabilitato.
Runlevel 2: /etc/rc.d/rc2.d Rappresenta lo stato multiutente, il servizio rete è attivo ma è disabilitato il file sharing.
Runlevel 3: /etc/rc.d/rc3.d In genere è quello predefinito quando si opera in modalità testuale, tutti i servizi sono attivi.
Runlevel 4: /etc/rc.d/rc4.d Inutilizzato. Può essere dedicato ad usi personali
Runlevel 5: /etc/rc.d/rc5.d E' il runlevel predefinito quando si vuole avviare Linux in modalità grafica
Runlevel 6: /etc/rc.d/rc6.d Il runlevel 6 è quello di reboot.  

Lo script /etc/rc.d/rc gestisce quali processi far partire a seconda del runlevel, andando ad analizzare le singole directory /etc/rc.d/rc#.d. In queste directory esistono una serie di symlink con nomi del tipo S12syslog o K65identd che puntano a degli script con nomi tipo /etc/rc.d/init.d/syslog o /etc/rc.d/init.d/identd.
/etc/rc.d/rc a seconda della directory corrispondente al runlevel da caricare fa partire tutti gli script che iniziano con S e fa chiudere tutti quelli che iniziano con K, eseguendoli nell'ordine indicato dal numero presente nei nomi dei file.
Gli script che di fatto permettono di gestire l'avvio o lo stop di un servizio sono quindi nella directory /etc/rc.d/init.d/ e possono essere utilizzati direttamente dall'utente per gestire i singoli processi.

es: S99nomescript.sh o K99nomescript.sh

altra possibilità di avviare uno script al completo riavvio del pc e inserire il nome dello script in /etc/init.d/rc.local che viene avviato dopo il completo avvio del pc ma comunque prima del login.

un esempio di script con funzioni avanzate si trova nel file /etc/init.d/skeleton che può servire come base di partenza per script d'avvio anche complessi

per ulteriori informazioni si veda il comando man update-rc.d