Utilizzare ACL per risolvere problemi di permessi sulle cartelle FTP con i file caricati da Apache

Utilizzare ACL per risolvere problemi di permessi sulle cartelle FTP

Un problema piuttosto comune che potrebbero lamentare gli utenti del nostro server FTP è quello di non avere la possibilità di modificare / cancellare i file caricati attraverso Apache. Un tipico esempio sono gli allegati o le immagini agli articoli del blog, oppure i moduli installati via interfaccia di amministrazione in CMS quali Joomla. Il problema è dato dal fatto che questi file vengono caricati dall'utente Apache, con permessi giustamente (parlando in termini di sicurezza) restrittivi, tipicamente 644 per i file o 755 per le cartelle, il che equivale a dire che solo il proprietario di tali file / cartelle è in grado di modificarli o cancellarli (permesso di scrittura), o in altri termini che il nostro utente FTP non ha modo di modificare / cancellare tali file utilizzando il client FTP in quanto tali file / cartelle possono essere gestite solo dal relativo proprietario (Apache per l'appunto).

Una possibile soluzione potrebbe essere quella di rinominare la cartella / il file (cosa consentita), e quindi ricaricare lo stesso file / cartelle via FTP, ma non è certo una soluzione pratica nè tantomeno elegante.

Modificare l'utente Apache assegnandogli lo stesso utente del server FTP o viceversa potrebbe essere un'altra soluzione, ma non è certo consigliabile in termini di sicurezza.

Invece, una buona soluzione potrebbe essere quella di uilizzare ACL, Access Control List, per la gestione dei permessi sulle cartelle del nostro server FTP. ACL consente di superare le due principali limitazioni del sistema di gestione permessi predefinito di Linux, ovvero:

  • non è possibile impostare più di una entità come utente o gruppo
  • non è possibile impostare qualcosa come dei permessi di defaul a cartelle o file

ACL è caricato di default (supporto via kernel) su Ubuntu per i filesystem + recenti (su EXT3, ad esempio). Per utlizzare ACL però, è necessario come prima cosa montare il filesystem con l'opzione corretta. A tal fine bisogna editare /etc/fstab ed aggiungere al filesystem l'opzione ACL come mostrato di seguito:

# /dev/sda1
UUID=b4a5834e-dba5-49a4-aa9b-662de5d83654   /   ext3   relatime,errors=remount-ro,acl   0   1

Quindi riavviare la macchina o rimontare il file system con:

sudo mount -o remount /

In secondo luogo è necessario installare gli strumenti setfacl e getfacl per lavorare sui permessi con ACL:

sudo apt-get install acl

A questo punto è possibile impostare i permessi di default sulle cartelle dove andrà anche a scrivere il nostro web server. Ad esempio, supponiamo di avere la cartella folder creata via FTP dove andremo ad installare il nostro CMS e dove ci saranno ad esempio delle cartelle create via FTP con permesso 777 dove Apache andrà a scrivere i suoi file (ad esempio i file caricati su di un sito dagli utenti) con permessi 644. Vogliamo assegnare a tutti i file caricati in questa cartella la possibilità di essere modificati anche dall'utente ftpuser uilizzato da tutti gli utenti virtuali del nostro server pureFTPd, a tal fine è sufficiente scrivere:

sudo setfacl -d -m u:ftpuser:rwx folder

Questo imposta (modifica, parametro -m) i permessi di default (-d) per la cartella folder all'utente (u:) ftpuser in lettura, scrittura, ed esecuzione. Assegnamo a questa cartella sempre all'utente ftpuser anche i permessi "non di default", ripetendo il comando senza utilizzare il parametro "-d" (default).

sudo setfacl -m u:ftpuser:rwx folder

Se ora proviamo a caricare una nuova cartella styles contenente un certo numero di file, all'interno della cartella folder via SSH e come utente root, possiamo verificare che è possibile modifcare questi file anche utilizzando l'utente ftpuser utilizzato dalla nostra connessione FTP. Infatti se andiamo a controllare i permessi impostati sulla nuova cartella appena caricata vedremo che:

$> sudo getfacl folder/styles

# file: folder/styles
# owner: root
# group: root
user::rwx
user:ftpuser:rwx
group::r-x
mask::rwx
other::r-x
default:user::rwx
default:user:ftpuser:rwx
default:group::r-x
default:mask::rwx
default:other::r-x

Ovvero l'utente FTP (ftpuser) risulta comproprietario assieme all'utente root e dispone degli stessi permessi (ovviamente solo su cartella e file appena caricati) dell'utente root. Se poi andassimo a controllare un singolo file nella cartella appena caricata:

$> sudo getfacl folder/styles/afile.php

# file: folder/styles/afile.php
# owner: root
# group: root
user::rw-
user:ftpuser:rwx                #effective:rw-
group::r-x                      #effective:r--
mask::rw-
other::r--

Vediamo che ftpuser ne risulta sempre comproprietario, e che tra l'altro non viene assegnato il permesso di esecuzione come mostrato (#effective: rw-) e come si può evidenziare anche con un semplice:

$> ls -la folder/styles

totale 104
drwxrwxr-x+ 2 root    root     4096 2009-12-03 17:13 .
drwxrwxr-x+ 13 ftpuser ftpgroup 4096 2009-12-03 17:12 ..
-rw-rw-r--+ 1 root    root      516 2005-08-03 03:37 debug.css
-rw-rw-r--+ 1 root    root     9901 2006-04-28 14:02 phplist.css
-rw-rw-r--+ 1 root    root     1566 2004-04-19 11:31 shader.css
-rw-rw-r--+ 1 root    root     3387 2003-11-25 18:20 styles_help.css
-rw-rw-r--+ 1 root    root     3027 2007-07-11 18:55 styles_mac.css
-rw-rw-r--+ 1 root    root     3005 2005-09-12 19:38 styles_unix1.css
-rw-rw-r--+ 1 root    root     3548 2009-12-03 17:13 styles_unix.css
-rw-rw-r--+ 1 root    root     3219 2005-09-12 19:38 styles_win_ie.css
-rw-rw-r--+ 1 root    root     3173 2005-09-12 19:38 styles_win_ns.css
-rw-rw-r--+ 1 root    root     1316 2005-08-03 03:37 tabs.css

Si noti il "+" alla fine della colonna dei permessi "-rw-rw-r--+" che indica appunto che tale su tale file / cartella è attivata la gestione permessi via ACL.

Quello che abbiamo fatto con il comando sudo setfacl -d -R -m u:ftpuser:rwx folder non è stato altor che rendere l'uente ftpuser di default comproprietario per tutti i file e le cartelle caricate all'interno della cartella folder, sia che questi vengano caricati via FTP (e che quindi sia di effettiva proprietà di fptuser) sia che vengano caricati da qualunque altro utente del vostro sistema, ad esempio via SSH o tramite Apache (ad esempio dalla vostra applicazione PHP).

Un'ultima nota. Un po' più problematica invece risulta la gestione dei permessi su eventuali file già caricati. Potremmo impostare i permessi ricorsivamente, ma ci sono dei problemi, ovvero sarà necessario distinguere tra cartelle e file. Ad esempio, supponedo di avere la cartella docs utilizzata da Apache per salvare gli allegati, se scrivessimo

sudo setfacl -R -m u:ftpuser:rw folder/docs

per assegnare ricorsivamente (parametro -R) anche all'utente ftpuser permessi di lettura e scrittura sui file, otterremmo il risultato di rendere non navigabile la cartella docs ed eventuali sottocartelle in quanto avremmo impostato non eseguibili (ovvero non sfogliabili) la cartella docs ed eventuali sottocartelle, ma d'altro canto, non sarebbe nemmeno una buona idea in termini di sicurezza scrivere

sudo setfacl -R -m u:ftpuser:rwx folder/docs

che se va bene per le cartelle, equivale a rendere eseguibili anche tutti i file in esse contenute e non non è certo una cosa buona...

Un modo per modificare i permessi ricorsivamente solo sulle cartelle o solo sui sui file c'è. Ad esempio, per impostare ricorsivamente i permessi sulle sole cartelle, in modo che ne sia possibile la gestione anche da parte dell'utente ftpuser, possiamo utilizzare l'opzione -exec del comanda find. Utilizzando find possiamo cercare i soli file o le sole directory (-type f o -type d) presenti all'interno di una data cartella (e sottocartella/e) ed eseguire sul file trovato l'operazione che ci interessa; per quanto riguarda le cartelle possiamo scrivere:

sudo find folder/docs -type d -exec setfacl -d -m u:ftpuser:rwx {} \;

sudo find folder/docs -type d -exec setfacl -m u:ftpuser:rwx {} \;

mentre per assegnare i permessi di lettura e scrittura su tutti i file presenti all'interno della cartella folder/docs anche all'utente ftpuser, è sufficiente scrivere:

sudo find folder/docs -type f -exec setfacl -m u:ftpuser:rw {} \;

Le parentesi graffe alla fine del comando "sostituiscono" il nome del file restituito da find. Ad esempio, per modificare i permessi ricorsivamente a tutti i file a partire dalla cartella corrente, è sufficiente scrivere un . al posto del nome della cartella:

sudo find . -type f -exec setfacl -m u:ftpuser:rw {} \;

Spingendoci un po' più in là, possiamo ad esempio cercare tutti i file nelle cartelle */files/ di Drupal ed assegnare il permesso ad Apache di scrivere e leggere su file e cartelle. Ad esempio, per modificare i permessi sui file:

sudo find /var/www/drupal-multisite -type f -path \*/files/\* -exec setfacl -m u:www-data:rw {} \;

La fliessibiltà del comando file è talmente elevata che l'unico limite è la nostra fantasia. Per una buona guida su find, vi rimando a "Using the find command" su linux.ie ed ovviamente al buon vecchio "man find".