GRANT e REVOKE
I permessi possono essere gestiti in due modi: attraverso le istruzioni SQL GRANT e REVOKE, oppure con le normali istruzioni SQL (INSERT, UPDATE ecc.) sulle tabelle interessate.
La differenza da tenere presente è che nel primo caso le modifiche sono immediatamente effettive, mentre nel secondo caso è necessario usare il comando FLUSH PRIVILEGES per costringere MySQL a ricaricare in memoria le tabelle dei permessi.
Vediamo alcuni esempi di sintassi per GRANT e REVOKE:
GRANT SELECT ON acquisti.* TO luca@localhost IDENTIFIED BY 'password' WITH GRANT OPTION
Il permesso relativo alle SELECT sarà regisrato sulla tabella db, essendo assegnato a livello di database. Inoltre all'utente viene assegnato il permesso GRANT, grazie al quale sarà in grado di assegnare ad altri utenti i propri permessi. Attenzione: con questa opzione l'utente potrà assegnare ad altri tutti i propri permessi: non solo quelli ricevuti con questa istruzione, ma anche quelli che aveva già e quelli che riceverà in futuro.
GRANT ALL ON acquisti.ordini TO paolo@localhost
Questa istruzione assegna tutti i permessi sulla tabella ordini del database acquisti all'utente paolo@localhost. Non è stata specificata una password, per cui se l'utente esisteva già questa non sarà modificata. Se invece l'utente non esisteva, viene creato senza password.
Attenzione però: l'opzione sql-mode del server (v. lez. 4) prevede il valore NO_AUTO_CREATE_USER fra quelli possibili. Se questo valore è attivo, non sarà possibile creare implicitamente un utente senza password con una GRANT. In questo caso l'istruzione fallirebbe, a meno che ovviamente l'utente non fosse già esistente. In questo esempio abbiamo visto che non viene assegnato il permesso GRANT, ma se l'utente lo possedeva già sarà comunque in grado di riassegnare questi permessi.
REVOKE SELECT on acquisti.* FROM luca@localhost
REVOKE ALL PRIVILEGES, GRANT OPTION FROM paolo@localhost
Con la seconda togliamo tutti i privilegi sulle tabelle più quello di GRANT a paolo@localhost. In questo caso l'utente rimarrà privo di privilegi, ma la sua utenza non viene comunque eliminata dalla tabella user.
È importante ricordare che quando si elimina un database o una tabella, tutti i permessi esistenti rimangono attivi. Ovviamente questo è influente nel caso in cui venissero ricreati oggetti con lo stesso nome.
Vediamo ora alcune altre istruzioni relative alla gestione dei permessi:
CREATE USER alberto@localhost;
CREATE USER fabio@localhost IDENTIFIED BY 'password';
DROP USER alberto@localhost;
SET PASSWORD = PASSWORD('pw');
SET PASSWORD FOR paolo@localhost = PASSWORD('pw');
La prima istruzione crea un utente senza password (in questo caso funziona anche se NO_AUTO_CREATE_USER è attivo); la seconda crea un utente con password. Tali utenti non devono essere già esistenti. La terza istruzione elimina un utente. La quarta imposta la password 'pw' per l'utente collegato; l'ultima imposta la password 'pw' per l'utente paolo@localhost.
Le prime tre istruzioni richiedono il permesso CREATE USER; la quarta è possibile per chiunque sia collegato come utente non anonimo; la quinta richiede il permesso UPDATE sul database mysql.
Vediamo ora quali sono i principali permessi che possono essere assegnati ad un utente relativamente alle tabelle e ai database, e le istruzioni che autorizzano:
Permesso | Istruzioni |
ALL | tutte esclusa GRANT |
ALTER | ALTER TABLE |
CREATE | CREATE TABLE |
CREATE TEMPORARY TABLES | CREATE TEMPORARY TABLE |
CREATE VIEW | CREATE VIEW |
DELETE | DELETE |
DROP | DROP TABLE |
INDEX | CREATE INDEX, DROP INDEX |
INSERT | INSERT |
LOCK TABLES | LOCK TABLES |
SELECT | SELECT |
SHOW VIEW | SHOW CREATE VIEW |
UPDATE | UPDATE |
USAGE | nessuna |
GRANT OPTION | GRANT, REVOKE |
Ci sono alcuni permessi di tipo amministrativo che non ha senso riferire ad un database: tali permessi si trovano infatti solo sulla tabella user. Vediamone alcuni:
Permesso | Istruzioni |
CREATE USER | CREATE USER, DROP USER, RENAME USER, REVOKE ALL PRIVILEGES |
FILE | SELECT ... INTO OUTFILE, LOAD DATA INFILE |
PROCESS | SHOW FULL PROCESSLIST |
RELOAD | FLUSH |
SHOW DATABASES | SHOW DATABASES |
SHUTDOWN | mysqladmin shutdown |
SUPER | KILL, SET GLOBAL |
SHOW DATABASES può essere utilizzata anche dagli utenti che non possiedono il permesso relativo (a meno che il server non sia stato avviato con l'opzione --skip-show-database).
Tuttavia questi non vedranno tutti i database presenti sul server, ma solo quelli per i quali possiedono diritti. In generale, comunque, gli utenti non amministrativi non dovrebbero mai possedere i permessi di quest'ultimo gruppo.
L'ultimo argomento da segnalare riguardo al sistema dei permessi è quello molto importante relativo alla memorizzazione delle password. Le password di ogni utente sono memorizzate nella colonna password della tabella user: un campo di 41 caratteri di cui il primo è un asterisco mentre i successivi 40 sono il risultato dell'algoritmo di hashing sulla password che è stata impostata con una GRANT o una CREATE USER, oppure con la funzione PASSWORD().
L'algoritmo di cifratura è monodirezionale, per cui non è possibile risalire alla password partendo dalla stringa criptata. Quando l'utente tenta di collegarsi e digita la password, il client esegue la cifratura ed invia la password criptata al server, che la confronta con quella memorizzata sul database.
Un elemento rilevante però è che l'algoritmo di cifratura attualmente utilizzato è stato introdotto con la versione 4.1 di MySQL: le versioni precedenti utilizzavano un algoritmo più semplice che produceva una stringa criptata di soli 16 caratteri. Questa situazione ha creato un problema di compatibilità che si verifica quando un client di tipo 'vecchio' (cioè di versione pre-4.1) tenta di collegarsi ad un server di tipo 'nuovo': i vecchi client infatti non sono in grado di supportare il nuovo algoritmo di hashing della password.
La conseguenza di ciò è che un client vecchio non può collegarsi ad un server nuovo se la password dell'utente che cerca di collegarsi è memorizzata col nuovo sistema. La situazione più tipica in cui ciò si verifica è l'utilizzo della vecchia estensione mysql del linguaggio PHP, molto utilizzato con MySQL. Tale estensione infatti è un client pre-4.1, e quindi non supporta il nuovo algoritmo di cifratura.
La soluzione è che un server di tipo nuovo può memorizzare password sia di un tipo che dell'altro: essendo evidente la differenza fra i due tipi di cifratura, il server è in grado di distinguerli facilmente e quindi può consentire l'accesso sia agli utenti con la vecchia password che a quelli con la nuova.
L'opzione del server --old-passwords è quella che determina quali tipi di password vengono creati dalle istruzioni GRANT, SET PASSWORD e dalla funzione PASSWORD(). Se il server viene avviato con questa opzione, le password generate saranno di tipo vecchio. Se invece l'opzione non è attiva, verranno generate password di tipo nuovo.
In sostanza quindi, per utilizzare un client di tipo vecchio su un server post-4.1, è necessario utilizzare un utente la cui password è cifrata col vecchio algoritmo.
Riassumendo:
- Sul server possono coesistere utenti con la password vecchia e utenti con la password nuova. I client di tipo nuovo possono accedere a tutte le utenze, quelli di tipo vecchio solo alle utenze con la password vecchia.
- Se il server è avviato senza opzione --old-passwords, le password vengono generate col formato nuovo. Ciò significa che i nuovi utenti creati non saranno accessibili dai vecchi client. Inoltre c'è il rischio che venga modificata la password di un utente che si collega con un client vecchio: la nuova password sarà cifrata con il nuovo algoritmo e l'utente non sarà più in grado di collegarsi. Per generare password di tipo vecchio è possibile utilizzare la funzione OLD_PASSWORD('password').
- Se il server è avviato con l'opzione --old-passwords, tutte le password verranno generate nel formato vecchio. In questo modo non verranno mai generate password lunghe, e anche quelle preesistenti, se modificate, torneranno al vecchio formato. In questo caso si mantiene la compatibilità con tutti i client, ma si perde la maggior sicurezza derivante dal nuovo algoritmo di cifratura
Evidentemente toccherà all'amministratore del database stabilire, in base alle esigenze dei propri utenti, se utilizzare o meno l'opzione --old-passwords
.