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.