2004-08-11 10:51:17 +01:00
|
|
|
/**
|
2004-08-18 16:46:33 +01:00
|
|
|
*
|
2004-08-11 10:51:17 +01:00
|
|
|
*@file arachne.c
|
|
|
|
*
|
|
|
|
* Introduces a method for proofs akin to the Athena modelchecker
|
|
|
|
* http://www.ece.cmu.edu/~dawnsong/athena/
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-08-27 19:09:09 +01:00
|
|
|
#include <limits.h>
|
2004-08-11 13:08:10 +01:00
|
|
|
#include "term.h"
|
2004-08-11 15:09:12 +01:00
|
|
|
#include "termlist.h"
|
2004-08-11 13:08:10 +01:00
|
|
|
#include "role.h"
|
2004-08-11 10:51:17 +01:00
|
|
|
#include "system.h"
|
2004-08-15 17:44:54 +01:00
|
|
|
#include "knowledge.h"
|
2004-08-12 13:28:57 +01:00
|
|
|
#include "compiler.h"
|
2004-08-11 15:09:12 +01:00
|
|
|
#include "states.h"
|
|
|
|
#include "mgu.h"
|
2004-08-11 10:51:17 +01:00
|
|
|
#include "arachne.h"
|
2004-10-25 15:28:53 +01:00
|
|
|
#include "memory.h"
|
2004-08-14 16:59:14 +01:00
|
|
|
#include "error.h"
|
|
|
|
#include "claim.h"
|
2004-08-14 17:12:32 +01:00
|
|
|
#include "debug.h"
|
2004-08-15 13:24:27 +01:00
|
|
|
#include "binding.h"
|
2004-08-28 14:47:37 +01:00
|
|
|
#include "warshall.h"
|
2004-08-11 10:51:17 +01:00
|
|
|
|
2004-08-15 15:07:34 +01:00
|
|
|
extern Term CLAIM_Secret;
|
|
|
|
extern Term CLAIM_Nisynch;
|
|
|
|
extern Term CLAIM_Niagree;
|
2004-08-15 17:44:54 +01:00
|
|
|
extern Term TERM_Agent;
|
2004-08-18 20:43:58 +01:00
|
|
|
extern Term TERM_Hidden;
|
2004-08-20 12:47:00 +01:00
|
|
|
extern Term TERM_Function;
|
2004-08-14 20:19:23 +01:00
|
|
|
|
2004-08-28 14:47:37 +01:00
|
|
|
extern int *graph;
|
|
|
|
extern int nodes;
|
|
|
|
|
2004-08-11 15:09:12 +01:00
|
|
|
static System sys;
|
2004-08-18 21:22:33 +01:00
|
|
|
static Claimlist current_claim;
|
2004-08-27 19:09:09 +01:00
|
|
|
static int attack_length;
|
2004-08-18 21:22:33 +01:00
|
|
|
|
2004-08-12 13:28:57 +01:00
|
|
|
Protocol INTRUDER; // Pointers, to be set by the Init
|
2004-08-17 12:30:03 +01:00
|
|
|
Role I_M; // Same here.
|
|
|
|
Role I_F;
|
|
|
|
Role I_T;
|
|
|
|
Role I_V;
|
|
|
|
Role I_R;
|
|
|
|
Role I_E;
|
|
|
|
Role I_D;
|
2004-08-18 16:46:33 +01:00
|
|
|
Role I_RRS;
|
2004-08-11 13:08:10 +01:00
|
|
|
|
2004-08-13 12:11:59 +01:00
|
|
|
static int indentDepth;
|
2004-10-14 16:25:28 +01:00
|
|
|
static int proofDepth;
|
2004-08-18 15:06:14 +01:00
|
|
|
static int max_encryption_level;
|
2004-08-19 13:47:53 +01:00
|
|
|
static int num_regular_runs;
|
|
|
|
static int num_intruder_runs;
|
2004-08-13 12:11:59 +01:00
|
|
|
|
2004-08-11 13:08:10 +01:00
|
|
|
struct goalstruct
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
int index;
|
2004-08-11 15:09:12 +01:00
|
|
|
Roledef rd;
|
2004-08-11 13:08:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct goalstruct Goal;
|
|
|
|
|
2004-08-11 15:09:12 +01:00
|
|
|
/**
|
|
|
|
* Forward declarations
|
|
|
|
*/
|
|
|
|
|
|
|
|
int iterate ();
|
2004-10-18 14:04:34 +01:00
|
|
|
void printSemiState ();
|
2004-08-11 15:09:12 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Program code
|
|
|
|
*/
|
|
|
|
|
2004-08-11 12:22:20 +01:00
|
|
|
//! Init Arachne engine
|
|
|
|
void
|
2004-08-11 15:09:12 +01:00
|
|
|
arachneInit (const System mysys)
|
2004-08-11 12:22:20 +01:00
|
|
|
{
|
2004-08-18 15:06:14 +01:00
|
|
|
Term GVT;
|
2004-08-12 12:55:03 +01:00
|
|
|
Roledef rd = NULL;
|
2004-08-15 17:44:54 +01:00
|
|
|
Termlist tl, know0;
|
2004-08-12 12:55:03 +01:00
|
|
|
|
|
|
|
void add_event (int event, Term message)
|
2004-08-12 13:28:57 +01:00
|
|
|
{
|
|
|
|
rd = roledefAdd (rd, event, NULL, NULL, NULL, message, NULL);
|
|
|
|
}
|
|
|
|
Role add_role (const char *rolenamestring)
|
|
|
|
{
|
|
|
|
Role r;
|
|
|
|
Term rolename;
|
|
|
|
|
|
|
|
rolename = makeGlobalConstant (rolenamestring);
|
|
|
|
r = roleCreate (rolename);
|
|
|
|
r->roledef = rd;
|
|
|
|
rd = NULL;
|
|
|
|
r->next = INTRUDER->roles;
|
|
|
|
INTRUDER->roles = r;
|
2004-08-12 14:22:49 +01:00
|
|
|
// compute_role_variables (sys, INTRUDER, r);
|
2004-08-12 13:28:57 +01:00
|
|
|
return r;
|
|
|
|
}
|
2004-08-12 12:55:03 +01:00
|
|
|
|
2004-08-11 15:09:12 +01:00
|
|
|
sys = mysys; // make sys available for this module as a global
|
2004-08-14 15:23:21 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Very important: turn role terms that are local to a run, into variables.
|
|
|
|
*/
|
|
|
|
term_rolelocals_are_variables ();
|
|
|
|
|
2004-08-11 12:22:20 +01:00
|
|
|
/*
|
|
|
|
* Add intruder protocol roles
|
|
|
|
*/
|
2004-08-12 12:55:03 +01:00
|
|
|
|
|
|
|
INTRUDER = protocolCreate (makeGlobalConstant (" INTRUDER "));
|
2004-08-18 15:06:14 +01:00
|
|
|
GVT = makeGlobalVariable ("GlobalVariable");
|
2004-08-12 12:55:03 +01:00
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
add_event (SEND, GVT);
|
2004-08-17 12:30:03 +01:00
|
|
|
I_M = add_role ("I_M: Atomic message");
|
2004-08-12 12:55:03 +01:00
|
|
|
|
2004-08-17 12:30:03 +01:00
|
|
|
add_event (READ, NULL);
|
|
|
|
add_event (READ, NULL);
|
2004-08-16 15:49:41 +01:00
|
|
|
add_event (SEND, NULL);
|
2004-08-19 15:49:03 +01:00
|
|
|
I_RRS = add_role ("I_E: Encrypt");
|
2004-08-16 15:49:41 +01:00
|
|
|
|
2004-08-11 12:22:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Close Arachne engine
|
|
|
|
void
|
2004-08-11 15:09:12 +01:00
|
|
|
arachneDone ()
|
2004-08-11 12:22:20 +01:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-08-11 13:08:10 +01:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Detail
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*
|
|
|
|
* runs[rid].step is now the number of 'valid' events within the run, but we
|
|
|
|
* call it 'length' here.
|
|
|
|
*/
|
|
|
|
#define INVALID -1
|
2004-08-11 15:09:12 +01:00
|
|
|
#define isGoal(rd) (rd->type == READ && !rd->internal)
|
2004-08-15 13:24:27 +01:00
|
|
|
#define isBound(rd) (rd->bound)
|
2004-08-11 13:08:10 +01:00
|
|
|
#define length step
|
|
|
|
|
2004-08-12 12:35:13 +01:00
|
|
|
//! Indent print
|
|
|
|
void
|
|
|
|
indentPrint ()
|
|
|
|
{
|
2004-10-18 14:04:34 +01:00
|
|
|
if (sys->output == ATTACK && globalError == 0)
|
2004-08-19 11:46:27 +01:00
|
|
|
{
|
2004-10-18 14:04:34 +01:00
|
|
|
// Arachne, attack, not an error
|
|
|
|
// We assume that means DOT output
|
|
|
|
eprintf ("// ");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If it is not to stdout, or it is not an attack...
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < indentDepth; i++)
|
|
|
|
{
|
|
|
|
if (i % 3 == 0)
|
|
|
|
eprintf ("|");
|
|
|
|
else
|
|
|
|
eprintf (" ");
|
|
|
|
eprintf (" ");
|
|
|
|
}
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
2004-08-13 11:50:56 +01:00
|
|
|
}
|
2004-08-12 12:35:13 +01:00
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
//! Print indented binding
|
|
|
|
void
|
2004-08-20 12:47:00 +01:00
|
|
|
binding_indent_print (const Binding b, const int flag)
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
if (flag)
|
|
|
|
eprintf ("!! ");
|
|
|
|
binding_print (b);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
|
|
|
|
2004-08-20 12:47:00 +01:00
|
|
|
//! Determine whether a term is a functor
|
|
|
|
int
|
|
|
|
isTermFunctionName (Term t)
|
|
|
|
{
|
|
|
|
t = deVar (t);
|
2004-08-31 13:35:05 +01:00
|
|
|
if (t != NULL && isTermLeaf(t) && t->stype != NULL && inTermlist (t->stype, TERM_Function))
|
2004-08-27 18:35:23 +01:00
|
|
|
return 1;
|
2004-08-20 12:47:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Determine whether a term is a function application. Returns the function term.
|
|
|
|
Term
|
|
|
|
getTermFunction (Term t)
|
|
|
|
{
|
|
|
|
t = deVar (t);
|
|
|
|
if (t != NULL)
|
|
|
|
{
|
2004-11-16 12:06:36 +00:00
|
|
|
if (realTermEncrypt (t) && isTermFunctionName (TermKey(t)))
|
2004-08-20 12:47:00 +01:00
|
|
|
{
|
2004-11-16 12:06:36 +00:00
|
|
|
return TermKey(t);
|
2004-08-20 12:47:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-08-19 13:47:53 +01:00
|
|
|
//! Wrapper for roleInstance
|
|
|
|
/**
|
|
|
|
*@return Returns the run number
|
|
|
|
*/
|
2004-08-19 14:09:35 +01:00
|
|
|
int
|
|
|
|
semiRunCreate (const Protocol p, const Role r)
|
2004-08-19 13:47:53 +01:00
|
|
|
{
|
|
|
|
int run;
|
|
|
|
|
|
|
|
if (p == INTRUDER)
|
2004-08-19 14:09:35 +01:00
|
|
|
num_intruder_runs++;
|
2004-08-19 13:47:53 +01:00
|
|
|
else
|
2004-08-19 14:09:35 +01:00
|
|
|
num_regular_runs++;
|
2004-08-19 13:47:53 +01:00
|
|
|
roleInstance (sys, p, r, NULL, NULL);
|
2004-08-19 15:55:21 +01:00
|
|
|
run = sys->maxruns - 1;
|
2004-08-19 13:47:53 +01:00
|
|
|
sys->runs[run].length = 0;
|
|
|
|
return run;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Wrapper for roleDestroy
|
2004-08-19 14:09:35 +01:00
|
|
|
void
|
|
|
|
semiRunDestroy ()
|
2004-08-19 13:47:53 +01:00
|
|
|
{
|
2004-08-19 15:49:03 +01:00
|
|
|
if (sys->maxruns > 0)
|
|
|
|
{
|
|
|
|
Protocol p;
|
2004-08-19 13:47:53 +01:00
|
|
|
|
2004-08-19 15:49:03 +01:00
|
|
|
p = sys->runs[sys->maxruns - 1].protocol;
|
|
|
|
roleInstanceDestroy (sys);
|
|
|
|
if (p == INTRUDER)
|
|
|
|
num_intruder_runs--;
|
|
|
|
else
|
|
|
|
num_regular_runs--;
|
|
|
|
}
|
2004-08-19 13:47:53 +01:00
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
|
2004-08-17 16:52:52 +01:00
|
|
|
//! After a role instance, or an extension of a run, we might need to add some goals
|
|
|
|
/**
|
|
|
|
* From old to new. Sets the new length to new.
|
|
|
|
*@returns The number of goals added (for destructions)
|
|
|
|
*/
|
|
|
|
int
|
2004-08-18 15:06:14 +01:00
|
|
|
add_read_goals (const int run, const int old, const int new)
|
2004-08-17 16:52:52 +01:00
|
|
|
{
|
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
Roledef rd;
|
|
|
|
|
|
|
|
sys->runs[run].length = new;
|
|
|
|
i = old;
|
2004-08-18 10:57:01 +01:00
|
|
|
rd = roledef_shift (sys->runs[run].start, i);
|
2004-08-18 15:06:14 +01:00
|
|
|
count = 0;
|
|
|
|
while (i < new && rd != NULL)
|
2004-08-17 16:52:52 +01:00
|
|
|
{
|
|
|
|
if (rd->type == READ)
|
|
|
|
{
|
2004-08-19 11:46:27 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
if (count == 0)
|
|
|
|
{
|
2004-08-19 12:37:41 +01:00
|
|
|
indentPrint ();
|
2004-08-19 13:35:51 +01:00
|
|
|
eprintf ("Thus, we must also produce ");
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eprintf (", ");
|
|
|
|
}
|
|
|
|
termPrint (rd->message);
|
2004-08-19 12:37:41 +01:00
|
|
|
}
|
2004-10-18 14:04:34 +01:00
|
|
|
count = count + goal_add (rd->message, run, i, 0);
|
2004-08-17 16:52:52 +01:00
|
|
|
}
|
|
|
|
rd = rd->next;
|
|
|
|
i++;
|
|
|
|
}
|
2004-08-19 11:46:27 +01:00
|
|
|
if ((count > 0) && sys->output == PROOF)
|
|
|
|
{
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
2004-08-17 16:52:52 +01:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2004-08-14 15:23:21 +01:00
|
|
|
//! Determine the run that follows from a substitution.
|
|
|
|
/**
|
|
|
|
* After an Arachne unification, stuff might go wrong w.r.t. nonce instantiation.
|
|
|
|
* This function determines the run that is implied by a substitution list.
|
|
|
|
* @returns >= 0: a run, -1 for invalid, -2 for any run.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
determine_unification_run (Termlist tl)
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
|
|
|
|
run = -2;
|
|
|
|
while (tl != NULL)
|
|
|
|
{
|
|
|
|
//! Again, hardcoded reference to compiler.c. Level -3 means a local constant for a role.
|
2004-11-16 12:06:36 +00:00
|
|
|
if (tl->term->type != VARIABLE && TermRunid(tl->term) == -3)
|
2004-08-14 15:23:21 +01:00
|
|
|
{
|
|
|
|
Term t;
|
|
|
|
|
|
|
|
t = tl->term->subst;
|
|
|
|
|
|
|
|
// It is required that it is actually a leaf, because we construct it.
|
|
|
|
if (!realTermLeaf (t))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (run == -2)
|
|
|
|
{
|
|
|
|
// Any run
|
2004-11-16 12:06:36 +00:00
|
|
|
run = TermRunid(t);
|
2004-08-14 15:23:21 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Specific run: compare
|
2004-11-16 12:06:36 +00:00
|
|
|
if (run != TermRunid(t))
|
2004-08-14 15:23:21 +01:00
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tl = tl->next;
|
|
|
|
}
|
|
|
|
return run;
|
|
|
|
}
|
|
|
|
|
2004-08-27 19:09:09 +01:00
|
|
|
//! Determine trace length
|
|
|
|
int
|
|
|
|
get_trace_length ()
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
int length;
|
|
|
|
|
|
|
|
run = 0;
|
|
|
|
length = 0;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
|
|
|
if (sys->runs[run].protocol != INTRUDER)
|
|
|
|
{
|
|
|
|
// Non-intruder run: count length
|
2004-08-27 20:15:24 +01:00
|
|
|
// Subtract 'firstReal' to ignore chooses.
|
|
|
|
length = length + sys->runs[run].length - sys->runs[run].firstReal;
|
2004-08-27 19:09:09 +01:00
|
|
|
}
|
|
|
|
run++;
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Proof reporting
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//! Protocol/role name of a run
|
|
|
|
void
|
|
|
|
role_name_print (const int run)
|
|
|
|
{
|
|
|
|
eprintf ("protocol ");
|
|
|
|
termPrint (sys->runs[run].protocol->nameterm);
|
|
|
|
eprintf (", role ");
|
|
|
|
termPrint (sys->runs[run].role->nameterm);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Adding a run/extending a run
|
|
|
|
void
|
|
|
|
proof_suppose_run (const int run, const int oldlength, const int newlength)
|
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
int reallength;
|
|
|
|
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Suppose ");
|
|
|
|
if (oldlength == 0)
|
|
|
|
eprintf ("there is a ");
|
|
|
|
else
|
|
|
|
eprintf ("we extend ");
|
|
|
|
reallength = roledef_length (sys->runs[run].start);
|
|
|
|
if (reallength > newlength)
|
|
|
|
eprintf ("semi-");
|
|
|
|
eprintf ("run #%i of ", run);
|
|
|
|
role_name_print (run);
|
|
|
|
if (reallength > newlength)
|
|
|
|
{
|
|
|
|
if (oldlength == 0)
|
|
|
|
eprintf (" of");
|
|
|
|
else
|
|
|
|
eprintf (" to");
|
2004-08-19 15:52:17 +01:00
|
|
|
eprintf (" length %i", newlength);
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Select a goal
|
|
|
|
void
|
|
|
|
proof_select_goal (Binding b)
|
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
|
|
|
|
rd = roledef_shift (sys->runs[b->run_to].start, b->ev_to);
|
|
|
|
indentPrint ();
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf ("Selected goal: Where does term ");
|
2004-08-19 11:46:27 +01:00
|
|
|
termPrint (b->term);
|
2004-08-19 15:55:21 +01:00
|
|
|
eprintf (" occur first as an interm?\n");
|
2004-08-19 12:37:41 +01:00
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* It is required for ");
|
2004-08-19 11:46:27 +01:00
|
|
|
roledefPrint (rd);
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf (" at index %i in run %i\n", b->ev_to, b->run_to);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Cannot bind because of cycle
|
|
|
|
void
|
|
|
|
proof_cannot_bind (const Binding b, const int run, const int index)
|
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf
|
|
|
|
("Cannot bind this to run %i, index %i because that introduces a cycle.\n",
|
|
|
|
run, index);
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Test a binding
|
|
|
|
void
|
|
|
|
proof_suppose_binding (Binding b)
|
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
|
|
|
|
indentPrint ();
|
|
|
|
rd = roledef_shift (sys->runs[b->run_from].start, b->ev_from);
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf ("Suppose it originates in run %i, at index %i\n", b->run_from,
|
|
|
|
b->ev_from);
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* I.e. event ");
|
2004-08-19 11:46:27 +01:00
|
|
|
roledefPrint (rd);
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf ("\n");
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* from ");
|
2004-08-19 11:46:27 +01:00
|
|
|
role_name_print (b->run_from);
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf ("\n");
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-11 13:08:10 +01:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Sub
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
2004-08-11 15:09:12 +01:00
|
|
|
//! Iterate over all send types in the roles (including the intruder ones)
|
|
|
|
/**
|
|
|
|
* Function is called with (protocol pointer, role pointer, roledef pointer, index)
|
|
|
|
* and returns an integer. If it is false, iteration aborts.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
iterate_role_sends (int (*func) ())
|
|
|
|
{
|
|
|
|
Protocol p;
|
|
|
|
|
|
|
|
p = sys->protocols;
|
|
|
|
while (p != NULL)
|
|
|
|
{
|
|
|
|
Role r;
|
|
|
|
|
|
|
|
r = p->roles;
|
|
|
|
while (r != NULL)
|
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
rd = r->roledef;
|
|
|
|
index = 0;
|
|
|
|
while (rd != NULL)
|
|
|
|
{
|
|
|
|
if (rd->type == SEND)
|
|
|
|
{
|
2004-08-12 13:37:30 +01:00
|
|
|
if (!func (p, r, rd, index))
|
2004-08-11 15:09:12 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
rd = rd->next;
|
|
|
|
}
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-16 10:50:37 +01:00
|
|
|
//! Try to bind a specific existing run to a goal.
|
2004-08-15 20:58:26 +01:00
|
|
|
/**
|
2004-08-16 10:50:37 +01:00
|
|
|
* The key goals are bound to the goal.
|
|
|
|
*@param subterm determines whether it is a subterm unification or not.
|
2004-08-15 20:58:26 +01:00
|
|
|
*/
|
2004-08-11 15:09:12 +01:00
|
|
|
int
|
2004-08-18 20:43:58 +01:00
|
|
|
bind_existing_to_goal (const Binding b, const int run, const int index)
|
2004-08-16 10:50:37 +01:00
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
int flag;
|
2004-08-16 14:18:04 +01:00
|
|
|
int old_length;
|
2004-08-18 10:57:01 +01:00
|
|
|
int newgoals;
|
2004-08-19 13:35:51 +01:00
|
|
|
int found;
|
2004-08-16 10:50:37 +01:00
|
|
|
|
|
|
|
int subterm_iterate (Termlist substlist, Termlist keylist)
|
|
|
|
{
|
|
|
|
int flag;
|
|
|
|
|
2004-08-19 13:35:51 +01:00
|
|
|
found++;
|
2004-08-16 10:50:37 +01:00
|
|
|
flag = 1;
|
2004-08-30 14:57:16 +01:00
|
|
|
/**
|
|
|
|
* Now create the new bindings
|
|
|
|
*/
|
2004-08-18 15:06:14 +01:00
|
|
|
if (goal_bind (b, run, index))
|
2004-08-16 10:50:37 +01:00
|
|
|
{
|
2004-10-18 14:04:34 +01:00
|
|
|
int newgoals;
|
2004-08-18 15:06:14 +01:00
|
|
|
Termlist tl;
|
2004-08-16 14:18:04 +01:00
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
proof_suppose_binding (b);
|
|
|
|
if (keylist != NULL && sys->output == PROOF)
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf
|
2004-08-19 13:35:51 +01:00
|
|
|
("This introduces the obligation to produce the following keys: ");
|
2004-08-18 15:06:14 +01:00
|
|
|
termlistPrint (keylist);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
2004-10-18 14:04:34 +01:00
|
|
|
newgoals = 0;
|
2004-08-18 15:06:14 +01:00
|
|
|
tl = keylist;
|
|
|
|
while (tl != NULL)
|
|
|
|
{
|
|
|
|
int keyrun;
|
2004-10-14 16:09:48 +01:00
|
|
|
int prioritylevel;
|
|
|
|
|
|
|
|
/* normally, a key gets higher priority */
|
|
|
|
prioritylevel = 1;
|
|
|
|
if (realTermEncrypt (tl->term))
|
|
|
|
{
|
|
|
|
/* the key is a construction itself */
|
2004-11-16 12:06:36 +00:00
|
|
|
if (inKnowledge (sys->know, TermKey(tl->term)))
|
2004-10-14 16:09:48 +01:00
|
|
|
{
|
|
|
|
/* the key is constructed by a public thing */
|
|
|
|
/* typically, this is a public key, so we postpone it */
|
|
|
|
prioritylevel = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* add the key as a goal */
|
2004-10-18 14:04:34 +01:00
|
|
|
newgoals = newgoals + goal_add (tl->term, b->run_to, b->ev_to, prioritylevel);
|
2004-08-18 15:06:14 +01:00
|
|
|
tl = tl->next;
|
|
|
|
}
|
|
|
|
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth++;
|
2004-08-18 15:06:14 +01:00
|
|
|
flag = flag && iterate ();
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth--;
|
2004-08-18 15:06:14 +01:00
|
|
|
|
2004-10-18 14:04:34 +01:00
|
|
|
goal_remove_last (newgoals);
|
2004-08-16 10:50:37 +01:00
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
else
|
2004-08-16 10:50:37 +01:00
|
|
|
{
|
2004-08-19 12:37:41 +01:00
|
|
|
proof_cannot_bind (b, run, index);
|
2004-08-16 10:50:37 +01:00
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
goal_unbind (b);
|
2004-08-16 10:50:37 +01:00
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
2004-08-16 14:18:04 +01:00
|
|
|
//----------------------------
|
2004-08-16 10:50:37 +01:00
|
|
|
// Roledef entry
|
|
|
|
rd = roledef_shift (sys->runs[run].start, index);
|
|
|
|
|
2004-08-16 14:18:04 +01:00
|
|
|
// Fix length
|
|
|
|
old_length = sys->runs[run].length;
|
|
|
|
if ((index + 1) > old_length)
|
2004-08-18 15:06:14 +01:00
|
|
|
newgoals = add_read_goals (run, old_length, index + 1);
|
2004-08-18 10:57:01 +01:00
|
|
|
else
|
2004-08-18 15:06:14 +01:00
|
|
|
newgoals = 0;
|
2004-08-16 14:18:04 +01:00
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
// Bind to existing run
|
2004-08-19 13:35:51 +01:00
|
|
|
found = 0;
|
2004-08-18 15:06:14 +01:00
|
|
|
flag = termMguSubTerm (b->term, rd->message,
|
|
|
|
subterm_iterate, sys->know->inverses, NULL);
|
2004-08-19 13:35:51 +01:00
|
|
|
// Did it work?
|
|
|
|
if (found == 0 && sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Cannot bind ");
|
|
|
|
termPrint (b->term);
|
2004-08-19 14:09:35 +01:00
|
|
|
eprintf (" to run %i, index %i because it does not subterm-unify.\n",
|
|
|
|
run, index);
|
2004-08-19 13:35:51 +01:00
|
|
|
}
|
2004-08-16 14:18:04 +01:00
|
|
|
// Reset length
|
2004-10-18 14:04:34 +01:00
|
|
|
goal_remove_last (newgoals);
|
2004-08-16 14:18:04 +01:00
|
|
|
sys->runs[run].length = old_length;
|
|
|
|
return flag;
|
2004-08-16 10:50:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Bind a goal to an existing regular run, if possible
|
|
|
|
int
|
2004-08-18 10:57:01 +01:00
|
|
|
bind_existing_run (const Binding b, const Protocol p, const Role r,
|
2004-08-18 20:43:58 +01:00
|
|
|
const int index)
|
2004-08-11 15:09:12 +01:00
|
|
|
{
|
|
|
|
int run, flag;
|
2004-08-19 12:37:41 +01:00
|
|
|
int found;
|
2004-08-11 15:09:12 +01:00
|
|
|
|
|
|
|
flag = 1;
|
2004-08-19 12:37:41 +01:00
|
|
|
found = 0;
|
2004-08-11 15:09:12 +01:00
|
|
|
for (run = 0; run < sys->maxruns; run++)
|
|
|
|
{
|
2004-08-16 14:18:04 +01:00
|
|
|
if (sys->runs[run].protocol == p && sys->runs[run].role == r)
|
|
|
|
{
|
2004-08-19 12:37:41 +01:00
|
|
|
found++;
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
if (found == 1)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Can we bind it to an existing regular run of ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf ("?\n");
|
|
|
|
}
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("%i. Can we bind it to run %i?\n", found, run);
|
|
|
|
}
|
|
|
|
indentDepth++;
|
2004-08-18 20:43:58 +01:00
|
|
|
flag = flag && bind_existing_to_goal (b, run, index);
|
2004-08-19 12:37:41 +01:00
|
|
|
indentDepth--;
|
2004-08-16 14:18:04 +01:00
|
|
|
}
|
2004-08-11 15:09:12 +01:00
|
|
|
}
|
2004-08-19 12:37:41 +01:00
|
|
|
if (sys->output == PROOF && found == 0)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("There is no existing run for ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
2004-08-11 15:09:12 +01:00
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Bind a goal to a new run
|
|
|
|
int
|
2004-08-18 10:57:01 +01:00
|
|
|
bind_new_run (const Binding b, const Protocol p, const Role r,
|
2004-08-18 20:43:58 +01:00
|
|
|
const int index)
|
2004-08-11 15:09:12 +01:00
|
|
|
{
|
2004-08-11 16:05:13 +01:00
|
|
|
int run;
|
|
|
|
int flag;
|
2004-08-18 10:57:01 +01:00
|
|
|
int newgoals;
|
2004-08-11 16:05:13 +01:00
|
|
|
|
2004-08-19 13:47:53 +01:00
|
|
|
run = semiRunCreate (p, r);
|
2004-08-19 12:37:41 +01:00
|
|
|
proof_suppose_run (run, 0, index + 1);
|
2004-08-18 15:06:14 +01:00
|
|
|
newgoals = add_read_goals (run, 0, index + 1);
|
2004-08-19 12:37:41 +01:00
|
|
|
indentDepth++;
|
2004-08-18 20:43:58 +01:00
|
|
|
flag = bind_existing_to_goal (b, run, index);
|
2004-08-19 12:37:41 +01:00
|
|
|
indentDepth--;
|
2004-10-18 14:04:34 +01:00
|
|
|
goal_remove_last (newgoals);
|
2004-08-19 13:47:53 +01:00
|
|
|
semiRunDestroy ();
|
2004-08-11 16:05:13 +01:00
|
|
|
return flag;
|
2004-08-11 15:09:12 +01:00
|
|
|
}
|
|
|
|
|
2004-08-28 10:24:30 +01:00
|
|
|
//! Display the current semistate using dot output format.
|
|
|
|
void
|
|
|
|
dotSemiState ()
|
|
|
|
{
|
|
|
|
static int attack_number = 0;
|
|
|
|
int run;
|
|
|
|
Protocol p;
|
2004-10-25 15:28:53 +01:00
|
|
|
int *ranks;
|
|
|
|
int maxrank;
|
2004-08-28 10:24:30 +01:00
|
|
|
|
2004-08-28 12:43:06 +01:00
|
|
|
void node (const int run, const int index)
|
2004-08-28 10:24:30 +01:00
|
|
|
{
|
2004-08-28 12:43:06 +01:00
|
|
|
if (sys->runs[run].protocol == INTRUDER)
|
|
|
|
{
|
2004-08-28 13:42:11 +01:00
|
|
|
if (sys->runs[run].role == I_M)
|
|
|
|
{
|
|
|
|
eprintf ("m0");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eprintf ("i%i", run);
|
|
|
|
}
|
2004-08-28 12:43:06 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eprintf ("r%ii%i", run, index);
|
|
|
|
}
|
2004-08-28 10:24:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Open graph
|
|
|
|
attack_number++;
|
|
|
|
eprintf ("digraph semiState%i {\n", attack_number);
|
2004-08-30 14:57:16 +01:00
|
|
|
eprintf ("\tlabel = \"Protocol ");
|
2004-08-28 10:24:30 +01:00
|
|
|
p = (Protocol) current_claim->protocol;
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", role ");
|
|
|
|
termPrint (current_claim->rolename);
|
|
|
|
eprintf (", claim type ");
|
|
|
|
termPrint (current_claim->type);
|
|
|
|
eprintf ("\";\n");
|
|
|
|
|
2004-10-18 14:04:34 +01:00
|
|
|
// Needed for the bindings later on: create graph
|
|
|
|
goal_graph_create (); // create graph
|
2004-10-28 16:23:16 +01:00
|
|
|
if (warshall (graph, nodes) == 0) // determine closure
|
|
|
|
{
|
|
|
|
eprintf ("// This graph was not completely closed transitively because it contains a cycle!\n");
|
|
|
|
}
|
2004-10-18 14:04:34 +01:00
|
|
|
|
2004-10-25 15:28:53 +01:00
|
|
|
ranks = memAlloc (nodes * sizeof(int));
|
|
|
|
maxrank = graph_ranks (graph, ranks, nodes); // determine ranks
|
|
|
|
|
2004-10-18 14:04:34 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
// For debugging purposes, we also display an ASCII version of some stuff in the comments
|
|
|
|
printSemiState ();
|
2004-10-28 16:23:16 +01:00
|
|
|
// Even draw all dependencies for non-intruder runs
|
|
|
|
// Real nice debugging :(
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
|
|
|
|
run = 0;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
|
|
|
int ev;
|
|
|
|
|
|
|
|
ev = 0;
|
|
|
|
while (ev < sys->runs[run].length)
|
|
|
|
{
|
|
|
|
int run2;
|
|
|
|
int notfirstrun;
|
|
|
|
|
|
|
|
eprintf ("// precedence: r%ii%i <- ", run,ev);
|
|
|
|
run2 = 0;
|
|
|
|
notfirstrun = 0;
|
|
|
|
while (run2 < sys->maxruns)
|
|
|
|
{
|
|
|
|
int notfirstev;
|
|
|
|
int ev2;
|
|
|
|
|
|
|
|
notfirstev = 0;
|
|
|
|
ev2 = 0;
|
|
|
|
while (ev2 < sys->runs[run2].length)
|
|
|
|
{
|
|
|
|
if (graph[graph_nodes (nodes, run2, ev2, run, ev)]
|
|
|
|
!= 0)
|
|
|
|
{
|
|
|
|
if (notfirstev)
|
|
|
|
eprintf (",");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (notfirstrun)
|
|
|
|
eprintf (" ");
|
|
|
|
eprintf ("r%i:", run2);
|
|
|
|
}
|
|
|
|
eprintf ("%i", ev2);
|
|
|
|
notfirstrun = 1;
|
|
|
|
notfirstev = 1;
|
|
|
|
}
|
|
|
|
ev2++;
|
|
|
|
}
|
|
|
|
run2++;
|
|
|
|
}
|
|
|
|
eprintf ("\n");
|
|
|
|
ev++;
|
|
|
|
}
|
|
|
|
run++;
|
|
|
|
}
|
|
|
|
}
|
2004-10-18 14:04:34 +01:00
|
|
|
#endif
|
|
|
|
|
2004-08-28 10:24:30 +01:00
|
|
|
// Draw graph
|
|
|
|
// First, all simple runs
|
|
|
|
run = 0;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
rd = sys->runs[run].start;
|
2004-10-27 17:10:58 +01:00
|
|
|
if (sys->runs[run].protocol != INTRUDER && sys->runs[run].length > 0)
|
2004-08-28 10:24:30 +01:00
|
|
|
{
|
2004-08-28 12:43:06 +01:00
|
|
|
// Regular run
|
|
|
|
|
2004-10-27 17:10:58 +01:00
|
|
|
/* DISABLED subgraphs
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf ("\tsubgraph cluster_run%i {\n", run);
|
|
|
|
eprintf ("\t\tlabel = \"");
|
2004-08-30 14:57:16 +01:00
|
|
|
eprintf ("#%i: ", run);
|
2004-08-28 10:24:30 +01:00
|
|
|
termPrint (sys->runs[run].protocol->nameterm);
|
2004-08-30 14:57:16 +01:00
|
|
|
eprintf (", ");
|
|
|
|
agentsOfRunPrint (sys, run);
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf ("\";\n", run);
|
|
|
|
if (run == 0)
|
|
|
|
{
|
|
|
|
eprintf ("\t\tcolor = red;\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eprintf ("\t\tcolor = blue;\n");
|
|
|
|
}
|
2004-10-27 17:10:58 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Display the respective events
|
2004-08-28 12:43:06 +01:00
|
|
|
while (index < sys->runs[run].length)
|
2004-08-28 10:24:30 +01:00
|
|
|
{
|
2004-08-28 12:43:06 +01:00
|
|
|
// Print node itself
|
2004-08-28 10:24:30 +01:00
|
|
|
eprintf ("\t\t");
|
|
|
|
node (run, index);
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf (" [");
|
|
|
|
if (run == 0 && index == current_claim->ev)
|
|
|
|
{
|
2004-08-30 14:57:16 +01:00
|
|
|
eprintf
|
|
|
|
("style=filled,fillcolor=mistyrose,color=salmon,shape=doubleoctagon,");
|
2004-08-28 12:43:06 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eprintf ("shape=box,");
|
|
|
|
}
|
|
|
|
eprintf ("label=\"");
|
2004-10-28 13:56:13 +01:00
|
|
|
roledefPrintShort (rd);
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf ("\"]");
|
2004-08-28 10:24:30 +01:00
|
|
|
eprintf (";\n");
|
2004-08-28 12:43:06 +01:00
|
|
|
|
|
|
|
// Print binding to previous node
|
2004-08-28 15:00:48 +01:00
|
|
|
if (index > sys->runs[run].firstReal)
|
2004-08-28 12:43:06 +01:00
|
|
|
{
|
2004-08-28 15:00:48 +01:00
|
|
|
// index > 0
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf ("\t\t");
|
|
|
|
node (run, index - 1);
|
|
|
|
eprintf (" -> ");
|
|
|
|
node (run, index);
|
2004-10-27 17:10:58 +01:00
|
|
|
eprintf (" [style=\"bold\", weight=\"10.0\"]");
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf (";\n");
|
|
|
|
}
|
2004-08-28 15:00:48 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// index <= firstReal
|
|
|
|
if (index == sys->runs[run].firstReal)
|
|
|
|
{
|
|
|
|
// index == firstReal
|
|
|
|
Roledef rd;
|
|
|
|
int send_before_read;
|
|
|
|
int done;
|
|
|
|
|
|
|
|
// Determine if it is an active role or note
|
|
|
|
/**
|
|
|
|
*@todo note that this will probably become a standard function call for role.h
|
|
|
|
*/
|
|
|
|
rd =
|
|
|
|
roledef_shift (sys->runs[run].start,
|
|
|
|
sys->runs[run].firstReal);
|
|
|
|
done = 0;
|
|
|
|
send_before_read = 0;
|
|
|
|
while (!done && rd != NULL)
|
|
|
|
{
|
|
|
|
if (rd->type == READ)
|
|
|
|
{
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
if (rd->type == SEND)
|
|
|
|
{
|
|
|
|
done = 1;
|
|
|
|
send_before_read = 1;
|
|
|
|
}
|
|
|
|
rd = rd->next;
|
|
|
|
}
|
2004-10-27 17:10:58 +01:00
|
|
|
// Draw the first box
|
|
|
|
// This used to be drawn only if done && send_before_read, now we always draw it.
|
2004-10-28 13:56:13 +01:00
|
|
|
eprintf ("\t\ts%i [label=\"Run %i\\n", run,run);
|
2004-10-27 17:10:58 +01:00
|
|
|
agentsOfRunPrint (sys, run);
|
|
|
|
eprintf ("\", shape=diamond];\n");
|
|
|
|
eprintf ("\t\ts%i -> ", run);
|
|
|
|
node (run, index);
|
|
|
|
eprintf (";\n");
|
2004-08-28 15:00:48 +01:00
|
|
|
}
|
|
|
|
}
|
2004-08-28 12:43:06 +01:00
|
|
|
index++;
|
|
|
|
rd = rd->next;
|
2004-08-28 10:24:30 +01:00
|
|
|
}
|
2004-10-27 17:10:58 +01:00
|
|
|
/* DISABLED subgraphs
|
2004-08-28 12:43:06 +01:00
|
|
|
eprintf ("\t}\n");
|
2004-10-27 17:10:58 +01:00
|
|
|
*/
|
2004-08-28 12:43:06 +01:00
|
|
|
}
|
2004-08-28 14:47:37 +01:00
|
|
|
run++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Second, all bindings.
|
|
|
|
// We now determine them ourselves between existing runs
|
|
|
|
run = 0;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
|
|
|
if (sys->runs[run].protocol != INTRUDER)
|
2004-08-28 12:43:06 +01:00
|
|
|
{
|
2004-08-28 14:47:37 +01:00
|
|
|
int ev;
|
|
|
|
|
|
|
|
ev = 0;
|
|
|
|
while (ev < sys->runs[run].length)
|
2004-08-28 13:42:11 +01:00
|
|
|
{
|
2004-08-28 14:47:37 +01:00
|
|
|
/**
|
|
|
|
* Determine wheter to draw an incoming arrow to this event.
|
|
|
|
* We check all other runs, to see if they are ordered.
|
|
|
|
*/
|
|
|
|
int run2;
|
|
|
|
|
|
|
|
run2 = 0;
|
|
|
|
while (run2 < sys->maxruns)
|
|
|
|
{
|
|
|
|
if (run2 != run && sys->runs[run2].protocol != INTRUDER)
|
|
|
|
{
|
|
|
|
// Is this run before the event?
|
|
|
|
int ev2;
|
|
|
|
int found;
|
|
|
|
|
|
|
|
found = 0;
|
2004-10-28 16:23:16 +01:00
|
|
|
ev2 = sys->runs[run2].length;
|
|
|
|
while (found == 0 && ev2 > 0)
|
2004-08-28 14:47:37 +01:00
|
|
|
{
|
2004-10-28 16:23:16 +01:00
|
|
|
ev2--;
|
2004-08-28 14:47:37 +01:00
|
|
|
if (graph[graph_nodes (nodes, run2, ev2, run, ev)]
|
|
|
|
!= 0)
|
2004-08-30 14:57:16 +01:00
|
|
|
{
|
|
|
|
found = 1;
|
|
|
|
}
|
2004-08-28 14:47:37 +01:00
|
|
|
}
|
2004-08-30 14:57:16 +01:00
|
|
|
|
2004-08-30 07:07:17 +01:00
|
|
|
if (found == 1)
|
2004-08-28 14:47:37 +01:00
|
|
|
{
|
|
|
|
// It is before the event, and thus we would like to draw it.
|
|
|
|
// However, if there is another path along which we can get here, forget it
|
2004-08-28 15:05:38 +01:00
|
|
|
/**
|
|
|
|
* Note that this algorithm is similar to Floyd's algorithm for all shortest paths.
|
|
|
|
* The goal here is to select only the path with distance 1 (as viewed from the regular runs),
|
|
|
|
* so we can simplify stuff a bit.
|
2004-08-30 14:57:16 +01:00
|
|
|
* Nevertheless, using Floyd first would probably be faster.
|
2004-08-28 15:05:38 +01:00
|
|
|
*/
|
2004-08-28 14:47:37 +01:00
|
|
|
int other_route;
|
2004-10-28 16:23:16 +01:00
|
|
|
int run3;
|
|
|
|
int ev3;
|
2004-08-28 14:47:37 +01:00
|
|
|
|
|
|
|
other_route = 0;
|
|
|
|
run3 = 0;
|
2004-10-28 16:23:16 +01:00
|
|
|
ev3 = 0;
|
2004-08-30 14:57:16 +01:00
|
|
|
while (other_route == 0 && run3 < sys->maxruns)
|
2004-08-28 14:47:37 +01:00
|
|
|
{
|
|
|
|
if (sys->runs[run3].protocol != INTRUDER)
|
|
|
|
{
|
|
|
|
ev3 = 0;
|
2004-08-30 14:57:16 +01:00
|
|
|
while (other_route == 0
|
|
|
|
&& ev3 < sys->runs[run3].length)
|
2004-08-28 14:47:37 +01:00
|
|
|
{
|
|
|
|
if (graph
|
|
|
|
[graph_nodes
|
|
|
|
(nodes, run2, ev2, run3, ev3)] != 0
|
|
|
|
&&
|
|
|
|
graph[graph_nodes
|
|
|
|
(nodes, run3, ev3, run,
|
|
|
|
ev)] != 0)
|
|
|
|
{
|
|
|
|
// other route found
|
|
|
|
other_route = 1;
|
|
|
|
}
|
|
|
|
ev3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
run3++;
|
|
|
|
}
|
2004-08-30 14:57:16 +01:00
|
|
|
if (other_route == 0)
|
2004-08-28 14:47:37 +01:00
|
|
|
{
|
2004-10-27 17:10:58 +01:00
|
|
|
Roledef rd,rd2;
|
|
|
|
/*
|
|
|
|
* We have decided to draw this binding,
|
|
|
|
* from run2,ev2 to run,ev
|
|
|
|
* However, me might need to decide some colouring for this node.
|
|
|
|
*/
|
2004-08-30 14:57:16 +01:00
|
|
|
eprintf ("\t");
|
2004-08-28 14:47:37 +01:00
|
|
|
node (run2, ev2);
|
|
|
|
eprintf (" -> ");
|
|
|
|
node (run, ev);
|
2004-10-27 17:10:58 +01:00
|
|
|
eprintf (" ");
|
|
|
|
// decide color
|
|
|
|
rd = roledef_shift (sys->runs[run].start,ev);
|
|
|
|
rd2 = roledef_shift (sys->runs[run2].start,ev2);
|
|
|
|
if (rd->type == CLAIM)
|
|
|
|
{
|
|
|
|
// Towards a claim, so only indirect dependency
|
|
|
|
eprintf ("[color=cornflowerblue]");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Not towards claim should imply towards read,
|
|
|
|
// but we check it to comply with future stuff.
|
|
|
|
if (rd->type == READ && rd2->type == SEND)
|
|
|
|
{
|
|
|
|
// We want to distinguish where it is from a 'broken' send
|
|
|
|
if (isTermEqual (rd->message, rd2->message))
|
|
|
|
{
|
|
|
|
if (isTermEqual (rd->from, rd2->from) && isTermEqual (rd->to, rd2->to))
|
|
|
|
{
|
|
|
|
// Wow, a perfect match. Leave the arrow as-is :)
|
|
|
|
eprintf ("[color=forestgreen]");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Same message, different people
|
|
|
|
eprintf ("[label=\"redirect\",color=darkorange2]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Not even the same message, intruder construction
|
|
|
|
eprintf ("[label=\"construct\",color=red]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// close up
|
2004-08-28 14:47:37 +01:00
|
|
|
eprintf (";\n");
|
|
|
|
}
|
2004-10-28 16:23:16 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// for debugging: show other route
|
|
|
|
run3--;
|
|
|
|
ev3--;
|
|
|
|
|
|
|
|
eprintf ("\t// HIDDEN r%ii%i -> r%ii%i because route through r%ii%i\n",
|
|
|
|
run2, ev2, run, ev, run3, ev3);
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-28 14:47:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
run2++;
|
|
|
|
}
|
|
|
|
ev++;
|
2004-08-28 13:42:11 +01:00
|
|
|
}
|
2004-08-28 10:24:30 +01:00
|
|
|
}
|
|
|
|
run++;
|
|
|
|
}
|
|
|
|
|
2004-10-25 15:28:53 +01:00
|
|
|
// Third, all ranking info
|
|
|
|
{
|
|
|
|
int myrank;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
eprintf ("/* ranks: %i\n", maxrank);
|
|
|
|
n = 0;
|
|
|
|
while (n < nodes)
|
|
|
|
{
|
|
|
|
eprintf ("%i ", ranks[n]);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
eprintf ("\n*/\n\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
myrank = 0;
|
|
|
|
while (myrank < maxrank)
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
int run;
|
|
|
|
int run1;
|
|
|
|
int ev1;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
run = 0;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
2004-10-27 17:10:58 +01:00
|
|
|
if (sys->runs[run].protocol != INTRUDER)
|
2004-10-25 15:28:53 +01:00
|
|
|
{
|
2004-10-27 17:10:58 +01:00
|
|
|
int ev;
|
|
|
|
|
|
|
|
ev = 0;
|
|
|
|
while (ev < sys->runs[run].step)
|
2004-10-25 15:28:53 +01:00
|
|
|
{
|
2004-10-27 17:10:58 +01:00
|
|
|
if (myrank == ranks[node_number (run,ev)])
|
|
|
|
{
|
|
|
|
if (count == 0)
|
|
|
|
eprintf ("\t{ rank = same; ");
|
|
|
|
count++;
|
|
|
|
eprintf ("r%ii%i; ",run,ev);
|
|
|
|
}
|
|
|
|
ev++;
|
2004-10-25 15:28:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
run++;
|
|
|
|
}
|
|
|
|
if (count > 0)
|
|
|
|
eprintf ("}\t\t// rank %i\n", myrank);
|
|
|
|
myrank++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clean memory
|
|
|
|
memFree (ranks, nodes * sizeof(int)); // ranks
|
|
|
|
|
2004-08-28 10:24:30 +01:00
|
|
|
// close graph
|
|
|
|
eprintf ("};\n\n");
|
|
|
|
}
|
|
|
|
|
2004-08-13 09:29:11 +01:00
|
|
|
//! Print the current semistate
|
|
|
|
void
|
|
|
|
printSemiState ()
|
|
|
|
{
|
|
|
|
int run;
|
2004-08-14 15:38:30 +01:00
|
|
|
int open;
|
2004-08-15 18:50:41 +01:00
|
|
|
List bl;
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
int binding_state_print (void *dt)
|
2004-08-15 20:58:26 +01:00
|
|
|
{
|
2004-08-18 15:06:14 +01:00
|
|
|
binding_indent_print ((Binding) dt, 1);
|
2004-08-15 20:58:26 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2004-08-13 09:29:11 +01:00
|
|
|
|
2004-08-14 15:38:30 +01:00
|
|
|
indentPrint ();
|
|
|
|
eprintf ("!! --=[ Semistate ]=--\n");
|
2004-08-27 19:18:16 +01:00
|
|
|
indentPrint ();
|
|
|
|
eprintf ("!!\n");
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("!! Trace length: %i\n", get_trace_length ());
|
2004-08-14 15:38:30 +01:00
|
|
|
open = 0;
|
2004-08-13 09:29:11 +01:00
|
|
|
for (run = 0; run < sys->maxruns; run++)
|
|
|
|
{
|
|
|
|
int index;
|
2004-08-15 18:16:13 +01:00
|
|
|
Role r;
|
2004-08-13 09:29:11 +01:00
|
|
|
Roledef rd;
|
2004-08-15 18:16:13 +01:00
|
|
|
Term oldagent;
|
2004-08-13 09:29:11 +01:00
|
|
|
|
2004-08-15 18:16:13 +01:00
|
|
|
indentPrint ();
|
|
|
|
eprintf ("!!\n");
|
2004-08-13 09:29:11 +01:00
|
|
|
indentPrint ();
|
2004-08-14 15:38:30 +01:00
|
|
|
eprintf ("!! [ Run %i, ", run);
|
2004-08-15 18:16:13 +01:00
|
|
|
termPrint (sys->runs[run].protocol->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
r = sys->runs[run].role;
|
|
|
|
oldagent = r->nameterm->subst;
|
|
|
|
r->nameterm->subst = NULL;
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
r->nameterm->subst = oldagent;
|
|
|
|
if (oldagent != NULL)
|
|
|
|
{
|
|
|
|
eprintf (": ");
|
|
|
|
termPrint (oldagent);
|
|
|
|
}
|
2004-08-13 09:29:11 +01:00
|
|
|
eprintf (" ]\n");
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
rd = sys->runs[run].start;
|
|
|
|
while (index < sys->runs[run].length)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-14 15:38:30 +01:00
|
|
|
eprintf ("!! %i ", index);
|
2004-08-13 09:29:11 +01:00
|
|
|
roledefPrint (rd);
|
|
|
|
eprintf ("\n");
|
2004-08-14 15:38:30 +01:00
|
|
|
if (isGoal (rd) && !isBound (rd))
|
2004-08-14 17:12:32 +01:00
|
|
|
open++;
|
2004-08-13 09:29:11 +01:00
|
|
|
index++;
|
|
|
|
rd = rd->next;
|
|
|
|
}
|
|
|
|
}
|
2004-08-15 18:50:41 +01:00
|
|
|
if (sys->bindings != NULL)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("!!\n");
|
2004-08-18 15:06:14 +01:00
|
|
|
list_iterate (sys->bindings, binding_state_print);
|
2004-08-15 18:50:41 +01:00
|
|
|
}
|
2004-08-14 15:38:30 +01:00
|
|
|
indentPrint ();
|
2004-08-15 18:16:13 +01:00
|
|
|
eprintf ("!!\n");
|
|
|
|
indentPrint ();
|
2004-08-14 15:38:30 +01:00
|
|
|
eprintf ("!! - open: %i -\n", open);
|
2004-08-13 09:29:11 +01:00
|
|
|
}
|
|
|
|
|
2004-08-11 22:04:52 +01:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Larger logical componentents
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//! Goal selection
|
|
|
|
/**
|
2004-08-20 10:21:39 +01:00
|
|
|
* Selects the most constrained goal.
|
|
|
|
*
|
2004-08-20 11:52:40 +01:00
|
|
|
* First selection is on level; thus, keys are selected first.
|
|
|
|
*
|
2004-08-20 10:21:39 +01:00
|
|
|
* Because the list starts with the newest terms, and we use <= (as opposed to <), we
|
|
|
|
* ensure that for goals with equal constraint levels, we select the oldest one.
|
2004-08-11 22:04:52 +01:00
|
|
|
*/
|
2004-08-18 10:57:01 +01:00
|
|
|
Binding
|
2004-08-11 22:04:52 +01:00
|
|
|
select_goal ()
|
|
|
|
{
|
2004-08-18 10:57:01 +01:00
|
|
|
List bl;
|
|
|
|
Binding best;
|
2004-08-18 15:06:14 +01:00
|
|
|
float min_constrain;
|
2004-08-20 11:52:40 +01:00
|
|
|
int max_level;
|
2004-08-11 22:04:52 +01:00
|
|
|
|
2004-08-31 15:31:06 +01:00
|
|
|
// Find the most constrained goal
|
2004-08-20 10:53:44 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Listing open goals that might be chosen: ");
|
|
|
|
}
|
2004-10-14 16:09:48 +01:00
|
|
|
max_level = INT_MIN;
|
2004-08-18 10:57:01 +01:00
|
|
|
best = NULL;
|
|
|
|
bl = sys->bindings;
|
|
|
|
while (bl != NULL)
|
2004-08-11 22:04:52 +01:00
|
|
|
{
|
2004-08-18 10:57:01 +01:00
|
|
|
Binding b;
|
2004-08-11 22:04:52 +01:00
|
|
|
|
2004-08-18 10:57:01 +01:00
|
|
|
b = (Binding) bl->data;
|
2004-08-30 21:48:11 +01:00
|
|
|
|
|
|
|
// Ignore singular variables
|
|
|
|
if (!b->done && !realTermVariable (deVar(b->term)) )
|
|
|
|
//if (!b->done)
|
2004-08-11 22:04:52 +01:00
|
|
|
{
|
2004-08-28 13:20:50 +01:00
|
|
|
float cons;
|
2004-08-18 16:46:33 +01:00
|
|
|
|
2004-08-28 13:20:50 +01:00
|
|
|
if (sys->output == PROOF && best != NULL)
|
|
|
|
eprintf (", ");
|
|
|
|
if (b->level >= max_level)
|
|
|
|
{
|
|
|
|
if (b->level > max_level)
|
2004-08-18 16:46:33 +01:00
|
|
|
{
|
2004-08-28 13:20:50 +01:00
|
|
|
max_level = b->level;
|
|
|
|
min_constrain = 1; // 1 is the maximum
|
2004-08-18 16:46:33 +01:00
|
|
|
}
|
2004-08-28 13:20:50 +01:00
|
|
|
cons = term_constrain_level (b->term);
|
|
|
|
if (cons <= min_constrain)
|
2004-08-20 11:52:40 +01:00
|
|
|
{
|
2004-08-28 13:20:50 +01:00
|
|
|
min_constrain = cons;
|
|
|
|
best = b;
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
eprintf ("*");
|
2004-08-20 11:52:40 +01:00
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
}
|
2004-08-28 13:20:50 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf ("[%i]", b->level);
|
|
|
|
}
|
2004-08-11 22:04:52 +01:00
|
|
|
}
|
2004-08-18 10:57:01 +01:00
|
|
|
bl = bl->next;
|
2004-08-11 22:04:52 +01:00
|
|
|
}
|
2004-08-20 10:53:44 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
if (best == NULL)
|
|
|
|
eprintf ("none");
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
2004-08-18 10:57:01 +01:00
|
|
|
return best;
|
2004-08-11 22:04:52 +01:00
|
|
|
}
|
|
|
|
|
2004-08-18 19:22:59 +01:00
|
|
|
//! Create a new intruder run to generate knowledge from m0
|
|
|
|
int
|
|
|
|
bind_goal_new_m0 (const Binding b)
|
|
|
|
{
|
|
|
|
Termlist m0tl;
|
|
|
|
int flag;
|
2004-08-19 13:35:51 +01:00
|
|
|
int found;
|
2004-08-18 19:22:59 +01:00
|
|
|
|
|
|
|
flag = 1;
|
2004-08-19 13:35:51 +01:00
|
|
|
found = 0;
|
2004-08-18 19:22:59 +01:00
|
|
|
m0tl = knowledgeSet (sys->know);
|
|
|
|
while (flag && m0tl != NULL)
|
|
|
|
{
|
|
|
|
Term m0t;
|
|
|
|
Termlist subst;
|
|
|
|
|
|
|
|
m0t = m0tl->term;
|
|
|
|
subst = termMguTerm (b->term, m0t);
|
|
|
|
if (subst != MGUFAIL)
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
|
2004-08-19 13:47:53 +01:00
|
|
|
run = semiRunCreate (INTRUDER, I_M);
|
2004-08-19 12:37:41 +01:00
|
|
|
proof_suppose_run (run, 0, 1);
|
2004-08-18 19:22:59 +01:00
|
|
|
sys->runs[run].start->message = termDuplicate (b->term);
|
|
|
|
sys->runs[run].length = 1;
|
2004-08-19 12:37:41 +01:00
|
|
|
indentDepth++;
|
2004-08-18 19:22:59 +01:00
|
|
|
if (goal_bind (b, run, 0))
|
|
|
|
{
|
2004-08-19 13:35:51 +01:00
|
|
|
found++;
|
2004-08-19 11:46:27 +01:00
|
|
|
proof_suppose_binding (b);
|
|
|
|
if (sys->output == PROOF)
|
2004-08-18 19:22:59 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-19 13:35:51 +01:00
|
|
|
eprintf ("* I.e. retrieving ");
|
2004-08-18 19:22:59 +01:00
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" from the initial knowledge.\n");
|
|
|
|
}
|
|
|
|
flag = flag && iterate ();
|
|
|
|
}
|
2004-08-19 12:37:41 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
proof_cannot_bind (b, run, 0);
|
|
|
|
}
|
2004-08-18 19:22:59 +01:00
|
|
|
goal_unbind (b);
|
2004-08-19 12:37:41 +01:00
|
|
|
indentDepth--;
|
2004-08-19 13:47:53 +01:00
|
|
|
semiRunDestroy ();
|
2004-08-19 15:49:03 +01:00
|
|
|
|
2004-08-18 19:22:59 +01:00
|
|
|
termlistSubstReset (subst);
|
|
|
|
termlistDelete (subst);
|
|
|
|
}
|
|
|
|
|
|
|
|
m0tl = m0tl->next;
|
|
|
|
}
|
|
|
|
|
2004-08-19 13:35:51 +01:00
|
|
|
if (found == 0 && sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Term ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" cannot be constructed from the initial knowledge.\n");
|
|
|
|
}
|
2004-08-18 19:22:59 +01:00
|
|
|
termlistDelete (m0tl);
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Bind an intruder goal by intruder composition construction
|
2004-08-13 21:56:51 +01:00
|
|
|
/**
|
|
|
|
* Handles the case where the intruder constructs a composed term himself.
|
|
|
|
*/
|
2004-08-13 11:25:23 +01:00
|
|
|
int
|
2004-08-18 19:22:59 +01:00
|
|
|
bind_goal_new_encrypt (const Binding b)
|
2004-08-13 11:25:23 +01:00
|
|
|
{
|
2004-08-13 21:09:12 +01:00
|
|
|
Term term;
|
2004-08-16 15:49:41 +01:00
|
|
|
int flag;
|
2004-08-19 15:49:03 +01:00
|
|
|
int can_be_encrypted;
|
2004-08-13 21:09:12 +01:00
|
|
|
|
2004-08-16 15:49:41 +01:00
|
|
|
flag = 1;
|
2004-08-19 15:55:21 +01:00
|
|
|
term = deVar (b->term);
|
2004-08-19 15:49:03 +01:00
|
|
|
can_be_encrypted = 0;
|
2004-08-18 19:22:59 +01:00
|
|
|
|
2004-08-13 21:09:12 +01:00
|
|
|
if (!realTermLeaf (term))
|
|
|
|
{
|
2004-08-18 16:46:33 +01:00
|
|
|
int run;
|
|
|
|
int index;
|
|
|
|
int newgoals;
|
|
|
|
Roledef rd;
|
2004-08-13 21:09:12 +01:00
|
|
|
Term t1, t2;
|
|
|
|
|
2004-08-19 15:49:03 +01:00
|
|
|
if (!realTermEncrypt (term))
|
2004-08-13 21:09:12 +01:00
|
|
|
{
|
|
|
|
// tuple construction
|
2004-08-18 16:46:33 +01:00
|
|
|
error ("Goal that is a tuple should not occur!");
|
2004-08-13 21:09:12 +01:00
|
|
|
}
|
|
|
|
|
2004-08-18 16:46:33 +01:00
|
|
|
// must be encryption
|
2004-11-16 12:06:36 +00:00
|
|
|
t1 = TermOp(term);
|
|
|
|
t2 = TermKey(term);
|
2004-08-18 16:46:33 +01:00
|
|
|
|
2004-08-19 15:49:03 +01:00
|
|
|
if (t2 != TERM_Hidden)
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
2004-08-19 15:49:03 +01:00
|
|
|
can_be_encrypted = 1;
|
|
|
|
run = semiRunCreate (INTRUDER, I_RRS);
|
|
|
|
rd = sys->runs[run].start;
|
2004-08-19 15:52:17 +01:00
|
|
|
rd->message = termDuplicateUV (t1);
|
|
|
|
rd->next->message = termDuplicateUV (t2);
|
2004-08-19 15:49:03 +01:00
|
|
|
rd->next->next->message = termDuplicateUV (term);
|
|
|
|
index = 2;
|
|
|
|
proof_suppose_run (run, 0, index + 1);
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* Encrypting ");
|
|
|
|
termPrint (term);
|
|
|
|
eprintf (" using term ");
|
|
|
|
termPrint (t1);
|
|
|
|
eprintf (" and key ");
|
|
|
|
termPrint (t2);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
|
|
|
newgoals = add_read_goals (run, 0, index + 1);
|
2004-08-19 15:55:21 +01:00
|
|
|
|
2004-08-19 15:49:03 +01:00
|
|
|
indentDepth++;
|
|
|
|
if (goal_bind (b, run, index))
|
|
|
|
{
|
|
|
|
proof_suppose_binding (b);
|
|
|
|
flag = flag && iterate ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
proof_cannot_bind (b, run, index);
|
|
|
|
}
|
|
|
|
goal_unbind (b);
|
|
|
|
indentDepth--;
|
2004-10-18 14:04:34 +01:00
|
|
|
goal_remove_last (newgoals);
|
2004-08-19 15:49:03 +01:00
|
|
|
semiRunDestroy ();
|
2004-08-19 12:37:41 +01:00
|
|
|
}
|
2004-08-13 21:09:12 +01:00
|
|
|
}
|
2004-08-19 15:49:03 +01:00
|
|
|
|
|
|
|
if (!can_be_encrypted)
|
2004-08-19 13:35:51 +01:00
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Term ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" cannot be constructed by encryption.\n");
|
|
|
|
}
|
|
|
|
}
|
2004-08-16 15:49:41 +01:00
|
|
|
return flag;
|
2004-08-13 11:25:23 +01:00
|
|
|
}
|
|
|
|
|
2004-08-18 19:22:59 +01:00
|
|
|
//! Bind an intruder goal by intruder construction
|
|
|
|
/**
|
|
|
|
* Handles the case where the intruder constructs a composed term himself.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
bind_goal_new_intruder_run (const Binding b)
|
|
|
|
{
|
2004-08-19 13:35:51 +01:00
|
|
|
int flag;
|
|
|
|
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Can we bind ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" from a new intruder run?\n");
|
|
|
|
}
|
|
|
|
indentDepth++;
|
|
|
|
flag = bind_goal_new_m0 (b);
|
|
|
|
flag = flag && bind_goal_new_encrypt (b);
|
|
|
|
indentDepth--;
|
|
|
|
return flag;
|
2004-08-18 19:22:59 +01:00
|
|
|
}
|
2004-08-13 11:25:23 +01:00
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
//! Bind a regular goal
|
2004-08-30 23:08:44 +01:00
|
|
|
/**
|
|
|
|
* Problem child. Valgrind does not like it.
|
|
|
|
*/
|
2004-08-11 13:08:10 +01:00
|
|
|
int
|
2004-08-18 16:46:33 +01:00
|
|
|
bind_goal_regular_run (const Binding b)
|
2004-08-11 13:08:10 +01:00
|
|
|
{
|
2004-08-15 18:07:38 +01:00
|
|
|
int flag;
|
2004-08-19 12:37:41 +01:00
|
|
|
int found;
|
2004-08-15 18:07:38 +01:00
|
|
|
|
2004-08-30 22:49:51 +01:00
|
|
|
int test_sub_unification (Termlist substlist, Termlist keylist)
|
|
|
|
{
|
|
|
|
// A unification exists; return the signal
|
|
|
|
return 0;
|
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
/*
|
|
|
|
* This is a local function so we have access to goal
|
|
|
|
*/
|
|
|
|
int bind_this_role_send (Protocol p, Role r, Roledef rd, int index)
|
|
|
|
{
|
2004-08-18 16:46:33 +01:00
|
|
|
if (p == INTRUDER)
|
|
|
|
{
|
|
|
|
// No intruder roles here
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
// Test for interm unification
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (5))
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Checking send candidate with message ");
|
|
|
|
termPrint (rd->message);
|
|
|
|
eprintf (" from ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf (", index %i\n", index);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!termMguSubTerm
|
2004-08-30 22:49:51 +01:00
|
|
|
(b->term, rd->message, test_sub_unification, sys->know->inverses, NULL))
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
2004-08-30 23:08:44 +01:00
|
|
|
int sflag;
|
2004-08-18 15:06:14 +01:00
|
|
|
|
|
|
|
// A good candidate
|
2004-08-19 12:37:41 +01:00
|
|
|
found++;
|
2004-08-19 13:35:51 +01:00
|
|
|
if (sys->output == PROOF && found == 1)
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-19 13:35:51 +01:00
|
|
|
eprintf ("The term ", found);
|
2004-08-18 15:06:14 +01:00
|
|
|
termPrint (b->term);
|
2004-08-19 14:09:35 +01:00
|
|
|
eprintf
|
|
|
|
(" matches patterns from the role definitions. Investigate.\n");
|
2004-08-19 13:35:51 +01:00
|
|
|
}
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("%i. It matches the pattern ", found);
|
2004-08-19 12:37:41 +01:00
|
|
|
termPrint (rd->message);
|
|
|
|
eprintf (" from ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
2004-08-18 15:06:14 +01:00
|
|
|
termPrint (r->nameterm);
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf (", at %i\n", index);
|
2004-08-18 15:06:14 +01:00
|
|
|
}
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth++;
|
2004-08-18 15:06:14 +01:00
|
|
|
// Bind to existing run
|
2004-08-30 23:08:44 +01:00
|
|
|
sflag = bind_existing_run (b, p, r, index);
|
2004-08-18 16:46:33 +01:00
|
|
|
// bind to new run
|
2004-08-30 23:08:44 +01:00
|
|
|
sflag = sflag && bind_new_run (b, p, r, index);
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth--;
|
2004-08-30 23:08:44 +01:00
|
|
|
return sflag;
|
2004-08-18 15:06:14 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-27 18:35:23 +01:00
|
|
|
|
2004-08-18 16:46:33 +01:00
|
|
|
// Bind to all possible sends of regular runs
|
2004-08-19 12:37:41 +01:00
|
|
|
found = 0;
|
|
|
|
flag = iterate_role_sends (bind_this_role_send);
|
|
|
|
if (sys->output == PROOF && found == 0)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("The term ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" does not match any pattern from the role definitions.\n");
|
|
|
|
}
|
|
|
|
return flag;
|
2004-08-18 16:46:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Bind to all possible sends of intruder runs
|
2004-08-18 20:43:58 +01:00
|
|
|
int
|
|
|
|
bind_goal_old_intruder_run (Binding b)
|
2004-08-18 16:46:33 +01:00
|
|
|
{
|
|
|
|
int run;
|
|
|
|
int flag;
|
2004-08-19 13:35:51 +01:00
|
|
|
int found;
|
2004-08-18 16:46:33 +01:00
|
|
|
|
2004-08-19 13:35:51 +01:00
|
|
|
found = 0;
|
2004-08-18 16:46:33 +01:00
|
|
|
flag = 1;
|
|
|
|
for (run = 0; run < sys->maxruns; run++)
|
|
|
|
{
|
|
|
|
if (sys->runs[run].protocol == INTRUDER)
|
|
|
|
{
|
|
|
|
int ev;
|
|
|
|
Roledef rd;
|
2004-08-18 15:06:14 +01:00
|
|
|
|
2004-08-18 20:43:58 +01:00
|
|
|
rd = sys->runs[run].start;
|
2004-08-18 16:46:33 +01:00
|
|
|
ev = 0;
|
|
|
|
while (ev < sys->runs[run].length)
|
|
|
|
{
|
|
|
|
if (rd->type == SEND)
|
|
|
|
{
|
2004-08-19 13:35:51 +01:00
|
|
|
found++;
|
|
|
|
if (sys->output == PROOF && found == 1)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-19 14:09:35 +01:00
|
|
|
eprintf
|
|
|
|
("Suppose it is from an existing intruder run.\n");
|
2004-08-19 13:35:51 +01:00
|
|
|
}
|
2004-08-19 14:09:35 +01:00
|
|
|
indentDepth++;
|
2004-08-18 20:43:58 +01:00
|
|
|
flag = flag && bind_existing_to_goal (b, run, ev);
|
2004-08-19 14:09:35 +01:00
|
|
|
indentDepth--;
|
2004-08-18 16:46:33 +01:00
|
|
|
}
|
|
|
|
rd = rd->next;
|
|
|
|
ev++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-08-19 13:35:51 +01:00
|
|
|
if (sys->output == PROOF && found == 0)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("No existing intruder runs to match to.\n");
|
|
|
|
}
|
2004-08-18 15:06:14 +01:00
|
|
|
return flag;
|
2004-08-11 13:08:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Bind a goal in all possible ways
|
|
|
|
int
|
2004-08-18 10:57:01 +01:00
|
|
|
bind_goal (const Binding b)
|
2004-08-11 13:08:10 +01:00
|
|
|
{
|
2004-08-18 10:57:01 +01:00
|
|
|
if (!b->done)
|
2004-08-11 13:08:10 +01:00
|
|
|
{
|
2004-08-18 16:46:33 +01:00
|
|
|
int flag;
|
2004-08-20 12:47:00 +01:00
|
|
|
int know_only;
|
|
|
|
Term function;
|
2004-08-18 16:46:33 +01:00
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
proof_select_goal (b);
|
|
|
|
indentDepth++;
|
2004-08-20 12:47:00 +01:00
|
|
|
|
|
|
|
// Prune: if it is an SK type construct, ready
|
|
|
|
// No regular run will apply SK for you.
|
|
|
|
//!@todo This still needs a lemma, and a more generic (correct) algorithm!!
|
2004-08-27 18:35:23 +01:00
|
|
|
|
2004-08-20 12:47:00 +01:00
|
|
|
know_only = 0;
|
|
|
|
function = getTermFunction (b->term);
|
|
|
|
if (function != NULL)
|
|
|
|
{
|
|
|
|
if (!inKnowledge (sys->know, function))
|
|
|
|
{
|
|
|
|
// Prune because we didn't know it before, and it is never subterm-sent
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* Because ");
|
|
|
|
termPrint (b->term);
|
2004-08-27 18:35:23 +01:00
|
|
|
eprintf
|
|
|
|
(" is never sent from a regular run (STILL NEEDS LEMMA!), we only intruder construct it.\n");
|
2004-08-20 12:47:00 +01:00
|
|
|
}
|
|
|
|
know_only = 1;
|
|
|
|
}
|
|
|
|
}
|
2004-08-27 18:35:23 +01:00
|
|
|
|
2004-10-14 16:25:28 +01:00
|
|
|
proofDepth++;
|
2004-08-20 12:47:00 +01:00
|
|
|
if (know_only)
|
|
|
|
{
|
|
|
|
// Special case: only from intruder
|
2004-08-27 18:35:23 +01:00
|
|
|
flag = flag && bind_goal_old_intruder_run (b);
|
|
|
|
flag = flag && bind_goal_new_intruder_run (b);
|
2004-08-20 12:47:00 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Normal case
|
|
|
|
flag = bind_goal_regular_run (b);
|
|
|
|
flag = flag && bind_goal_old_intruder_run (b);
|
|
|
|
flag = flag && bind_goal_new_intruder_run (b);
|
|
|
|
}
|
2004-10-14 16:25:28 +01:00
|
|
|
proofDepth--;
|
2004-08-20 12:47:00 +01:00
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
indentDepth--;
|
2004-08-18 16:46:33 +01:00
|
|
|
return flag;
|
2004-08-11 13:08:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-15 13:24:27 +01:00
|
|
|
return 1;
|
2004-08-11 13:08:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-19 14:09:35 +01:00
|
|
|
//! Prune determination because of theorems
|
2004-08-11 12:22:20 +01:00
|
|
|
/**
|
2004-08-19 14:09:35 +01:00
|
|
|
*@returns true iff this state is invalid because of a theorem
|
2004-08-11 12:22:20 +01:00
|
|
|
*/
|
|
|
|
int
|
2004-08-19 14:09:35 +01:00
|
|
|
prune_theorems ()
|
2004-08-11 12:22:20 +01:00
|
|
|
{
|
2004-08-15 17:44:54 +01:00
|
|
|
Termlist tl;
|
2004-08-18 20:43:58 +01:00
|
|
|
List bl;
|
2004-08-31 15:31:06 +01:00
|
|
|
int run;
|
2004-08-15 17:44:54 +01:00
|
|
|
|
2004-08-31 15:31:06 +01:00
|
|
|
// Check if all agents are agents (!)
|
|
|
|
run = 0;
|
|
|
|
while (run < sys->maxruns)
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
2004-08-31 15:31:06 +01:00
|
|
|
Termlist agl;
|
2004-08-15 17:44:54 +01:00
|
|
|
|
2004-08-31 15:31:06 +01:00
|
|
|
agl = sys->runs[run].agents;
|
|
|
|
while (agl != NULL)
|
2004-08-31 13:35:05 +01:00
|
|
|
{
|
2004-08-31 15:31:06 +01:00
|
|
|
Term agent;
|
|
|
|
|
|
|
|
agent = deVar(agl->term);
|
|
|
|
if (agent == NULL)
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
2004-08-31 15:31:06 +01:00
|
|
|
error ("Agent of run %i is NULL", run);
|
2004-08-15 17:44:54 +01:00
|
|
|
}
|
2004-08-31 15:31:06 +01:00
|
|
|
if (!realTermLeaf (agent) || (agent->stype != NULL && !inTermlist (agent->stype, TERM_Agent)))
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
2004-08-31 15:31:06 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because the agent ");
|
|
|
|
termPrint (agent);
|
|
|
|
eprintf (" of run %i is not of a compatible type.\n", run);
|
|
|
|
}
|
|
|
|
return 1;
|
2004-08-15 17:44:54 +01:00
|
|
|
}
|
2004-08-31 15:31:06 +01:00
|
|
|
agl = agl->next;
|
2004-08-15 17:44:54 +01:00
|
|
|
}
|
2004-08-31 15:31:06 +01:00
|
|
|
run++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if all agents of the main run are valid
|
|
|
|
tl = sys->runs[0].agents;
|
|
|
|
while (tl != NULL)
|
|
|
|
{
|
|
|
|
Term agent;
|
|
|
|
|
|
|
|
agent = deVar (tl->term);
|
2004-08-16 15:49:41 +01:00
|
|
|
if (!realTermVariable (agent) && inTermlist (sys->untrusted, agent))
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
2004-08-19 11:46:27 +01:00
|
|
|
if (sys->output == PROOF)
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-17 12:30:03 +01:00
|
|
|
eprintf
|
|
|
|
("Pruned because all agents of the claim run must be trusted.\n");
|
2004-08-15 17:44:54 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
tl = tl->next;
|
|
|
|
}
|
|
|
|
|
2004-08-30 22:07:45 +01:00
|
|
|
// Check if the actors of all other runs are not untrusted
|
|
|
|
if (sys->untrusted != NULL)
|
|
|
|
{
|
|
|
|
int run;
|
|
|
|
|
|
|
|
run = 1;
|
|
|
|
while (run < sys->maxruns)
|
|
|
|
{
|
2004-08-30 23:08:44 +01:00
|
|
|
if (sys->runs[run].protocol != INTRUDER)
|
2004-08-30 22:07:45 +01:00
|
|
|
{
|
2004-08-31 13:35:05 +01:00
|
|
|
if (sys->runs[run].agents != NULL)
|
2004-08-30 22:07:45 +01:00
|
|
|
{
|
2004-08-31 13:35:05 +01:00
|
|
|
Term actor;
|
|
|
|
|
|
|
|
actor = agentOfRun(sys, run);
|
|
|
|
if (actor == NULL)
|
2004-08-30 23:08:44 +01:00
|
|
|
{
|
2004-08-31 13:35:05 +01:00
|
|
|
error ("Agent of run %i is NULL", run);
|
2004-08-30 23:08:44 +01:00
|
|
|
}
|
2004-08-31 13:35:05 +01:00
|
|
|
if (inTermlist (sys->untrusted, actor))
|
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because the actor of run %i is untrusted.\n", run);
|
|
|
|
}
|
2004-10-27 17:20:12 +01:00
|
|
|
return 1;
|
2004-08-31 13:35:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Protocol p;
|
|
|
|
|
|
|
|
globalError++;
|
|
|
|
eprintf ("Run %i: ", run);
|
|
|
|
role_name_print (run);
|
|
|
|
eprintf (" has an empty agents list.\n");
|
|
|
|
eprintf ("protocol->rolenames: ");
|
|
|
|
p = (Protocol) sys->runs[run].protocol;
|
|
|
|
termlistPrint (p->rolenames);
|
|
|
|
eprintf ("\n");
|
|
|
|
error ("Aborting.");
|
|
|
|
globalError--;
|
2004-10-27 17:20:12 +01:00
|
|
|
return 1;
|
2004-08-30 22:07:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
run++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
// Check for c-minimality
|
|
|
|
if (!bindings_c_minimal ())
|
|
|
|
{
|
2004-08-19 11:46:27 +01:00
|
|
|
if (sys->output == PROOF)
|
2004-08-18 15:06:14 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because this is not <=c-minimal.\n");
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-20 12:47:00 +01:00
|
|
|
/**
|
|
|
|
* Check whether the bindings are valid
|
|
|
|
*/
|
2004-08-18 20:43:58 +01:00
|
|
|
bl = sys->bindings;
|
|
|
|
while (bl != NULL)
|
|
|
|
{
|
|
|
|
Binding b;
|
|
|
|
|
|
|
|
b = bl->data;
|
2004-08-20 12:47:00 +01:00
|
|
|
|
|
|
|
// Check for "Hidden" interm goals
|
2004-08-18 20:43:58 +01:00
|
|
|
if (termInTerm (b->term, TERM_Hidden))
|
|
|
|
{
|
|
|
|
// Prune the state: we can never meet this
|
2004-08-19 11:46:27 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because intruder can never construnct ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
2004-08-18 20:43:58 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2004-08-20 12:47:00 +01:00
|
|
|
|
|
|
|
// Check for encryption levels
|
2004-08-20 10:53:44 +01:00
|
|
|
if (sys->match < 2
|
|
|
|
&& (term_encryption_level (b->term) > max_encryption_level))
|
2004-08-19 16:30:31 +01:00
|
|
|
{
|
|
|
|
// Prune: we do not need to construct such terms
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because the encryption level of ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" is too high.\n");
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-08-20 12:47:00 +01:00
|
|
|
|
2004-08-20 15:55:34 +01:00
|
|
|
// Check for SK-type function occurrences
|
|
|
|
//!@todo Needs a LEMMA, although this seems to be quite straightforward to prove.
|
|
|
|
// The idea is that functions are never sent as a whole, but only used in applications.
|
|
|
|
if (isTermFunctionName (b->term))
|
|
|
|
{
|
|
|
|
if (!inKnowledge (sys->know, b->term))
|
|
|
|
{
|
|
|
|
// Not in initial knowledge of the intruder
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned because the function ");
|
|
|
|
termPrint (b->term);
|
|
|
|
eprintf (" is not known initially to the intruder.\n");
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-18 20:43:58 +01:00
|
|
|
bl = bl->next;
|
|
|
|
}
|
|
|
|
|
2004-08-11 12:22:20 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-08-19 14:09:35 +01:00
|
|
|
//! Prune determination for bounds
|
|
|
|
/**
|
|
|
|
*@returns true iff this state is invalid for some reason
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
prune_bounds ()
|
|
|
|
{
|
|
|
|
Termlist tl;
|
|
|
|
List bl;
|
|
|
|
|
2004-10-14 16:25:28 +01:00
|
|
|
if (proofDepth > sys->switch_maxtracelength)
|
|
|
|
{
|
|
|
|
// Hardcoded limit on proof tree depth
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Pruned: proof tree too deep: %i (-l %i switch)\n", proofDepth, sys->switch_maxtracelength);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-19 16:30:31 +01:00
|
|
|
if (num_regular_runs > sys->switchRuns)
|
2004-08-19 14:09:35 +01:00
|
|
|
{
|
2004-08-19 16:30:31 +01:00
|
|
|
// Hardcoded limit on runs
|
2004-08-19 14:09:35 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-19 16:30:31 +01:00
|
|
|
eprintf ("Pruned: too many regular runs (%i).\n", num_regular_runs);
|
2004-08-19 14:09:35 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-08-19 16:30:31 +01:00
|
|
|
|
|
|
|
// This needs some foundation. Probably * 2^max_encryption_level
|
|
|
|
//!@todo Fix this bound
|
2004-08-20 10:53:44 +01:00
|
|
|
if ((sys->match < 2)
|
|
|
|
&& (num_intruder_runs >
|
|
|
|
((double) sys->switchRuns * max_encryption_level * 8)))
|
2004-08-19 14:09:35 +01:00
|
|
|
{
|
2004-08-19 16:30:31 +01:00
|
|
|
// Hardcoded limit on iterations
|
2004-08-19 14:09:35 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-20 10:53:44 +01:00
|
|
|
eprintf
|
|
|
|
("Pruned: %i intruder runs is too much. (max encr. level %i)\n",
|
|
|
|
num_intruder_runs, max_encryption_level);
|
2004-08-19 14:09:35 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-08-27 19:09:09 +01:00
|
|
|
|
|
|
|
// Limit on exceeding any attack length
|
2004-08-27 19:18:16 +01:00
|
|
|
if (sys->prune == 2 && get_trace_length () >= attack_length)
|
2004-08-27 19:09:09 +01:00
|
|
|
{
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf
|
2004-08-27 19:18:16 +01:00
|
|
|
("Pruned: we already know an attack of length %i.\n",
|
|
|
|
attack_length);
|
2004-08-27 19:09:09 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No pruning because of bounds
|
2004-08-19 14:09:35 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-08-27 16:02:33 +01:00
|
|
|
//! Prune determination for specific properties
|
|
|
|
/**
|
|
|
|
* Sometimes, a property holds in part of the tree. Thus, we don't need to explore that part further if we want to find an attack.
|
|
|
|
*
|
|
|
|
*@returns true iff this state is invalid for some reason
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
prune_claim_specifics ()
|
|
|
|
{
|
|
|
|
if (current_claim->type == CLAIM_Niagree)
|
|
|
|
{
|
2004-08-27 18:25:38 +01:00
|
|
|
if (arachne_claim_niagree (sys, 0, current_claim->ev))
|
2004-08-27 16:02:33 +01:00
|
|
|
{
|
2004-08-27 18:35:23 +01:00
|
|
|
current_claim->count = statesIncrease (current_claim->count);
|
2004-08-27 16:02:33 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-27 18:35:23 +01:00
|
|
|
eprintf
|
|
|
|
("Pruned: niagree holds in this part of the proof tree.\n");
|
2004-08-27 16:02:33 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (current_claim->type == CLAIM_Nisynch)
|
|
|
|
{
|
2004-08-27 18:25:38 +01:00
|
|
|
if (arachne_claim_nisynch (sys, 0, current_claim->ev))
|
2004-08-27 16:02:33 +01:00
|
|
|
{
|
2004-08-27 18:35:23 +01:00
|
|
|
current_claim->count = statesIncrease (current_claim->count);
|
2004-08-27 16:02:33 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-27 18:35:23 +01:00
|
|
|
eprintf
|
|
|
|
("Pruned: nisynch holds in this part of the proof tree.\n");
|
2004-08-27 16:02:33 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-08-14 20:19:23 +01:00
|
|
|
//! Setup system for specific claim test
|
2004-08-18 10:57:01 +01:00
|
|
|
add_claim_specifics (const Claimlist cl, const Roledef rd)
|
2004-08-14 20:19:23 +01:00
|
|
|
{
|
2004-08-15 15:07:34 +01:00
|
|
|
if (cl->type == CLAIM_Secret)
|
2004-08-14 20:19:23 +01:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Secrecy claim
|
|
|
|
*/
|
2004-08-19 11:46:27 +01:00
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("* To verify the secrecy claim, we add the term ");
|
|
|
|
termPrint (rd->message);
|
|
|
|
eprintf (" as a goal.\n");
|
|
|
|
indentPrint ();
|
2004-08-19 12:37:41 +01:00
|
|
|
eprintf
|
|
|
|
("* If all goals can be bound, this constitutes an attack.\n");
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
2004-08-19 14:09:35 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* We say that a state exists for secrecy, but we don't really test wheter the claim can
|
|
|
|
* be reached (without reaching the attack).
|
|
|
|
*/
|
|
|
|
cl->count = statesIncrease (cl->count);
|
2004-08-20 11:52:40 +01:00
|
|
|
goal_add (rd->message, 0, cl->ev, 0); // Assumption that all claims are in run 0
|
2004-08-14 20:19:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-18 21:22:33 +01:00
|
|
|
//! Count a false claim
|
|
|
|
void
|
|
|
|
count_false ()
|
|
|
|
{
|
|
|
|
current_claim->failed = statesIncrease (current_claim->failed);
|
|
|
|
}
|
|
|
|
|
2004-08-11 13:08:10 +01:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Main logic core
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
2004-08-18 21:22:33 +01:00
|
|
|
//! Check properties
|
|
|
|
int
|
|
|
|
property_check ()
|
|
|
|
{
|
|
|
|
int flag;
|
2004-08-27 19:09:09 +01:00
|
|
|
int attack_this;
|
2004-08-18 21:22:33 +01:00
|
|
|
|
|
|
|
flag = 1;
|
2004-08-27 18:25:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* By the way the claim is handled, this automatically means a flaw.
|
|
|
|
*/
|
|
|
|
count_false ();
|
|
|
|
if (sys->output == ATTACK)
|
2004-08-28 10:24:30 +01:00
|
|
|
dotSemiState ();
|
2004-08-27 19:09:09 +01:00
|
|
|
// Store attack length if shorter
|
|
|
|
attack_this = get_trace_length ();
|
|
|
|
if (attack_this < attack_length)
|
|
|
|
{
|
|
|
|
// Shortest attack
|
|
|
|
attack_length = attack_this;
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
2004-08-27 19:18:16 +01:00
|
|
|
eprintf ("New shortest attack found with trace length %i.\n",
|
|
|
|
attack_length);
|
2004-08-27 19:09:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-18 21:22:33 +01:00
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
2004-08-11 10:51:17 +01:00
|
|
|
//! Main recursive procedure for Arachne
|
|
|
|
int
|
2004-08-11 15:09:12 +01:00
|
|
|
iterate ()
|
2004-08-11 12:22:20 +01:00
|
|
|
{
|
2004-08-11 22:04:52 +01:00
|
|
|
int flag;
|
2004-08-11 13:08:10 +01:00
|
|
|
|
2004-08-11 22:04:52 +01:00
|
|
|
flag = 1;
|
2004-08-19 14:09:35 +01:00
|
|
|
if (!prune_theorems ())
|
2004-08-11 22:04:52 +01:00
|
|
|
{
|
2004-08-27 16:02:33 +01:00
|
|
|
if (!prune_claim_specifics ())
|
2004-08-19 14:09:35 +01:00
|
|
|
{
|
2004-08-27 16:02:33 +01:00
|
|
|
if (!prune_bounds ())
|
|
|
|
{
|
|
|
|
Binding b;
|
2004-08-11 13:08:10 +01:00
|
|
|
|
2004-08-27 16:02:33 +01:00
|
|
|
/**
|
|
|
|
* Not pruned: count
|
|
|
|
*/
|
2004-08-11 22:04:52 +01:00
|
|
|
|
2004-08-27 16:02:33 +01:00
|
|
|
sys->states = statesIncrease (sys->states);
|
2004-08-19 14:09:35 +01:00
|
|
|
|
2004-08-27 16:02:33 +01:00
|
|
|
/**
|
|
|
|
* Check whether its a final state (i.e. all goals bound)
|
2004-08-19 14:09:35 +01:00
|
|
|
*/
|
2004-08-27 16:02:33 +01:00
|
|
|
|
|
|
|
b = select_goal ();
|
|
|
|
if (b == NULL)
|
2004-08-19 14:09:35 +01:00
|
|
|
{
|
2004-08-27 16:02:33 +01:00
|
|
|
/*
|
|
|
|
* all goals bound, check for property
|
|
|
|
*/
|
|
|
|
if (sys->output == PROOF)
|
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("All goals are now bound.\n");
|
|
|
|
}
|
|
|
|
sys->claims = statesIncrease (sys->claims);
|
2004-08-27 18:35:23 +01:00
|
|
|
current_claim->count =
|
|
|
|
statesIncrease (current_claim->count);
|
2004-08-27 16:02:33 +01:00
|
|
|
flag = property_check ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* bind this goal in all possible ways and iterate
|
|
|
|
*/
|
|
|
|
flag = bind_goal (b);
|
2004-08-19 14:09:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-27 16:02:33 +01:00
|
|
|
// Pruned because of bound!
|
|
|
|
current_claim->complete = 0;
|
2004-08-19 11:46:27 +01:00
|
|
|
}
|
2004-08-11 22:04:52 +01:00
|
|
|
}
|
2004-08-11 13:08:10 +01:00
|
|
|
}
|
2004-08-18 19:22:59 +01:00
|
|
|
|
2004-08-18 19:41:49 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (5) && !flag)
|
2004-08-18 19:22:59 +01:00
|
|
|
{
|
|
|
|
warning ("Flag has turned 0!");
|
|
|
|
}
|
2004-08-18 19:41:49 +01:00
|
|
|
#endif
|
2004-08-11 22:04:52 +01:00
|
|
|
return flag;
|
2004-08-11 12:22:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Main code for Arachne
|
|
|
|
/**
|
|
|
|
* For this test, we manually set up some stuff.
|
2004-08-12 12:35:13 +01:00
|
|
|
*
|
|
|
|
* But later, this will just iterate over all claims.
|
2004-08-11 12:22:20 +01:00
|
|
|
*/
|
|
|
|
int
|
2004-08-11 15:09:12 +01:00
|
|
|
arachne ()
|
2004-08-11 10:51:17 +01:00
|
|
|
{
|
2004-08-14 16:59:14 +01:00
|
|
|
Claimlist cl;
|
2004-08-12 12:35:13 +01:00
|
|
|
|
2004-08-13 21:56:51 +01:00
|
|
|
int print_send (Protocol p, Role r, Roledef rd, int index)
|
|
|
|
{
|
|
|
|
eprintf ("IRS: ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf (", %i, ", index);
|
|
|
|
roledefPrint (rd);
|
|
|
|
eprintf ("\n");
|
2004-08-18 15:06:14 +01:00
|
|
|
return 1;
|
2004-08-13 21:56:51 +01:00
|
|
|
}
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
int determine_encrypt_max (Protocol p, Role r, Roledef rd, int index)
|
|
|
|
{
|
|
|
|
int tlevel;
|
|
|
|
|
|
|
|
tlevel = term_encryption_level (rd->message);
|
|
|
|
if (tlevel > max_encryption_level)
|
|
|
|
max_encryption_level = tlevel;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-08-19 13:47:53 +01:00
|
|
|
/*
|
|
|
|
* set up claim role(s)
|
|
|
|
*/
|
|
|
|
|
2004-08-27 19:26:19 +01:00
|
|
|
if (sys->switchRuns == 0)
|
|
|
|
{
|
|
|
|
// No real checking.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-08-19 13:47:53 +01:00
|
|
|
if (sys->maxruns > 0)
|
|
|
|
{
|
|
|
|
error ("Something is wrong, number of runs >0.");
|
|
|
|
}
|
|
|
|
|
|
|
|
num_regular_runs = 0;
|
|
|
|
num_intruder_runs = 0;
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
max_encryption_level = 0;
|
|
|
|
iterate_role_sends (determine_encrypt_max);
|
|
|
|
|
2004-08-14 17:12:32 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (1))
|
|
|
|
{
|
2004-08-18 15:06:14 +01:00
|
|
|
eprintf ("Maximum encryption level: %i\n", max_encryption_level);
|
2004-08-14 17:12:32 +01:00
|
|
|
iterate_role_sends (print_send);
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-13 21:56:51 +01:00
|
|
|
|
2004-08-13 12:11:59 +01:00
|
|
|
indentDepth = 0;
|
2004-10-14 16:25:28 +01:00
|
|
|
proofDepth = 0;
|
2004-08-14 16:59:14 +01:00
|
|
|
cl = sys->claimlist;
|
|
|
|
while (cl != NULL)
|
|
|
|
{
|
2004-08-15 17:44:54 +01:00
|
|
|
/**
|
|
|
|
* Check each claim
|
|
|
|
*/
|
2004-08-14 16:59:14 +01:00
|
|
|
Protocol p;
|
|
|
|
Role r;
|
2004-08-11 12:22:20 +01:00
|
|
|
|
2004-08-15 17:44:54 +01:00
|
|
|
if (sys->switchClaimToCheck == NULL
|
|
|
|
|| sys->switchClaimToCheck == cl->type)
|
2004-08-14 17:12:32 +01:00
|
|
|
{
|
2004-08-19 13:47:53 +01:00
|
|
|
int run;
|
|
|
|
|
2004-08-19 11:46:27 +01:00
|
|
|
current_claim = cl;
|
2004-08-27 19:09:09 +01:00
|
|
|
attack_length = INT_MAX;
|
2004-08-19 14:09:35 +01:00
|
|
|
cl->complete = 1;
|
2004-08-15 17:44:54 +01:00
|
|
|
p = (Protocol) cl->protocol;
|
|
|
|
r = (Role) cl->role;
|
2004-08-19 11:46:27 +01:00
|
|
|
|
|
|
|
if (sys->output == PROOF)
|
2004-08-15 17:44:54 +01:00
|
|
|
{
|
|
|
|
indentPrint ();
|
|
|
|
eprintf ("Testing Claim ");
|
|
|
|
termPrint (cl->type);
|
2004-08-19 11:46:27 +01:00
|
|
|
eprintf (" from ");
|
2004-08-19 13:35:51 +01:00
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (", ");
|
|
|
|
termPrint (r->nameterm);
|
2004-08-15 17:44:54 +01:00
|
|
|
eprintf (" at index %i.\n", cl->ev);
|
|
|
|
}
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth++;
|
2004-08-19 14:09:35 +01:00
|
|
|
run = semiRunCreate (p, r);
|
2004-08-19 13:47:53 +01:00
|
|
|
proof_suppose_run (run, 0, cl->ev + 1);
|
|
|
|
add_read_goals (run, 0, cl->ev + 1);
|
2004-08-14 20:19:23 +01:00
|
|
|
|
2004-08-15 17:44:54 +01:00
|
|
|
/**
|
|
|
|
* Add specific goal info
|
|
|
|
*/
|
|
|
|
add_claim_specifics (cl,
|
2004-08-19 13:47:53 +01:00
|
|
|
roledef_shift (sys->runs[run].start, cl->ev));
|
2004-08-14 16:59:14 +01:00
|
|
|
#ifdef DEBUG
|
2004-08-15 17:44:54 +01:00
|
|
|
if (DEBUGL (5))
|
|
|
|
{
|
|
|
|
printSemiState ();
|
|
|
|
}
|
2004-08-14 16:59:14 +01:00
|
|
|
#endif
|
2004-08-19 15:49:03 +01:00
|
|
|
// Iterate
|
2004-08-15 17:44:54 +01:00
|
|
|
iterate ();
|
2004-08-14 16:59:14 +01:00
|
|
|
|
2004-08-15 17:44:54 +01:00
|
|
|
//! Destroy
|
2004-08-19 15:49:03 +01:00
|
|
|
while (sys->bindings != NULL)
|
|
|
|
{
|
2004-10-18 14:04:34 +01:00
|
|
|
goal_remove_last (1);
|
2004-08-19 15:49:03 +01:00
|
|
|
}
|
2004-08-15 17:44:54 +01:00
|
|
|
while (sys->maxruns > 0)
|
|
|
|
{
|
2004-08-19 13:47:53 +01:00
|
|
|
semiRunDestroy ();
|
2004-08-15 17:44:54 +01:00
|
|
|
}
|
2004-08-19 13:35:51 +01:00
|
|
|
indentDepth--;
|
2004-08-14 20:19:23 +01:00
|
|
|
}
|
2004-08-14 16:59:14 +01:00
|
|
|
// next
|
|
|
|
cl = cl->next;
|
|
|
|
}
|
2004-08-11 10:51:17 +01:00
|
|
|
}
|