• Non ci sono risultati.

Capitolo 4 La sicurezza nelle griglie computazionali

5.11 Struttura di un programma GSS-API

5.11.2 Analisi del lato server

Il lato server di un'applicazione basata su GSS-API deve essenzialmente fare le seguenti operazioni:

1. Analizzare gli argomenti della linea di comando.

2. Creare un OID (Object Identifier)per un eventuale meccanismo di sicurezza specificato nella linea di comando.

5. Ricevere i messaggi che gli arrivano dal client. 6. Inviare un MIC al client.

Vediamo allora una per una le cose da fare: 1.Analizzare gli argomenti della linea di comando

I vari argomenti che potrebbero essere utili sono: il numero di porta su cui stare in ascolto, il tipo di meccanismo di sicurezza che si vuole usare (ad esempio kerberos o X.509), il nome (ftp, telnet login) del servizio offerto

2.Creare un OID per un eventuale meccanismo di sicurezza specificato nella linea di comando

Come regola generale le applicazioni che usano lo standard GSS-API non dovrebbero specificare però un particolare meccanismo di sicurezza, ma usare il meccanismo di default stabilito dall'implementazione dello standard.

3.Acquisire le credenziali

Così come il lato cliente, nemmeno l'applicazione lato server crea delle credenziali. Infatti le credenziali sono create dal meccanismo di sicurezza sottostante. Il server però al contrario del client deve acquisire le proprie credenziali esplicitamente. Alcuni clienti devono anch’essi acquisire le credenziali esplicitamente e lo fanno nello stesso modo che ora vediamo per il server. Ma generalmente l’acquisizione delle credenziali per il client avviene all’atto del login e poi ci pensa l’implementazione di GSS-API a procurarsele automaticamente.

Come visto in precedenza la funzione per acquisire le credenziali è la funzione

gss_acquire_cred(). Prima di chiamarla occorre però fare due cose. Come già detto se la struttura che contiene le credenziali contiene un campo per ogni meccanismo supportato, la funzione restituisce le credenziali per tutti questi meccanismi. Quindi la prima cosa da fare è assicurarsi che l’insieme dei meccanismi passati alla funzione gss_acquire_cred() contenga tutti quelli specificati a linea di comando. Un modo per farlo è il seguente:

5.11 Struttura di un programma GSS-API if (mechOid != GSS_C_NULL_OID) { desiredMechs = &mechOidSet; mechOidSet.count = 1; mechOidSet.elements = mechOid; } else desiredMechs = GSS_C_NULL_OID_SET;

/* GSS_C_NULL_OID_SET indica l’uso del meccanismo di default*/

Fatto questo occorre preparare il nome del server che passeremo alla funzione

gss_acquire_cred() nel formato GSS-API, e possiamo procedere in questo

modo: name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; major_status = gss_import_name(&minor_status, &name_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (major_status != GSS_S_COMPLETE) { display_status("importing name", major_status,minor_status); if (mechOid != GSS_C_NO_OID) gss_release_oid(&minor_status, &mechOid); return -1; }

Si può quindi chiamare la funzione gss_acquire_cred():

major_status = gss_acquire_cred(&minor_status, server_name, 0, desiredMechs, GSS_C_ACCEPT,

4.Accettare un contesto di sicurezza

L’operazione successiva all’acquisizione delle credenziali è l’accettare il contesto che un’applicazione lato client ha chiesto di inzializzare.

Come detto per il lato client l’operazione di stabilimento di contesto può richiedere lo scambio di più di un token è per questo che l’operazione di accettare un contesto (così come quella di stabilimento) viene effettuata in un ciclo, il cui codice potrebbe essere il seguente:

*context_handle = GSS_C_NO_CONTEXT; do { if (recv_token(s, &recv_tok) < 0) return -1; major_status = gss_accept_sec_context(&minor_status, context_handle, server_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_type, &send_tok, ret_flags, NULL, /* ignore time_rec */ NULL); // ignore del_cred_handle if (major_status!=GSS_S_COMPLETE && major_status!=GSS_S_CONTINUE_NEEDED) { display_status("accepting context", major_status, min_stat); gss_release_buffer(&minor_status, &recv_tok); return -1;

5.11 Struttura di un programma GSS-API

gss_release_buffer(&minor_status, &recv_tok);

if (send_token(s, &send_tok) < 0) {

fprintf("failure sending token\n"); return -1;

}

gss_release_buffer(&minor_status, &send_tok); }

} while (major_status == GSS_S_CONTINUE_NEEDED);

Il ciclo inizia ricercando un token che il client ci ha inviato, cosa che possiamo fare tramite una funzione recv_token():

do {

if (recv_token(s, &recv_tok) < 0) return -1;

Ricordiamo che la funzione recv_token() non è definita nello standard GSS- API ma è compito del programmatore scriverla.

Dopo la ricezione del token il ciclo continua con la chiamata alla funzione che accetta il contesto: major_status = gss_accept_sec_context(&minor_status, context_handle, server_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_type, &send_tok, ret_flags, NULL, NULL);

Ricordando che la funzione gss_accept_context() restituisce un valore positivo per la lunghezza del token se il contesto non è ancora stato stabilito,

if (send_tok.length != 0) { . . .

if (send_token(s, &send_tok) < 0) { fprintf("failure sending token\n"); return -1;

}

gss_release_buffer(&minor_status, &send_tok); }

} while (major_status == GSS_S_CONTINUE_NEEDED);

il ciclo termina quando gss_accept_context() restituisce un

major_status diverso da GSS_S_CONTINUE_NEEDED

5. Ricevere i messaggi

Dopo aver accettato il contesto si passa alla ricezione e al decifrare i messaggi che il client ha inviato al server. Quindi si chiamano in sequenza la funzione

recv_token() e la funzione gss_unwrap():

if (recv_token(s, &xmit_buf) < 0) return(-1); major_status = gss_unwrap(&minor_status, context_handle, &xmit_buf, &msg_buf, &conf_state, (gss_qop_t *) NULL); if (major_status != GSS_S_COMPLETE) { display_status("unwrapping message", major_status, minor_status); return(-1); } else if (! conf_state) {

fprintf(stderr, "Warning! Message not

encrypted.\n"); }

5.11 Struttura di un programma GSS-API

gss_release_buffer(&minor_status, &xmit_buf);

6.Inviare un MIC al client

Per assicurare il client sul fatto che il messaggio è stato ricevuto correttamente si prepara e si invia un MIC. In questo modo:

major_status = gss_get_mic(&minor_status, context_handle, GSS_C_QOP_DEFAULT, &msg_buf,

Documenti correlati