OpenSSL
In laboratorio sono installate più versioni di OpenSSL, sia del tool che della libreria.
Tool
Quello di sistema è in /usr/bin/openssl
.
Le macchine del laboratorio possono avere una versione più recente,
compatibile con la versione di sistema, in /opt/openssl/bin/openssl
.
Questo percorso non è nel path; è comodo aggiungerlo, modificando
la variabile PATH
.
Per poter funzionare, l’eseguibile deve poter trovare la versione aggiornata
delle librerie; è necessario utilizzare la variabile d’ambiente
LD_LIBRARY_PATH
.
Per fare queste due cose, è possibile utilizzare questi comandi:
export PATH=/opt/openssl/bin:$PATH
export LD_LIBRARY_PATH=/opt/openssl/lib/
/opt/openssl
è un link simbolico che punta all’ultima versione installata,
compatibile con la versione di sistema della libreria.
Sulla macchina possono essere presenti versioni più recenti della libreria, che non sono più compatibili con la versione di sistema, ma che è comunque possibile utilizzare per compilare nuovi programmi.
Per utilizzare una versione particolare di OpenSSL, bisogna specificare
il percorso reale (/opt/openssl-x.y.z
) nelle variabili d’ambiente.
Libreria
Se compilate un programma senza specificare alcuna opzione, il vostro programma verrà linkato con la versione della libreria inclusa nella distribuzione.
In alternativa, sotto /opt
, ci sono delle versioni più aggiornate della
libreria OpenSSL.
Per poter linkare queste ultime occorre passare questi parametri in fase di compilazione:
-I/opt/openssl/include
E questi in fase di link:
-L/opt/openssl/lib -lssl -lcrypto -ldl
Oppure, per utilizzare una versione particolare di OpenSSL, bisogna
specificare il percorso completo (/opt/openssl-x.y.z
).
Esempio
Ecco un esempio realizzato con un breve file di prova e un Makefile.
Il programma di esempio è chiamato openssl-test.c
:
#include <stdio.h>
#include <openssl/ssl.h>
int main( ) {
int r;
SSL_load_error_strings();
r = SSL_library_init();
if ( r != 1 ) {
fprintf( stderr, "But the man page said: 'SSL_library_init() always returns 1'.\n" );
exit( 1 );
}
if (SSLeay() == SSLEAY_VERSION_NUMBER) {
printf("%s\n",SSLeay_version(SSLEAY_VERSION));
} else {
printf("%s (Library: %s)\n", OPENSSL_VERSION_TEXT,
SSLeay_version(SSLEAY_VERSION)
);
}
return( 0 );
}
E il relativo Makefile
:
CC=gcc -Wall
# (Normalmente dovremmo utilizzare `pkg-config --libs openssl` per ottenere
# questi parametri dinamicamente.)
LOADLIBES=-lssl -lcrypto -ldl
#LOADLIBES=-lssl -lcrypto
# Specifichiamo i parametri per utilizzare la versione sotto /opt/openssl.
# (Normalmente dovremmo utilizzare `pkg-config --cflags openssl` e
# `pkg-config --libs openssl` per ottenere questi parametri dinamicamente.)
CFLAGS=-I/opt/openssl/include
LDFLAGS=-L/opt/openssl/lib -Wl,-rpath=/opt/openssl/lib
# Parametri per una versione specifica di OpenSSL
# Attenzione alla directory lib! Con le version più recenti, si usa lib64.
#CFLAGS=-I/opt/openssl-3.0.8/include
#LDFLAGS=-L/opt/openssl-3.0.8/lib64 -Wl,-rpath=/opt/openssl-3.0.8/lib64
.PHONY: all clean
all: openssl-test openssl-test2
# Qui compiliamo con la versione installata sotto /opt/openssl,
# sfruttando le regole automatiche di GNU make.
#
# Attenzione: potrebbe essere necessario impostare la variabile
# d'ambiente LD_LIBRARY_PATH per poi eseguire il programma:
#
# export LD_LIBRARY_PATH=/opt/openssl/lib/
#
# (In teoria non serve più, da quando abbiamo aggiunto l'opzione rpath
# per il linker.)
openssl-test: openssl-test.o
openssl-test.o: openssl-test.c
# Qui compiliamo con la versione presente nella distribuzione.
openssl-test2: openssl-test2.o
${CC} $< -o $@ ${LOADLIBES}
openssl-test2.o: openssl-test.c
${CC} -c $< -o $@
clean:
rm -rf *.o openssl-test openssl-test2
Lanciando il comando make
si ottengono dal programma sorgente due eseguibili,
uno linkato con le librerie presenti nella distribuzione, e l’altro con la
versione più recente presente in /opt
.
Ecco il risultato dell’esecuzione dei due programmi ottenuti su una delle macchine del laboratorio:
lab99:~/src/openssl/test $ ./openssl-test
OpenSSL 1.1.0g 2 Nov 2017
lab99:~/src/openssl/test $ ./openssl-test2
OpenSSL 1.0.2m-fips 2 Nov 2017
L’uso dell’opzione -rpath
L’opzione -Wl,-rpath=/opt/openssl/lib
, passata al compilatore (e poi in cascata
al linker; maggiori informazioni al riguardo si possono avere lanciando il
comando info ld invocation options
) durante la compilazione del primo
programma, consente di lanciare il programma senza utilizzare la variabile
d’ambiente LD_LIBRARY_PATH
.
Senza quell’opzione, avremmo dovuto utilizzare la variabile d’ambiente, come
fatto per l’utilizzo del tool openssl
, per poter eseguire il programma.
Benché comoda in questo caso particolare, in cui vogliamo poter lanciare i due
programmi senza modificare le variabili d’ambiente, in linea generale
l’utilizzo dell’opzione -rpath
è sconsigliato, perché lega il programma a un
percorso predefinito in cui trovare la libreria. Se, ad esempio, esce una
versione 1.2 di OpenSSL, e i link in /opt
vengono aggiornati per puntare alla
nuova versione, i programmi compilati con -rpath
smetteranno di funzionare, e
saranno da ricompilare.
I programmi compilati senza -rpath
invece funzioneranno di nuovo dopo aver
aggiornato le variabili d’ambiente per puntare alla directory giusta (quella
con la versione di OpenSSL utilizzata in fase di compilazione).
Un alternativa è usare -rpath
con il percorso finale della libreria, che
comprende anche la versione di openssl (quindi non /opt/openssl/lib
, ma ad
esempio /opt/openssl-1.0.1f/lib
; a quel punto i programmi continueranno a
funzionare finché quella versione della libreria non verrà rimossa dal sistema.
Non è comunque un approccio consigliato, perché le vecchie versioni della
libreria contengono delle vulnerabilità che sono poi state corrette nelle
versioni successive.
Nell’utilizzo normale, conviene fare affidamento sulla versione presente nella distribuzione.