Supponiamo di voler realizzare un meccanismo semplificato per la gestione degli account utente e delle loro password. *** Esercizio 1 *** Realizzare un programma adduser che consente di aggiungere un nuovo utente al sistema. Il comando ha la seguente sintassi: adduser nome_utente password Aggiunge l'utente nome_utente al sistema e gli associa la password specificata. Ad ogni utente del sistema corrisponde una riga nel file mypasswd che, per semplicita', supponiamo essere contenuto nella cartella corrente. Ogni riga del file mypasswd ha il seguente formato: nome_utente password_cifrata Il contenuto del file mypasswd potrebbe essere, per esempio, il seguente: gino ld/J66D4A7xxA mario upwrRAf.h3BN6 furio yLpNvq1q0/aMe La password cifrata viene ottenuta usando la funzione di sistema crypt. La documentazione di crypt riporta: CRYPT(3) Linux Programmer's Manual CRYPT(3) NAME crypt, crypt_r - password and data encryption SYNOPSIS #define _XOPEN_SOURCE /* See feature_test_macros(7) */ #include char *crypt(const char *key, const char *salt); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include char *crypt_r(const char *key, const char *salt, struct crypt_data *data); Link with -lcrypt. DESCRIPTION crypt() is the password encryption function. It is based on the Data Encryption Standard algorithm with variations intended (among other things) to discourage use of hard‐ ware implementations of a key search. key is a user's typed password. salt is a two-character string chosen from the set [a-zA-Z0-9./]. This string is used to perturb the algorithm in one of 4096 different ways. By taking the lowest 7 bits of each of the first eight characters of the key, a 56-bit key is obtained. This 56-bit key is used to encrypt repeatedly a constant string (usually a string consisting of all zeros). The returned value points to the encrypted password, a series of 13 printable ASCII characters (the first two characters repre‐ sent the salt itself). The return value points to static data whose content is overwritten by each call. Warning: The key space consists of 2**56 equal 7.2e16 possible values. Exhaustive searches of this key space are possible using massively parallel computers. Software, such as crack(1), is available which will search the portion of this key space that is generally used by humans for passwords. Hence, password selection should, at mini‐ mum, avoid common words and names. The use of a passwd(1) program that checks for crackable passwords during the selection process is recommended. The DES algorithm itself has a few quirks which make the use of the crypt() interface a very poor choice for anything other than password authentication. If you are plan‐ ning on using the crypt() interface for a cryptography project, don't do it: get a good book on encryption and one of the widely available DES libraries. crypt_r() is a reentrant version of crypt(). The structure pointed to by data is used to store result data and bookkeeping information. Other than allocating it, the only thing that the caller should do with this structure is to set data->initialized to zero before the first call to crypt_r(). RETURN VALUE On success, a pointer to the encrypted password is returned. On error, NULL is returned. ... Usare man crypt per ottenere tutte le informazioni al riguardo. Quando la funzione viene invocata e' necessario fornire un valore di inizializzazione detto 'salt'. Il salt e'costituito da un array di due caratteri. Il salt viene restituito dalla funzione crypt come le prime due lettere della password cifrata. Se chiamo la funzione crypt usando salt uguale a XX, allora la password cifrata potrebbe avere la seguente forma: XXl4k.3jSc9 ^^ L'uso di un salt diverso ogni volta che viene inserito un nuovo utente consente di avere password cifrate diverse anche nel caso in cui gli utenti abbiano impostato la stessa password in chiaro. Nel seguente esempio gli utenti gino e pino hanno impostato la stessa password (abc), ma la forma cifrata e' diversa. gino bKyzDJIwTjIyQ pino ryXqDXQE5birc Nel primo caso l'algoritmo di cifratura ha usato bK come salt, nel secondo caso ha usato ry. Il programma adduser deve, in sintesi, comportarsi cosi': 1) Genera un salt casuale composto da due caratteri stampabili; per generare un valore casuale usare la funzione rand (vedere manuale: man 3 rand). 2) Cifra la password dell'utente usando il salt calcolato al punto precedente. 3) Appende al file mypasswd una riga contenente username e password cifrata (la password cifrata contiene nelle sue due prime lettere il salt). *** Esercizio 2 *** Realizzare un progrmma login che permette ad un utente di accedere al sistema. Esempio di esecuzione: $ ./login login:mario password:abc Nome utente e/o password scorretti login:mario password:qwerty Welcome mario Il programma login si comporta come segue: 1) Chiede all'utente di inserire il suo username e la sua password (che per semplicita' viene mostrata mentre l'utente la digita). 2) Controlla se nel file mypasswd e' presente una coppia username password cifrata che consente all'utente di accedere al sistema. In particolare, per quanto riguarda il punto 2, le operazioni da eseguire sono: - leggere una nuova riga e estrarre username e password cifrata; andare avanti fino che viene trovata una riga con il nome utente in questione; - prendere i primi due caratteri della password cifrata (sono il salt) - cifrare la password inserita dall'utente usando il salt appena estratto (funzione crypt) - vedere se la password inserita dall'utente e cosi' cifrata e' uguale a quella della riga corrente; se si',l'utente accede al sistema (semplicemente mostrare il messaggio "Welcome nome_utente") - se tutte le righe sono state esaminate senza successo mostrare un messaggio ("Nome utente e/o password scorretti")