|
Il protocollo SSL utilizza combinazioni di chiavi pubbliche e simmetriche. Una sessione SSL inizia con uno scambio di messaggi effettuati nella fase detta “Handshake”. Vediamola in dettaglio. Il server ha un certificato che descrive le informazioni riguardanti la società/ente/persona. I campi più rilevanti sono le informazioni di cui sopra e la chiave pubblica. Il tutto è regolato dal Certificato X.509. Tale certificato può essere garantito da una Certification Authority, la quale assicura l’esatta corrispondenza tra il certificato e colui che lo emette. Anche il client può avere un certificato, ma questo serve solo se esso deve ricevere dati sensibili da parte del server. Generalmente è il contrario. Se la connessione è iniziata dal server, esso invierà al client un messaggio “server hello”. Se è il client ad iniziare la connessione, si avrà in invio un messaggio “hello”. Analizziamo più in dettaglio tale messaggio. E’ definito dai campi: protocol version: definisce la versione SSl usata; random byte: byte casuali generati dal client; Session identifier: per verificare se si tratta di una nuova sessione o di una aperta in precedenza; Lista delle CipherSuite: è una lista in cui il Client notifica al Server gli algoritmi di crittografia supportati, ordinati in modo decrescente; Lista degli algoritmi di compressione supportati dal Client.
Il Server risponde con un messaggio “server hello” definito nel modo seguente: Protocol version: rappresenta la versione SSl scelta dal Server; Random byte: byte generati in modo casuale; Session identifier: identifica la sessione. Se non è una sessione già aperta, se ne crea una nuova; questo nel caso in cui nel tag “session identifier” del messaggio “hello” sino presenti tutti zeri; Altrimenti viene riesumata la sessione indicata dal client, se presente nella cache del server; ChiperSuite: famiglia di algoritmi di crittografia scelta dal server; Compression method: metodo di compressione scelto da server.
Dopo questo scambio di messaggi, avviene l’autenticazione tramite lo scambio di un certificato. Supponiamo che debba essere il server ad identificarsi. Questo vuol dire che i dati confidenziali transiteranno dal client al server e NON viceversa, in quanto il Client non è identificato. Tale situazione potrebbe essere, per esempio, una fase di acquisto in rete, in cui il client invia i suoi dati personali al Server, quindi è necessario che il Server sia ben identificato. Il Server dunque invia il certificato al Client, insieme alle preferenze riguardo l’algoritmo di crittografia da usare. A questo punto il client verifica che il certificato ricevuto sia valido analizzando vari aspetti. Per prima cosa la data di validità del certificato. In seguito, si verifica che la CA che garantisce il certificato (ammesso che ce ne sia una), sia una CA affidabile. Se lo è, il client recupera la chiave pubblica dalla sua lista di CA sicure per verificare la firma digitale arrivatagli con il certificato del server. Se l’informazione in tale certificato è cambiata da quando è stata firmata da una CA, o se la chiave pubblica nella lista CA non corrisponde alla chiave privata usata dalla CA per firmate il certificato del server, il client non potrà autenticare il server. Infine, il client verifica che il nome del dominio nel certificato server corrisponda allo stesso dominio del server. Questa fase conferma che il server è localizzato nello stesso indirizzo di rete che è specificato nel nome di dominio del suo certificato. Tale controllo previene attacchi del tipo “Man in the Middle”, in quanto se il domain name non corrisponde, molto probabilmente perché il certificato è stato inviato non dal server atteso, ma da una terza persona che si è intromessa. La connessione sarà rifiutata se i due nomi non corrispondono. Se invece tutto è andato a buon fine, il client avrà verificato che il server è affidabile. A questo punto il client genera una “pre master key” e la cripta con la chiave pubblica del server. Opzionalmente, in questa fase, può essere richiesta l’autenticazione del client, che è molto simile a quella vista prima, nel seguente modo: esso deve cifrare alcuni valori casuali condivisi con la sua chiave privata, creando in pratica una firma. In più, il server verifica che il client, anche se autenticato, sia autorizzato ad accedere alle risorse richieste. La chiave pubblica nel certificato del client può facilmente convalidare tale firma se il certificato è autentico, in caso contrario la sessione sarà terminata. Il server riceve il messaggio criptato e, verificata l’attendibiltà del client, lo decripta tramite la sua chiave privata. Genera poi una master secret (cosa che fa anche il client, seguendo gli stessi passi) e da questa, insieme, generano la chiave di sessione, una chiave simmetrica che sarà usata per criptare e decriptare i dati che attraversano il tunnel SSL appena creato; inoltre serve per verificare che i dati non vengano alterati nel lasso di tempo che intercorre tra l’invio e la ricezione. A questo punto il client ed il server si inviano un messaggio di notifica di HandShake concluso, e lo scambio di dati può iniziare. Vediamo come implementare il protocollo SSL con la server authentication su Axis. Sono due le cose da fare: crearsi un certificato e configurare Tomcat in modo che accetti connessioni SSL. Vediamo la prima. Posizioniamoci nella directory home di Java. Adesso creeremo un keystore per il server e lo esporteremo in un certificato chiamato server.cer. Il keystore altro non è che un repository di certificati usato per identificare il client o il server, in questo caso il server. Usiamo, per fare ciò, l’utility keytool di Java. Da console scriviamo: keytool -genkey -alias server-alias -keyalg RSA -keypass changeit -storepass changeit -keystore keystoreserver.jks ed immettiamo le informazione riguardanti il server. Successivamente: keytool -export -alias server-alias -storepass changeit -file server.cer -keystore keystoreserver.jks Il nostro certificato è pronto e possiamo visionarlo: 
Fig. 8 PROTOCOLLO SSL: breve introduzione Da notare che, giustamente, non è considerato attendibile in quanto non è stato autenticato da una Certification Authority. Scorrendo il certificato possiamo visionare anche la chiave pubblica: 
Fig. 9 PROTOCOLLO SSL: breve introduzione Il passo successivo prevede di predisporre Tomcat ad accettare connessione SSL. Apriamo il file di configurazione di Tomcat server.xml e togliamo il simbolo di commento dalle righe relative alla connessione SSL : <Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" acceptCount="100" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="JAVA_HOME\keystoreserver.jks" keystorePass="changeit" /> Adesso, scrivendo https://localhost:8443 , verrà visualizzato il certificato: 
Fig. 10 PROTOCOLLO SSL: breve introduzione Se lo accettiamo, saremo in un tunnel SSL:

Fig. 11 PROTOCOLLO SSL: breve introduzione Analizziamo adesso la mutua autenticazione SSL. Per mutua autenticazione siintende che l’autenticazione deve essere effettuata sia dal lato client che dal lato server. La cosa da fare adesso è creare, oltre al certificato del server e del client, un repository di certificati contenenti le chiavi pubbliche che chiameremo cacerts.jks. Questo file serve per verificare l’autenticazione di entrambi, nel modo visto in precedenza. Nel nostro caso, siccome il client ed il server sono la stessa macchina, il repository è uno solo. In genere però, ognuno ha il suo. Analizziamo i passi da fare. Dal Lato Server: 1) Creiamo un keystore server: keytool -genkey -alias server-alias -keyalg RSA -keypass changeit -storepass changeit -keystore keystoreserver.jks 2) Rendiamolo self-signed: keytool -selfcert -alias server-alias -keystore keystoreserver -keypass changeit -storepass changeit Ovviamente, in una situazione reale, questo passo dovrebbe essere fatto da una CA. In questo caso ci sostituiamo alla CA per continuare l’esercitazione. 3) Creiamo il file server.cer: keytool -export -alias server-alias -storepass changeit -file server.cer -keystore keystoreserver.jks 4) Importiamo il tutto nel repository cacerts.jks: keytool -import -v -trustcacerts -alias server-alias -file server.cer -keystore cacerts.jks -keypass changeit -storepass changeit Dal Lato Client: I passi sono analoghi: 1) keytool -genkey -alias client-alias -keyalg RSA -keypass changeit -storepass changeit -keystore keystoreclient.jks 2) keytool -selfcert -alias client-alias -keystore keystoreclient.jks -keypass changeit -storepass changeit 3) keytool -export -alias client-alias -storepass changeit -file client.cer -keystore keystoreclient.jks 4) keytool -import -v -trustcacerts -alias client-alias -file client.cer -keystore cacerts.jks -keypass changeit -storepass changeit In questo modo, in tutti e due i keystore, vi sono i certificati proprietari, con le rispettive chiavi private e nel cacerts.jks i certificati dell’altro, con le chiavi pubbliche, in modo da fare i confronti per provvedere all’autenticazione. Nella classe del client, dobbiamo modificare leggermente il codice per permetterle di inviare il certificato del client e di caricare successivamente il repository. Vanno aggiunte le seguenti righe: System.setProperty("javax.net.ssl.keyStore","D:\\Programmi\\Java\\jdk1.5.0_01\\jre\\bin\\keystoreclient.jks"); System.setProperty("javax.net.ssl.keyStorePassword","changeit"); System.setProperty("javax.net.ssl.trustStore","D:\\Programmi\\Java\\domains\\domain1\\config\\cacerts.jks"); System.setProperty("javax.net.ssl.trustStorePassword","changeit"); Adesso dobbiamo impostare Tomcat per fare i confronti tra certificati. Le impostazioni da fare, per quanto riguarda il file server.xml sono le stesse viste prima per la Server Authentication, con l’unica eccezione di impostare a “true” la variabile “clientauth”. Tomcat è predisposto per inviare il certificato del server. Non sa però dove cercare il repository, quindi va impostato. Dobbiamo aprire il file tomcat-users.xml ed aggiungere un username che ha ESATTAMENTE GLI STESSI PARAMETRI DI INGRESSO DEL CERTIFICATO DEL CLIENT. Sarebbero le informazioni che si sono inserite nel client.cer quando ci sono state richieste (nome, località, ecc…). Il server deve sapere questi dati perché è proprio tramite questi che analizza l’attendibilità del client. Nel nostro caso, abbiamo inserito il seguente user: <user username="CN=Client, OU=Client di Prova, O=Prova, L=Grosseto, ST=Gr, C=IT" password="changeit" roles="prova"/> Ciò, non basta. Dobbiamo impostare Tomcat affinché trovi il repository. Clicchiamo con il tasto destro sull’icona di Tomcat e selezioniamo “Configura”. Andiamo poi su “Java” e poi “Java opsions”. Aggiungiamo le seguenti impostazioni: -Djavax.net.ssl.trustStore=JAVA_HOME\bin\cacerts.jks -Djavax.net.ssl.trustStorePassword=changeit In pratica, quando Tomcat lancia la JVM, carica anche il cacerts.jks, insieme al certificato del server. 
Fig. 12 PROTOCOLLO SSL: breve introduzione Come potete osservare, dopo un lasso di tempo in cui si verifica l’autenticazione di entrambi, è possibile invocare il metodo e ricevere il risultato. Vediamo un’esempio di sicurezza sotto OC4j. Useremo, per questo esempio JDeveloper 10.1.3. Una volta creato il Web Services, dalla classe che espone il metodo, importiamo il file oraks.jks nel nostro progetto ed inseriamolo in una cartella che chiameremo META-INF, sotto la directory SRC. Tale file è un repository di certificati già presente in OC4J, utile per fare il nostro test. Adesso editiamo il file jazn-data.xml presente in OC4J_HOME\j2ee\home\config ed inseriamo lo stesso user visto in precedenza. Successivamente clicchiamo con il tasto destro sul file creato dal Web Service e selezioniamo “Secure Web Service”. Selezioniamo la caselle “Expect X.509 Certificate to Autenticate”. Seguiamo le indicazioni a video, inserendo le giuste password dove richiesto e selezionando nell’apposita schermata “Use public key to encrypt” immettendo “oracle”. Nella schermata di selezione del keystore, abilitiamo anche “Specify segnature alias” inserendo “orasign”e “Specify Encryption alias” inserendo “oraenc”. Effettuiamo il Deployment del nostro Web Services in un modo diverso da quello visto prima: Creiamo un nuovo EAR File da General\Deployment profiles. In “Application Assembly” passamogli il nostro file.deploy. In Ear Options, creiamo un nuovo gruppo chiamandolo “keys”, passandogli il file oraks.jks. Abbiamo così creato il nostro file.deploy. Con il tasto destro su di esso, facciamo il deployment nel contenitore locale OC4J. Quello che ci serve adesso è la classe client che invoca il metodo appena esposto. Creiamo un nuovo Web Service Proxy e mettiamolo in sicurezza con “Secure Proxy” tramite tasto destro. Inseriamo le stesse impostazioni messe per il server. Adesso, invocando il metodo ed usando TCP Packet monitor, è possibile vedere che il server ed il client si sono inviati i dati criptati.
|