Possiamo considerare ogni fase della pipeline come una funzione che data una rappresentazione del
firewall ne produce una equivalente in un diverso dominio. In questo modo la transcompilazione pu`o
essere vista come una composizione di pi`u funzioni. Individuiamo cinque domini per la rappresentazio- ne dei firewall, ognuno corrispondente ad un diverso livello di astrazione. Ad ogni livello distinguiamo quali attributi di un firewall sono dovuti al sistema scelto e quali alla sua configurazione. Per semplifi- care la notazione, dato che abbiamo deciso di concentrarci unicamente sullo stato sNEW, nelle definizioni
omettiamo l’eventuale parametro relativo allo stato.
Livello 0 (firewall concreti): A questo livello di astrazione un sistema firewall `e rappresentato da un processo di sistema e una configurazione da un file di configurazione.
Livello 1 (firewallIFCL): Un sistema firewall `e un diagramma di controllo C, una configurazione
Σ `e una coppia composta da un insieme di rulesetIFCLρ e da un’assegnazione delle ruleset ai
nodi del diagramma c : Q → ρ.
Livello 2 (firewallIFCLnormalizzati): Un sistema firewall `e un diagramma di controllo C, una
configurazione Σ `e una coppia composta da un insieme di ruleset IFCL normalizzate ρ e da
un’assegnazione delle ruleset ai nodi del diagramma c : Q → ρ.
Livello 3 (firewall semiastratti): Un sistema firewall `e un diagramma di controllo C, una confi-
gurazione `e una funzione f : Q → P → T (P) ∪ {⊥} che assegna ad ogni nodo una funzione su
pacchetti λ : P → T (P) ∪ {⊥}.
Livello 4 (firewall astratti): Un firewall `e la sua configurazione astratta, cio`e una funzione che associa ogni pacchetto al modo in cui viene trattato λ : P → T (P) ∪ {⊥}.
Indichiamo per ogni firewall, il livello di astrazione a cui ci stiamo riferendo attraverso un pedice: F0
`e un firewall concreto, F1 `e un firewall IFCL, F2 `e un firewall IFCL normalizzato, F3 `e un firewall
semiastratto e F4`e un firewall astratto.
Abbiamo presentato i domini in ordine dal pi`u concreto al pi`u astratto. Le prime due fasi della pipeline, corrispondenti al frontend, operano traduzioni dal dominio dei firewall concreti a quello dei firewall astratti; le ultime due, corrispondenti al backend, operano nel verso opposto, dal dominio dei firewall astratti ritornano al dominio dei firewall concreti.
La funzione di traduzione dal primo al secondo livello `e la formalizzazione del linguaggio di con- figurazione. Quella che traduce dal secondo al terzo `e la normalizzazione (rimozione di CALL eGOTO e RETURN). Chiamiamo la traduzione dal terzo al quarto livello semiastrazione ed infine la traduzione dal
quarto al quinto livello composizione.
Per realizzare le ultime due fasi della pipeline occorre definire delle funzioni di traduzione nel verso opposto: dall’astratto al concreto. La funzione di traduzione dal quinto al quarto livello `e la decomposizione. Quella che traduce dal quarto al terzo `e la codifica. Chiamiamo la traduzione dal terzo al secondo livello rifattorizzazione ed infine la traduzione dal secondo al primo livello concretizzazione. Tutte le funzioni di traduzione, ad eccezione di quelle fra il primo ed il secondo livello, sono definite genericamente su ogni diagramma di controllo. Con questo approccio per estendere la teoria includendo il supporto a nuovi linguaggi `e sufficiente definirne la formalizzazione IFCL.
La figura 4.2 illustra le varie fasi della pipeline in relazione con i domini di riferimento. Assumiamo di avere un file di configurazione file.conf per il sistema source k ∈ {pf, iptables, ipfw} e di avere un sistema target k0, allora gli stadi della pipeline di configurazione possono essere formalizzati come segue:
1. formalizzazione del firewall concreto come firewall IFCL
• riceve F0= (k, file.conf)
• prende Ck definito per il sistema se questo `e supportato
• calcola Σ = f ork(file.conf)
• restituisce F1= (Ck, Σ)
2. estrazione della semantica astratta del firewall
(a) normalizzazione del firewallIFCL
• riceve F1= (Ck, Σ)
• calcola e restituisce F2=
$
F1%
(b) semiastrazione del firewall normalizzato • riceve F2= (Ck, Σn), dove Σn = (ρ, c)
• per ogni ruleset R ∈ ρ calcolaLRM
• calcola f tale che per ogni q ∈ Qk vale f (q) =Lc(q)M(sNEW)
• restituisce F3= (Ck, f )
(c) composizione del firewall astratto • riceve F3= (Ck, f )
• calcola e restituisce F4= F3
3. generazione del firewallIFCLfinale
(a) decomposizione del firewall astratto in un firewall semiastratto del tipo target • riceve F0
4= F4: P → T (P) ∪ {⊥} e k0 il sistema target
• prende Ck0 definito per il sistema se questo `e supportato
• calcola f0: Q
k0 → P → T (P) ∪ {⊥} tale che (Ck0, f0) = F40
• restituisce F0
3= (Ck0, f0)
(b) codifica del firewall IFCLnormalizzato
• riceve F0
3= (Ck0, f0)
• per ogni funzione λ ∈ Λ assegnato ai nodi da f (la definizione esatta di Λ `e {f0(q) | q ∈ Qk0}) genera una ruleset R tale che
LRM(sNEW) = λ e colleziona queste ruleset nell’insieme ρ0
• calcola c0 : Qk0 → ρ0 tale che per ogni q ∈ Qk0 vale
Lc
0(q)
M(sNEW) = f0(q)
• restituisce F0
2= (Ck0, Σ0), dove Σ0 = (ρ0, c0)
(c) rifattorizzazione del firewallIFCL normalizzato in un generico firewallIFCL
• riceve F0
2= (Ck0, Σ0)
• calcola una nuova configurazione Σ0
r tale che
$
(Ck0, Σr0)%
= (Ck0, Σ0)• restituisce F0
1= (Ck0, Σ0r)
4. concretizzazione del firewallIFCLin un firewall concreto
• riceve F0
1= (Ck0, Σ0r)
• calcola file.conf0 = con
k0(Ck0, Σ0r)
Dove nei passi 2.c e 3.a abbiamo usato la funzione di composizione , che dato un firewall semiastratto restituisce il firewall astratto ottenuto componendo le funzioni associate ai nodi secondo la semantica denotazionale. Vale che (Ck, f ) = L(Ck, Σ)M(sNEW), con Σ = (ρ, c) se per ogni q ∈ Qk vale f (q) = Lc(q)M(sNEW)
1.
Formalmente la funzione , per un firewall semiastratto F = (C, f ), `e definita come F∅(qi). Dove
la funzione FI (q) per un dato insieme di nodi I, `e definita per ogni q ∈ Q, q 6= qf come:
FI (q) (p) = F I∪{q}(q 0) (p0 ) n t se t 6= ⊥ ∧ q0∈ I/ ⊥ altrimenti dove t = f (q)(p) e se t 6= ⊥ allora p0= t(p) e q0 = δ(q, p0)
e per il nodo finale come:
FI (qf) (p) = id
La funzione conk `e la funzione di concretizzazione del sistema k che data una configurazione IF-
CLΣ restituisce un file di configurazione file.conf nel linguaggio di configurazione di k. Questa `e concettualmente la funzione inversa della funzione di formalizzazione f ork, tuttavia `e bene osservare
che non `e necessariamente l’inversa dal punto di vista funzionale. Infatti la formalizzazione delle con- figurazioni prodotta dalla funzione f ork ha spesso una forma molto particolare (si prenda ad esempio
quella di ipfw presentata nella sezione 2.2.3); non vogliamo limitarci alla possibilit`a di concretizzare solo configurazioniIFCLaventi una struttura cos`ı particolare. L’idea `e quella di definire una funzione
che per ogni configurazione IFCL per il diagramma di controllo del sistema k restituisca una confi-
gurazione nel linguaggio target “il pi`u simile possibile”; esprimiamo questo concetto dicendo che la normalizzazione del firewallIFCLe di quello ottenuto applicando conk e poi formalizzando di nuovo,
devono essere uguali:
$
(Ck, Σ)%
=$
(Ck, f ork(file.conf))%
. La forma di queste funzioni sar`adescritta in maggior dettaglio nel capitolo 7.
In questa trattazione trascuriamo la fase di rifattorizzazione, assumendo che il firewall restituito da questa fase sia sempre quello ottenuto in input dello stadio di codifica (Σ0r = Σ0). Si ricordi che `e banalmente vero che ogni firewall normalizzato `e anche un firewall IFCL. Inoltre, come gi`a annunciato, abbiamo trascurato il comportamento dei pacchetti appartenenti a connessioni stabilite, concentrandoci unicamente sullo stato sNEW.
Teorema 5 (Correttezza della pipeline). Sia file.conf un firewall concreto in uno qualunque dei sistemi k ∈ {iptables, ipfw, pf}. Il firewall target file.conf0 prodotto dalla pipeline di transcompi- lazione, per il sistema target k0, ha la stessa semantica del firewall source per quanto riguarda pacchetti non appartenenti a connessioni stabilite. Formalmente vale:
L
$
(Ck, f ork(file.conf))%
M(sNEW) ≡L$
(Ck0, f ork0(file.conf0))