Unix e i permessi ----------------- Capire il meccanismo (spesso mal spiegato) dei permessi sui file di Unix, uno degli aspetti fondamentali di questo sistema operativo. Impostando opportunamente questi attributi potete rendere un file accessibile o inaccessibile ad alcuni utenti. Ma per capire i permessi dei file di Unix, bisogna prima capire come sono identificati e classificati gli utenti in un sistema Unix. Ecco una spiegazione in lingua italiana comprensibile ;) In un sistema multiutente come Unix ogni utente viene identificato da un nome unico, detto "username" che viene specificato all'atto della procedura di accesso al sistema (detta in gergo "login"). Per assicurarsi che l'utente sia proprio quello che dichiara di essere, è necessario che esso fornisca oltre allo username una stringa di caratteri corrispondente (detta password). Si deve avere cura di scegliere la password in modo che non sia facilmente indovinabile e di farla rimanere nota solo all'utente e al sistema. L'amministratore del sistema (root) può anche far sì che un utente possa loggarsi col solo username senza dover immettere nessuna password, ma la cosa non è raccomandabile su una macchina non protetta da accessi esterni. I sistemi Unix sono case-sensitive, quindi ad es. nome utente e password devono essere scritti con le giuste lettere maiuscole e minuscole, così come i nomi dei file a cui ci si vuole riferire. Dopo aver immesso il nome utente e la password corretti, il sistema UNIX concede l'accesso. Vengono eseguiti alcuni script di login che stabiliscono le preferenze dell'ambiente di lavoro dell'utente, (come la shell da usare, la stampante e l'editor di testo preferiti, ecc...), impostando i valori di alcune variabili di ambiente. Dopo che viene avviata la shell ci si ritrova posizionati nella propria home directory, che è una directory del file system di Unix in cui l'utente ha pieni privilegi. Ad es. la home directory dell'utente ant sul mio sistema è posizionata in /home/ant e i suoi privilegi sono: drwx------ 31 ant root 4096 Mar 22 14:41 ant/ capiremo tra poco il significato di questi simboli, comunque stanno a significare pieni privilegi per il possessore della directory (l'utente ant) e nessun privilegio per tutti gli altri (escluso il root che ha sempre tutti i privilegi). Il nome utente e la password sono stabiliti dall'amministratore di sistema (l'utente root) all'atto della creazione dell'account ed a questi dovete rivolgervi se dimenticate la password e non riuscite più a loggarvi nel sistema. Sin dalle origini Unix è stato un sistema operativo di rete, multitasking e multiutente, quindi possono esservi anche moltissimi utenti loggati contemporaneamente in un sistema e voi stessi potete loggarvi più di una volta se avete più di un account o anche più volte sullo stesso account utilizzando terminali virtuali o fisici diversi. Inoltre potete loggarvi da remoto, purché esista un collegamente di rete tra client e server (usando sul client programmi come rlogin, telnet o ssh, che comunicano con i rispettivi programmi server sul server). Ogni utente di un sistema Unix è membro di 1 o più gruppi. Un gruppo è un insieme di utenti che godono di un accesso protetto alle loro risorse. Il caso più semplice è quello in cui ogni utente appartiene ad un gruppo con lo stesso nome del nome utente stesso; in tal caso è come se i gruppi non esistessero. I nomi degli utenti e dei gruppi in Unix sono biunivocamente associati ad alcuni numeri, per convenienza di rappresentazione interna. Alcuni file di configurazione di sistema, normalmente modificabili solo dal root ma leggibili da tutti, mantengono traccia dell'associazione username<=>userid e groupname<=>groupid. Questi file sono /etc/passwd e /etc/group. Il "Group ID" viene anche indicato con l'abbreviazione GID, mentre lo "User ID" con l'abbreviazione UID. Detto questo possiamo affrontare l'argomento delle permission sui file. In Unix ogni file ha associato lo userid del possessore, un numero che corrisponde all'username dell'utente che possiede il file. Ad es. sul mio sistema l'utente ant ha userid 500 (ant<=>500), quindi se un file ha userid 500, allora il possessore di quel file è ant e viceversa. Ricordate quindi che lo userid di un file indica il possessore del file. Ogni file ha inoltre associato il nome o se volete l'id corrispondente del gruppo che lo possiede, che può essere scelto dall'utente solo tra i gruppi a cui l'utente stesso appartiene. In altri termini un utente non può stabilire che il gruppo di un file che possiede sia X se X non è un gruppo a cui appartiene. C'è una sola eccezione: l'utente root non ha questa limitazione e può settare il gruppo di un file anche se l'utente possessore del file non vi appartiene. L'utente root comunque è il superuser, il superutente manutentore del sistema che ha tutti i privilegi e può fare tutto. Ricapitolando: ogni file ha un utente ed un gruppo di appartenza. Poi ogni file ha associati alcuni bit di stato chiamati permessi. Semplificando, possiamo dire che ci sono tre tipi di permessi su un file (in realtà ce ne sono altri, ma comunque questi 3 sono i più usati), che vengono comunemente indicati in forma mnemonica con una lettera: r permesso di lettura del file (Read) w permesso di scrittura del file (Write) x permesso di esecuzione del file (eXecute) Occorre notare che non è il permesso di scrittura su un file (w) che conferisce il permesso di cancellare il file, bensì è il permesso wx sulla directory che lo contiene. Il comando rm si limita a chiedere conferma della cancellazione se non si possiede il permesso w su un file ma si posseggono i permessi wx sulla directory, ma la cancellazione rimane ugualmente possibile in questo caso. Questa affermazione risulterà chiara tra poco quando spiegherò il significato dei permessi sulle directory. Ciascuno di questi tre permessi è definito per tre tipi di utenti, per un totale quindi di 9 bit di stato dei permessi (almeno di quelli che esamineremo noi). Anche i tipi di utenti vengono identificati con delle lettere mnemoniche: u utente che possiede il file (User) g membri del gruppo al quale appartiene il file (Group) o tutti gli altri utenti che non ricadono nelle due categorie precedenti (Others) I permessi di accesso per tutti i tre tipi di utenti possono quindi essere rappresentati con una stringa di nove caratteri, scelti tra i tre r,w,x: user group others r w x r w x r w x Questa rappresentazione viene utilizzata dal comando ls, che tra le altre cose visualizza i permessi del file quando viene usato con l'opzione -l. Quando un permesso non è concesso ls visualizza un trattino (-) al suo posto. I tre permessi di user esistono perché a volte può essere conveniente limitare l'accesso a sé stessi. Un'altra rappresentazione molto usata dei permessi di un file è quella ottale. E' più semplice far vedere un esempio di come si ricava questa rappresentazione che descriverne il procedimento: rwxr-xr-x 111101101 7 5 5 Anche le directory hanno un utente ed un gruppo di appartenza e dei permessi, però nel caso delle directory i permessi hanno un significato differente, anche se vengono utilizzati gli stessi simboli r,w,x. La tabella seguente riassume per ogni permesso il suo significato su un file e su una directory: il permesso su un File è il permesso di su una Directory è il permesso di --------------------------------------------------------------------------------- r (read) lettura del file listare i suoi file (solo i nomi) w (write) scrittura del file creare, rinominare, cancellare i suoi file (in aggiunta occorre il permesso x) x execute esecuzione del file leggere, scrivere, eseguire i suoi file (se il permesso dei file lo consente) Un esempio per chiarire le idee: l'utente root ha creato una directory prova all'interno della home di ant, con i seguenti permessi: drwxr-x--- 2 root root 4096 Mar 14 17:52 prova/ L'utente ant vede che c'è quella directory in virtù del fatto che può listare il contenuto della directory padre, ma ricadendo nella categoria others (supponiamo non appartenga al gruppo root) non ha alcun permesso su quella directory. Ecco cosa accade quando ant tenta invece di listare o fare cd nella directory: [ant@localhost ant]$ ll prova/ ls: prova/: Permission denied [ant@localhost ant]$ cd prova/ bash: cd: prova/: Permission denied L'utente ant può cancellare la directory prova (con rd prova/) se questa è vuota e se ha diritto di scrittura (w) nella propria directory home, indipendentemente dai permessi della directory prova stessa. Tuttavia se prova non è vuota, non può cancellarla, perché avrebbe bisogno prima dei permessi per poter listare e cancellare i file contenuti. Supponente poi che il proprietario di prova (il root) decida di dare il permesso r alla categoria di utenti others. Il root fa questo con il comando: # chmod o+r prova/ che si legge: "cambia la modalità di accesso alla directory prova/ (chmod); alla categoria others (o) aggiungi (+) il permesso di lettura (r)". Sommando il permesso di lettura ai permessi che c'erano prima, per effetto dell'operatore + si ha, banalmente: --- r-- === r-- Difatti la somma è una somma logica (OR logico dei permessi). Quindi i permessi complessivi di prova/ diventano, come mostrato da ls: drwxr-xr-- 2 root root 4096 Mar 14 22:09 prova/ Supponete poi dentro prova ci sia un file chiamato test. Non importa quali sono le permission di test, adesso l'utente ant ne vede solo il nome, non può vederne le permission, la dimensione, la data di ultima modifica ecc... [ant@localhost ant]$ ll prova/ ls: prova/test: Permission denied total 0 [ant@localhost ant]$ cd prova/ bash: cd: prova/: Permission denied La ragione di questo comportamento è che in un sistema Unix una directory non è altro che un file speciale che contiene una lista dei nomi dei file contenuti e, per ogni file, un indice nella "lista degli inode". Nell'inode di un file vengono mantenute tutte le informazioni relative ad esso, ad eccezione del suo nome, che come detto si trova nel file della directory padre. Questo spiega perché nell'esempio precedente vediamo solo il nome dei file contenuti nella directory prova: infatti il permesso di lettura di una directory significa solo che possiamo leggere il file speciale che rappresenta la directory, che contiene la lista dei nomi dei file contenuti, il riferimento all'inode e niente di più. E' interessante adesso provare cosa succede attivando solo il permesso x sulla directory per gli utenti come ant. Il root da il comando: chmod o=x prova/ Quindi i permessi di prova diventano: drwxr-x--x 2 root root 4096 Mar 14 22:11 prova/ Adesso l'utente ant ha il permesso di leggere i file della directory prova, ma solo se questi li concedono diritto di lettura. Inoltre dovrà conoscere il nome del file perché non ha il permesso di listare il contenuto della directory. Può però fare cd nella directory. [ant@localhost ant]$ ll prova/ ls: prova/: Permission denied [ant@localhost ant]$ cat prova/test contenuto di test nell'ipotesi che questo file abbia permessi di lettura per ant [ant@localhost ant]$ cd prova/ [ant@localhost prova]$ Non può però creare un nuovo file nella directory: [ant@localhost ant]$ cat>prova/nuovo bash: prova/nuovo: Permission denied Se però ant ha i permessi di scrittura su un file già esistente dentro la directory può riscriverlo: [ant@localhost ant]$ cat>prova/test nuovo contenuto scritto da ant Lo stesso dicasi per quanto riguarda l'esecuzione di un file dentro la directory. In tutti e tre i casi (lettura,scrittura,esecuzione), ant deve avere il permesso su quel file e deve indovinare il nome se ha solo il permesso x sulla directory genitore. Anche qui la ragione di questo comportamento è presto spiegata: quello che il permesso x conferisce ad ant è il permesso di lettura e scrittura degli inode corrispondenti ai file contenuti nella directory. Così ad es. se ant fa "ll prova/test", visualizza tutte le informazioni nell'inode di test. Il permesso di scrittura di un inode è necessario ma non sufficiente per poter editare un file: occorre inoltre avere la permission di scrittura del file in questione. Lo stesso per la lettura e l'esecuzione. Terzo caso: ant ha sia il permesso r che x sulla directory prova (chmod o=rx prova/). Semplicemente si sommano i permessi illustrati prima: ant può listare la directory ottenendo i nomi dei file contenuti in virtù del permesso r ed in più può accedere anche agli inode dei file contenuti in virtù del permesso x, con la conseguenza che se le permission di un file contenuto nella directory lo consente, ant può leggere, scrivere e/o eseguire questo file, cosa che non può fare col solo permesso r sulla directory (anche se il file lo consente), per l'impossibilità di accedere all'inode del file (cosa che consente il permesso x sulla directory). Insomma rx su una directory differisce da x solo per il fatto che l'utente non deve "indovinare" i nomi dei file. Tenete a mente che il solo permesso x su una directory è necessario ma non sufficiente per poter leggere scrivere e/o eseguire file contenuti: occorre anche avere tali permessi sui singoli file. Quarto caso: ant ha solo il permesso w sulla directory prova. In tal caso tutto quello che può fare è modificare il file speciale che rappresenta la directory. Questo gli conferisce il permesso di creare, rinominare, cancellare file all'interno della directory semplicemente rispettivamente aggiungendo, rinominando, togliendo una entry da questo file? No, perché per creare un file dentro una directory occorre avere il permesso x oltre che il permesso w: w occorre per aggiungere una entry al file della directory e x per poter creare un nuovo inode. Per rinominare un file esistente con mv, occorre avere accesso w al file della directory ed accesso x alla directory perché occorre aggiornare il tempo ctime nell'inode (il tempo ctime o status indica proprio il tempo di ultima modifica delle informazioni di stato del file contenute nell'inode, quindi di ultima modifica dell'inode stesso). Per cancellare un file in una directory non basta il permesso w su quella directory, occorre anche il permesso x per rimuoverne l'inode. Quinto caso (chmod o=rwx): banale combinazioni di tutti i permessi visti nei casi precedenti. Tenete presente che il root può fare tutto, indipendentemente dai permessi di un file. Anche se un file non ha alcun permesso (---------) il root può fare tutto su questo. Loggarsi come root per l'uso ordinario del sistema apre un buco di sicurezza grande quanto una casa ed inoltre è molto semplice danneggiare il sistema cancellando qualche file vitale se si è inesperti, o anche se si è esperti e si va troppo di fretta e si sbaglia un comando. Come ultimo consiglio pensate sempre agli inode ed ai file di directory speciali e sarete in grado di regolare le permission o risolvere eventuali problemi di accesso negato. Occhio sempre alla sicurezza del sistema che dipende molto dalle permission sui file. Come è ovvio, essere troppo "permissivi" su alcuni file importanti di sistema è un grosso buco di sicurezza. Nel mio sistema Linux esiste un sottoalbero di info che spiega i permessi dei file richiamabile col comando: $ info "File utilities" "File permissions" Ricordate inoltre che ovviamente bisogna essere possessore del file per poter cambiare i permessi col comando chmod (a meno che non si sia l'utente root), così come il gruppo o l'utente di appartenenza. Se così non fosse sarebbe fin troppo facile scavalcare la protezione offerta dai permessi. La shell mette a disposizione il comando umask. Eccone la descrizione: [ant@localhost ant]$ help umask umask: umask [-p] [-S] [mode] The user file-creation mask is set to MODE. If MODE is omitted, or if `-S' is supplied, the current value of the mask is printed. The `-S' option makes the output symbolic; otherwise an octal number is output. If `-p' is supplied, and MODE is omitted, the output is in a form that may be used as input. If MODE begins with a digit, it is interpreted as an octal number, otherwise it is a symbolic mode string like that accepted by chmod(1). Se date il comando interno umask senza argomenti verrà stampata il valore corrente della vostra umask. Nel mio caso, ad es.: [ant@localhost ant]$ umask 022 oppure in forma simbolica: [ant@localhost ant]$ umask -S u=rwx,g=rx,o=rx Il valore ottale della umask non indica i permessi che avrà di default un file creato dall'utente, bensì il contrario: i permessi che vengono tolti. Nel mio caso umask 022 significa che il permesso w viene tolto sia al gruppo che a tutti gli altri utenti, mentre tutti gli altri permessi vengono concessi, come si vede meglio dall'equivalente output in forma simbolica ottenuto col parametro -S. In altri termini il valore ottale della umask viene "sottratto" dal valore ottale 666 per determinare i permessi di default di un file. Perciò parliamo di questo valore come umask (che è l'abbreviazione di user mask, ossia maschera dell'utente): il valore umask viene di fatto usato come una maschera in una particolare operazione logica: così come la maschera di carnevale copre certe parti del viso per non farvi riconoscere, la umask non fa passare alcuni 1 del numero 0666=110110110b. Quale sia l'operazione logica è presto detto. Ecco la sua tabella di verità (dove F e U sono due bit, l'operazione è del tipo bit-a-bit e non è commutativa): F | U | F op U ---+---+------- 0 | 0 | 0 0 | 1 | 0 1 | 0 | 1 1 | 1 | 0 Con U ho indicato un bit dell'umask, mentre con F ho indicato un bit del valore da mascherare (Full permission). Mediante gli operatori logici fondamentali AND e NOT, l'operazione si definisce così: F op U == F AND NOT U Questa formula si legge a parole dicendo che i permessi di default di un file sono determinati dall'AND logico tra i pieni permessi e la negazione logica dell'umask. In effetti si potrebbe definire ed utilizzare anche il complemento logico dell'umask, ma questo non viene fatto in pratica, perché si preferisce pensare ai permessi "da togliere" anziché a quelli da "mantenere". Si tratta di una operazione logica e non di una operazione aritmetica, tuttavia tanto per ricordarsela mnemonicamente, notate che è simile alla sottrazione di bit ignorando la questione del riporto (la riga che differisce rispetto alla sottrazione è 0 op 1 = 0). Proprio per questo l'operazione op e la sottrazione di bit NON sono la stessa cosa. Nota: per le directory il valore che l'umask maschera è 777, 666 è solo per i file. Per settare una nuova umask è sufficiente fornire la nuova maschera in ottale al comando umask. Es: [ant@localhost ant]$ umask 000 D'ora in poi i nuovi file che vengono creati avranno i permessi: 666 op 000 == ------ 666 cioè rw-rw-rw- mentre le directory avranno i permessi: 777 op 000 == ------ 777 cioè rwxrwxrwx Se invece la setto così: [ant@localhost ant]$ umask 066 Allora un nuovo file avrà il permesso: 666 op 066 == ------ 600 cioè rw------- mentre una nuova directory avrà il permesso: 777 op 066 == ------ 711 cioè rwx--x--x Altro esempio: umask 077 permesso predefinito di un file: 666 op 077 == ------ 600 cioè rw------- permesso predefinito di una directory: 777 op 077 == ------ 700 cioè rwx------ Se preferite un altro valore di umask, settatevelo nel vostro .bash_profile o .profile se non usate la bash. Concludiamo con un problemino pratico: il solito utente (ant) vuole rendere accessibile via web (all'utente sotto cui gira il server web, chiamato apache) la directory: $HOME/public_html dove è posizionato il proprio sito web. I permessi della home directory di ant e della sua directory padre /home sono i seguenti: drwxr-xr-x 3 root root 4096 Mar 13 22:41 home drwx------ 37 ant root 4096 Mar 26 22:43 ant/ Mentre quelli di ant/public_html sono: drwxr-xr-x 17 ant ant 4096 Mar 11 22:20 public_html/ Una possibile semplice soluzione è la seguente: $ cd /home $ chmod a+x ant/ (oppure solo: chmod o+x ant/) Potete testarla sia via web, sia impersonandovi come utente apache con un "su apache" (possibile solo se avete i permessi di root, essendo l'account di apache disabilitato). Avendo presente il significato del solo permesso x su una directory, capite che questa soluzione offre una certa sicurezza, poiché mancano agli altri utenti i permessi rw sulla directory e per il fatto che solo root può impersonare l'utente apache; rende quindi difficile ad altri utenti curiosare nei file della vostra home (devono indovinarne il nome), o impossibile se ne regolate bene i permessi, in modo che non possano leggere o scrivere i file anche se ne indovinano il nome. Potete infatti regolare i permessi e i possessori sulla directory public_html e sui file contenuti in modo che siano più restrittivi per gli altri utenti, senza impedire all'utente apache l'accesso.