BROKEN
- Working on new algorithm. Some memory error can occur.
This commit is contained in:
parent
c5695d6fe8
commit
b2d21f0a8a
506
src/arachne.c
506
src/arachne.c
@ -36,6 +36,7 @@ Role I_E;
|
|||||||
Role I_D;
|
Role I_D;
|
||||||
|
|
||||||
static int indentDepth;
|
static int indentDepth;
|
||||||
|
static int max_encryption_level;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static char *explanation; // Pointer to a string that describes what we just tried to do
|
static char *explanation; // Pointer to a string that describes what we just tried to do
|
||||||
@ -68,6 +69,7 @@ int iterate ();
|
|||||||
void
|
void
|
||||||
arachneInit (const System mysys)
|
arachneInit (const System mysys)
|
||||||
{
|
{
|
||||||
|
Term GVT;
|
||||||
Roledef rd = NULL;
|
Roledef rd = NULL;
|
||||||
Termlist tl, know0;
|
Termlist tl, know0;
|
||||||
|
|
||||||
@ -102,8 +104,9 @@ arachneInit (const System mysys)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
INTRUDER = protocolCreate (makeGlobalConstant (" INTRUDER "));
|
INTRUDER = protocolCreate (makeGlobalConstant (" INTRUDER "));
|
||||||
|
GVT = makeGlobalVariable ("GlobalVariable");
|
||||||
|
|
||||||
add_event (SEND, NULL);
|
add_event (SEND, GVT);
|
||||||
I_M = add_role ("I_M: Atomic message");
|
I_M = add_role ("I_M: Atomic message");
|
||||||
|
|
||||||
add_event (READ, NULL);
|
add_event (READ, NULL);
|
||||||
@ -148,6 +151,18 @@ indentPrint ()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Print indented binding
|
||||||
|
void
|
||||||
|
binding_indent_print (Binding b, int flag)
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
if (flag)
|
||||||
|
eprintf ("!! ");
|
||||||
|
binding_print (b);
|
||||||
|
eprintf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Iterate but discard the info of the termlist
|
//! Iterate but discard the info of the termlist
|
||||||
int
|
int
|
||||||
mgu_iterate (const Termlist tl)
|
mgu_iterate (const Termlist tl)
|
||||||
@ -161,7 +176,7 @@ mgu_iterate (const Termlist tl)
|
|||||||
*@returns The number of goals added (for destructions)
|
*@returns The number of goals added (for destructions)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
add_read_goals (const int run, int old, int new)
|
add_read_goals (const int run, const int old, const int new)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
int i;
|
int i;
|
||||||
@ -170,11 +185,13 @@ add_read_goals (const int run, int old, int new)
|
|||||||
sys->runs[run].length = new;
|
sys->runs[run].length = new;
|
||||||
i = old;
|
i = old;
|
||||||
rd = roledef_shift (sys->runs[run].start, i);
|
rd = roledef_shift (sys->runs[run].start, i);
|
||||||
while (i < new)
|
count = 0;
|
||||||
|
while (i < new && rd != NULL)
|
||||||
{
|
{
|
||||||
if (rd->type == READ)
|
if (rd->type == READ)
|
||||||
{
|
{
|
||||||
goal_add (rd->message, run, i);
|
goal_add (rd->message, run, i);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
rd = rd->next;
|
rd = rd->next;
|
||||||
i++;
|
i++;
|
||||||
@ -186,7 +203,7 @@ add_read_goals (const int run, int old, int new)
|
|||||||
void
|
void
|
||||||
remove_read_goals (int n)
|
remove_read_goals (int n)
|
||||||
{
|
{
|
||||||
while (n>0)
|
while (n > 0)
|
||||||
{
|
{
|
||||||
goal_remove_last ();
|
goal_remove_last ();
|
||||||
n--;
|
n--;
|
||||||
@ -301,43 +318,59 @@ bind_existing_to_goal (const Binding b, const int index, const int run,
|
|||||||
|
|
||||||
int subterm_iterate (Termlist substlist, Termlist keylist)
|
int subterm_iterate (Termlist substlist, Termlist keylist)
|
||||||
{
|
{
|
||||||
int keycount;
|
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DEBUGL (5))
|
|
||||||
{
|
|
||||||
indentPrint ();
|
|
||||||
eprintf ("Adding key list : ");
|
|
||||||
termlistPrint (keylist);
|
|
||||||
eprintf ("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
flag = 1;
|
flag = 1;
|
||||||
keycount = 0;
|
if (goal_bind (b, run, index))
|
||||||
while (flag && keylist != NULL)
|
|
||||||
{
|
{
|
||||||
int keyrun;
|
int keycount;
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
goal_add (keylist->term, b->run_to, b->ev_to);
|
#ifdef DEBUG
|
||||||
keylist = keylist->next;
|
if (DEBUGL (5))
|
||||||
keycount++;
|
{
|
||||||
|
binding_indent_print (b, 0);
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Adding key list for subterm iteration: ");
|
||||||
|
termlistPrint (keylist);
|
||||||
|
eprintf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
keycount = 0;
|
||||||
|
tl = keylist;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
int keyrun;
|
||||||
|
|
||||||
|
goal_add (tl->term, b->run_to, b->ev_to);
|
||||||
|
tl = tl->next;
|
||||||
|
keycount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = flag && iterate ();
|
||||||
|
|
||||||
|
while (keycount > 0)
|
||||||
|
{
|
||||||
|
goal_remove_last ();
|
||||||
|
keycount--;
|
||||||
|
}
|
||||||
|
termlistDestroy (keylist);
|
||||||
}
|
}
|
||||||
flag = flag && iterate ();
|
else
|
||||||
while (keycount > 0)
|
|
||||||
{
|
{
|
||||||
goal_remove_last ();
|
#ifdef DEBUG
|
||||||
keycount--;
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Aborted binding existing run because of cycle.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
flag = 0;
|
||||||
}
|
}
|
||||||
termlistDestroy (keylist);
|
goal_unbind (b);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interm_iterate (Termlist substlist)
|
|
||||||
{
|
|
||||||
iterate ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------
|
//----------------------------
|
||||||
// Roledef entry
|
// Roledef entry
|
||||||
rd = roledef_shift (sys->runs[run].start, index);
|
rd = roledef_shift (sys->runs[run].start, index);
|
||||||
@ -345,13 +378,9 @@ bind_existing_to_goal (const Binding b, const int index, const int run,
|
|||||||
// Fix length
|
// Fix length
|
||||||
old_length = sys->runs[run].length;
|
old_length = sys->runs[run].length;
|
||||||
if ((index + 1) > old_length)
|
if ((index + 1) > old_length)
|
||||||
{
|
newgoals = add_read_goals (run, old_length, index + 1);
|
||||||
newgoals = add_read_goals (run, old_length, index+1);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
newgoals = 0;
|
||||||
newgoals = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (DEBUGL (3))
|
if (DEBUGL (3))
|
||||||
@ -361,30 +390,8 @@ bind_existing_to_goal (const Binding b, const int index, const int run,
|
|||||||
e_term1 = b->term;
|
e_term1 = b->term;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (goal_bind (b, run, index))
|
flag = termMguSubTerm (b->term, rd->message,
|
||||||
{
|
subterm_iterate, sys->know->inverses, NULL);
|
||||||
if (subterm)
|
|
||||||
{
|
|
||||||
flag = termMguSubTerm (b->term, rd->message,
|
|
||||||
subterm_iterate, sys->know->inverses, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = termMguInTerm (b->term, rd->message,
|
|
||||||
interm_iterate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DEBUGL (5))
|
|
||||||
{
|
|
||||||
indentPrint ();
|
|
||||||
eprintf ("Aborted binding existing run because of cycle.\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
goal_unbind (b);
|
|
||||||
// Reset length
|
// Reset length
|
||||||
remove_read_goals (newgoals);
|
remove_read_goals (newgoals);
|
||||||
sys->runs[run].length = old_length;
|
sys->runs[run].length = old_length;
|
||||||
@ -404,7 +411,7 @@ bind_existing_run (const Binding b, const Protocol p, const Role r,
|
|||||||
indentPrint ();
|
indentPrint ();
|
||||||
eprintf ("Trying to bind ");
|
eprintf ("Trying to bind ");
|
||||||
termPrint (b->term);
|
termPrint (b->term);
|
||||||
eprintf (" to an existing instance of ");
|
eprintf (" to an existing (of %i runs) instance of ", sys->maxruns);
|
||||||
termPrint (p->nameterm);
|
termPrint (p->nameterm);
|
||||||
eprintf (", ");
|
eprintf (", ");
|
||||||
termPrint (r->nameterm);
|
termPrint (r->nameterm);
|
||||||
@ -433,7 +440,7 @@ bind_new_run (const Binding b, const Protocol p, const Role r,
|
|||||||
|
|
||||||
roleInstance (sys, p, r, NULL, NULL);
|
roleInstance (sys, p, r, NULL, NULL);
|
||||||
run = sys->maxruns - 1;
|
run = sys->maxruns - 1;
|
||||||
newgoals = add_read_goals (run, 0, index+1);
|
newgoals = add_read_goals (run, 0, index + 1);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (DEBUGL (4))
|
if (DEBUGL (4))
|
||||||
{
|
{
|
||||||
@ -447,9 +454,9 @@ bind_new_run (const Binding b, const Protocol p, const Role r,
|
|||||||
eprintf (", run %i (subterm:%i)\n", run, subterm);
|
eprintf (", run %i (subterm:%i)\n", run, subterm);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
flag = bind_existing_to_goal (b, index, run, subterm);
|
flag = bind_existing_to_goal (b, index, run, 1);
|
||||||
roleInstanceDestroy (sys);
|
|
||||||
remove_read_goals (newgoals);
|
remove_read_goals (newgoals);
|
||||||
|
roleInstanceDestroy (sys);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,11 +468,9 @@ printSemiState ()
|
|||||||
int open;
|
int open;
|
||||||
List bl;
|
List bl;
|
||||||
|
|
||||||
int binding_indent_print (void *data)
|
int binding_state_print (void *dt)
|
||||||
{
|
{
|
||||||
indentPrint ();
|
binding_indent_print ((Binding) dt, 1);
|
||||||
eprintf ("!! ");
|
|
||||||
binding_print (data);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +520,7 @@ printSemiState ()
|
|||||||
{
|
{
|
||||||
indentPrint ();
|
indentPrint ();
|
||||||
eprintf ("!!\n");
|
eprintf ("!!\n");
|
||||||
list_iterate (sys->bindings, binding_indent_print);
|
list_iterate (sys->bindings, binding_state_print);
|
||||||
}
|
}
|
||||||
indentPrint ();
|
indentPrint ();
|
||||||
eprintf ("!!\n");
|
eprintf ("!!\n");
|
||||||
@ -536,7 +541,9 @@ select_goal ()
|
|||||||
{
|
{
|
||||||
List bl;
|
List bl;
|
||||||
Binding best;
|
Binding best;
|
||||||
|
float min_constrain;
|
||||||
|
|
||||||
|
min_constrain = 2; // 1 is the maximum, but we want to initialize it.
|
||||||
best = NULL;
|
best = NULL;
|
||||||
bl = sys->bindings;
|
bl = sys->bindings;
|
||||||
while (bl != NULL)
|
while (bl != NULL)
|
||||||
@ -546,141 +553,20 @@ select_goal ()
|
|||||||
b = (Binding) bl->data;
|
b = (Binding) bl->data;
|
||||||
if (!b->done)
|
if (!b->done)
|
||||||
{
|
{
|
||||||
// For now, we simply take the first encountered goal
|
float cons;
|
||||||
return b;
|
|
||||||
|
cons = term_constrain_level (b->term);
|
||||||
|
if (cons < min_constrain)
|
||||||
|
{
|
||||||
|
min_constrain = cons;
|
||||||
|
best = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bl = bl->next;
|
bl = bl->next;
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Bind a regular goal
|
|
||||||
int
|
|
||||||
bind_goal_regular (const Binding b)
|
|
||||||
{
|
|
||||||
int flag;
|
|
||||||
/*
|
|
||||||
* This is a local function so we have access to goal
|
|
||||||
*/
|
|
||||||
int bind_this_role_send (Protocol p, Role r, Roledef rd, int index)
|
|
||||||
{
|
|
||||||
int test_unification (Termlist substlist)
|
|
||||||
{
|
|
||||||
// A unification exists; return the signal
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == INTRUDER)
|
|
||||||
{
|
|
||||||
/* only bind to regular runs */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 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 (!termMguInTerm (b->term, rd->message, test_unification))
|
|
||||||
{
|
|
||||||
// A good candidate
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DEBUGL (5))
|
|
||||||
{
|
|
||||||
indentPrint ();
|
|
||||||
eprintf ("Term ");
|
|
||||||
termPrint (b->term);
|
|
||||||
eprintf (" can possibly be bound by role ");
|
|
||||||
termPrint (r->nameterm);
|
|
||||||
eprintf (", index %i\n", index);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (bind_new_run (b, p, r, index, 0) &&
|
|
||||||
bind_existing_run (b, p, r, index, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Cannot unify: no attacks
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to all possible sends or intruder node;
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DEBUGL (5))
|
|
||||||
{
|
|
||||||
indentPrint ();
|
|
||||||
eprintf ("Try regular role send.\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
flag = iterate_role_sends (bind_this_role_send);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (DEBUGL (5))
|
|
||||||
{
|
|
||||||
indentPrint ();
|
|
||||||
eprintf ("Try intruder send.\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return flag;
|
|
||||||
// return (flag && add_intruder_goal_iterate (b));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Bind an intruder goal to a regular run
|
|
||||||
int
|
|
||||||
bind_intruder_to_regular (Binding b)
|
|
||||||
{
|
|
||||||
int bind_this_roleevent (Protocol p, Role r, Roledef rd, int index)
|
|
||||||
{
|
|
||||||
int cannotUnify;
|
|
||||||
|
|
||||||
int test_unification (Termlist substlist, Termlist keylist)
|
|
||||||
{
|
|
||||||
// Signal that unification is possible.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note that we only bind to regular runs here
|
|
||||||
*/
|
|
||||||
if (p == INTRUDER)
|
|
||||||
{
|
|
||||||
return 1; // don't abort scans
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Test for subterm unification
|
|
||||||
if (termMguSubTerm
|
|
||||||
(b->term, rd->message, test_unification,
|
|
||||||
sys->know->inverses, NULL))
|
|
||||||
{
|
|
||||||
// cannot unify
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Either from an existing, or from a new run.
|
|
||||||
*/
|
|
||||||
return (bind_new_run (b, p, r, index, 1)
|
|
||||||
&& bind_existing_run (b, p, r, index, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to all possible sends?
|
|
||||||
return iterate_role_sends (bind_this_roleevent);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Bind an intruder goal by intruder construction
|
//! Bind an intruder goal by intruder construction
|
||||||
/**
|
/**
|
||||||
* Handles the case where the intruder constructs a composed term himself.
|
* Handles the case where the intruder constructs a composed term himself.
|
||||||
@ -696,9 +582,9 @@ bind_intruder_to_construct (const Binding b)
|
|||||||
flag = 1;
|
flag = 1;
|
||||||
term = b->term;
|
term = b->term;
|
||||||
/**
|
/**
|
||||||
* Two options.
|
* Three options.
|
||||||
*
|
*
|
||||||
* 1. Constructed from composite terms
|
* 1. Constructed from smaller composite terms
|
||||||
*/
|
*/
|
||||||
if (!realTermLeaf (term))
|
if (!realTermLeaf (term))
|
||||||
{
|
{
|
||||||
@ -706,6 +592,7 @@ bind_intruder_to_construct (const Binding b)
|
|||||||
|
|
||||||
if (realTermTuple (term))
|
if (realTermTuple (term))
|
||||||
{
|
{
|
||||||
|
warning ("Goal that is a tuple should not occur!");
|
||||||
// tuple construction
|
// tuple construction
|
||||||
t1 = term->left.op1;
|
t1 = term->left.op1;
|
||||||
t2 = term->right.op2;
|
t2 = term->right.op2;
|
||||||
@ -719,12 +606,61 @@ bind_intruder_to_construct (const Binding b)
|
|||||||
|
|
||||||
goal_add (t1, b->run_to, b->ev_to);
|
goal_add (t1, b->run_to, b->ev_to);
|
||||||
goal_add (t2, b->run_to, b->ev_to);
|
goal_add (t2, b->run_to, b->ev_to);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (3))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Constructing ");
|
||||||
|
termPrint (term);
|
||||||
|
eprintf (" from smaller terms ");
|
||||||
|
termPrint (t1);
|
||||||
|
eprintf (" and ");
|
||||||
|
termPrint (t2);
|
||||||
|
eprintf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
flag = flag && iterate ();
|
flag = flag && iterate ();
|
||||||
goal_remove_last ();
|
goal_remove_last ();
|
||||||
goal_remove_last ();
|
goal_remove_last ();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 2. Retrieved from M_0
|
* 2. Constructed from bigger term and decryption key
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if (!realTermLeaf (term))
|
||||||
|
{
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
Term t1, t2;
|
||||||
|
|
||||||
|
t1 = term->left.op;
|
||||||
|
t2 = term->right.key;
|
||||||
|
|
||||||
|
goal_add (t1, b->run_to, b->ev_to);
|
||||||
|
goal_add (t2, b->run_to, b->ev_to);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (3))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Deriving ");
|
||||||
|
termPrint (term);
|
||||||
|
eprintf (" from encrypted term ");
|
||||||
|
termPrint (t1);
|
||||||
|
eprintf (" and key ");
|
||||||
|
termPrint (t2);
|
||||||
|
eprintf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
flag = flag && iterate ();
|
||||||
|
goal_remove_last ();
|
||||||
|
goal_remove_last ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3. Retrieved from M_0
|
||||||
*/
|
*/
|
||||||
m0tl = knowledgeSet (sys->know);
|
m0tl = knowledgeSet (sys->know);
|
||||||
while (flag && m0tl != NULL)
|
while (flag && m0tl != NULL)
|
||||||
@ -747,15 +683,20 @@ bind_intruder_to_construct (const Binding b)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (DEBUGL (3))
|
if (DEBUGL (3))
|
||||||
{
|
{
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
binding_indent_print (b, 0);
|
||||||
|
}
|
||||||
indentPrint ();
|
indentPrint ();
|
||||||
eprintf ("Retrieving ");
|
eprintf ("Retrieving ");
|
||||||
termPrint (term);
|
termPrint (term);
|
||||||
eprintf (" from the initial knowledge.\n");
|
eprintf (" from the initial knowledge.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
iterate ();
|
flag = flag && iterate ();
|
||||||
}
|
}
|
||||||
goal_unbind (b);
|
goal_unbind (b);
|
||||||
|
roleInstanceDestroy (sys);
|
||||||
termlistSubstReset (subst);
|
termlistSubstReset (subst);
|
||||||
termlistDelete (subst);
|
termlistDelete (subst);
|
||||||
}
|
}
|
||||||
@ -770,57 +711,104 @@ bind_intruder_to_construct (const Binding b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Bind an intruder goal
|
//! Bind a regular goal
|
||||||
/**
|
|
||||||
* Computes F2 as in Athena explanations.
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
bind_goal_intruder (const Binding b)
|
bind_goal_regular (const Binding b)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Special case: when the intruder can bind it to the initial knowledge.
|
|
||||||
*/
|
|
||||||
Termlist tl;
|
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
flag = 1;
|
/*
|
||||||
tl = knowledgeSet (sys->know);
|
* This is a local function so we have access to goal
|
||||||
while (flag && tl != NULL)
|
*/
|
||||||
|
int bind_this_role_send (Protocol p, Role r, Roledef rd, int index)
|
||||||
|
{
|
||||||
|
int test_unification (Termlist substlist)
|
||||||
{
|
{
|
||||||
int hasvars;
|
// A unification exists; return the signal
|
||||||
Termlist substlist;
|
return 0;
|
||||||
|
|
||||||
substlist = termMguTerm (tl->term, b->term);
|
|
||||||
if (substlist != MGUFAIL)
|
|
||||||
{
|
|
||||||
// This seems to work
|
|
||||||
flag = flag && iterate ();
|
|
||||||
termlistSubstReset (substlist);
|
|
||||||
termlistDelete (substlist);
|
|
||||||
}
|
|
||||||
tl = tl->next;
|
|
||||||
}
|
}
|
||||||
termlistDelete (tl);
|
|
||||||
return (flag && bind_intruder_to_regular (b) &&
|
// Test for interm unification
|
||||||
bind_intruder_to_construct (b));
|
#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
|
||||||
|
(b->term, rd->message, test_unification, sys->know->inverses, NULL))
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
// A good candidate
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Term ");
|
||||||
|
termPrint (b->term);
|
||||||
|
eprintf (" can possibly be bound by role ");
|
||||||
|
termPrint (r->nameterm);
|
||||||
|
eprintf (", index %i\n", index);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Bind to existing run
|
||||||
|
flag = bind_existing_run (b, p, r, index, 1);
|
||||||
|
if (p != INTRUDER)
|
||||||
|
{
|
||||||
|
// No intruder: bind to new run
|
||||||
|
flag = flag && bind_new_run (b, p, r, index, 1);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cannot unify: no attacks
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to all possible sends or intruder node;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Try regular role send.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
flag = iterate_role_sends (bind_this_role_send);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Try intruder send.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Other option: bind to term construction
|
||||||
|
|
||||||
|
flag = flag && bind_intruder_to_construct (b);
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//! Bind a goal in all possible ways
|
//! Bind a goal in all possible ways
|
||||||
int
|
int
|
||||||
bind_goal (const Binding b)
|
bind_goal (const Binding b)
|
||||||
{
|
{
|
||||||
if (!b->done)
|
if (!b->done)
|
||||||
{
|
{
|
||||||
int flag;
|
return bind_goal_regular (b);
|
||||||
if (sys->runs[b->run_to].protocol == INTRUDER)
|
|
||||||
{
|
|
||||||
flag = bind_goal_intruder (b);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flag = bind_goal_regular (b);
|
|
||||||
}
|
|
||||||
return flag;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -906,6 +894,19 @@ prune ()
|
|||||||
tl = tl->next;
|
tl = tl->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for c-minimality
|
||||||
|
if (!bindings_c_minimal ())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (3))
|
||||||
|
{
|
||||||
|
indentPrint ();
|
||||||
|
eprintf ("Pruned because this is not <=c-minimal.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,7 +977,7 @@ iterate ()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
b = select_goal ();
|
b = select_goal ();
|
||||||
if (b != NULL)
|
if (b == NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* all goals bound, check for property
|
* all goals bound, check for property
|
||||||
@ -1046,11 +1047,26 @@ arachne ()
|
|||||||
eprintf (", %i, ", index);
|
eprintf (", %i, ", index);
|
||||||
roledefPrint (rd);
|
roledefPrint (rd);
|
||||||
eprintf ("\n");
|
eprintf ("\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_encryption_level = 0;
|
||||||
|
iterate_role_sends (determine_encrypt_max);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (DEBUGL (1))
|
if (DEBUGL (1))
|
||||||
{
|
{
|
||||||
|
eprintf ("Maximum encryption level: %i\n", max_encryption_level);
|
||||||
iterate_role_sends (print_send);
|
iterate_role_sends (print_send);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1123,13 +1139,3 @@ arachne ()
|
|||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Done: add_read_goals, remove_read_goals.
|
|
||||||
*
|
|
||||||
* Now we must make the new algorithm.
|
|
||||||
* At role instance (of e.g. claim), fix add_read_goals.
|
|
||||||
*
|
|
||||||
* Iterate on roles. Create new roles for intruder (encrypt RRS, decrypt RRS, and M_0 S)
|
|
||||||
* Check for bindings_c_minimal.
|
|
||||||
*/
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
|
||||||
static System sys;
|
static System sys;
|
||||||
static int* graph;
|
static int *graph;
|
||||||
static int nodes;
|
static int nodes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -78,7 +78,8 @@ bindingDone ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Destroy graph
|
//! Destroy graph
|
||||||
void goal_graph_destroy ()
|
void
|
||||||
|
goal_graph_destroy ()
|
||||||
{
|
{
|
||||||
if (graph != NULL)
|
if (graph != NULL)
|
||||||
{
|
{
|
||||||
@ -88,13 +89,14 @@ void goal_graph_destroy ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Compute unclosed graph
|
//! Compute unclosed graph
|
||||||
void goal_graph_create ()
|
void
|
||||||
|
goal_graph_create ()
|
||||||
{
|
{
|
||||||
int run, ev;
|
int run, ev;
|
||||||
List bl;
|
List bl;
|
||||||
|
|
||||||
goal_graph_destroy ();
|
goal_graph_destroy ();
|
||||||
|
|
||||||
// Setup graph
|
// Setup graph
|
||||||
nodes = node_count ();
|
nodes = node_count ();
|
||||||
graph = memAlloc ((nodes * nodes) * sizeof (int));
|
graph = memAlloc ((nodes * nodes) * sizeof (int));
|
||||||
@ -120,14 +122,18 @@ void goal_graph_create ()
|
|||||||
Binding b;
|
Binding b;
|
||||||
|
|
||||||
b = (Binding) bl->data;
|
b = (Binding) bl->data;
|
||||||
|
if (b->done)
|
||||||
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (graph_nodes (nodes, b->run_from, b->ev_from, b->run_to, b->ev_to) >=
|
if (graph_nodes
|
||||||
(nodes * nodes))
|
(nodes, b->run_from, b->ev_from, b->run_to,
|
||||||
error ("Node out of scope for %i,%i -> %i,%i.\n", b->run_from,
|
b->ev_to) >= (nodes * nodes))
|
||||||
b->ev_from, b->run_to, b->ev_to);
|
error ("Node out of scope for %i,%i -> %i,%i.\n", b->run_from,
|
||||||
|
b->ev_from, b->run_to, b->ev_to);
|
||||||
#endif
|
#endif
|
||||||
graph[graph_nodes (nodes, b->run_from, b->ev_from, b->run_to, b->ev_to)]
|
graph[graph_nodes
|
||||||
= 1;
|
(nodes, b->run_from, b->ev_from, b->run_to, b->ev_to)] = 1;
|
||||||
|
}
|
||||||
bl = bl->next;
|
bl = bl->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,13 +209,14 @@ graph_nodes (const int nodes, const int run1, const int ev1, const int run2,
|
|||||||
|
|
||||||
//! Print a binding (given a binding list pointer)
|
//! Print a binding (given a binding list pointer)
|
||||||
int
|
int
|
||||||
binding_print (void *bindany)
|
binding_print (const Binding b)
|
||||||
{
|
{
|
||||||
Binding b;
|
if (b->done)
|
||||||
|
eprintf ("Binding (%i,%i) --( ", b->run_from, b->ev_from);
|
||||||
b = (Binding) bindany;
|
else
|
||||||
eprintf ("Binding (%i,%i) --->> (%i,%i)\n", b->run_from, b->ev_from,
|
eprintf ("Unbound --( ");
|
||||||
b->run_to, b->ev_to);
|
termPrint (b->term);
|
||||||
|
eprintf (" )->> (%i,%i)", b->run_to, b->ev_to);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,51 +313,63 @@ goal_unbind (const Binding b)
|
|||||||
*
|
*
|
||||||
*@returns True, if it's okay. If false, it needs to be pruned.
|
*@returns True, if it's okay. If false, it needs to be pruned.
|
||||||
*/
|
*/
|
||||||
int bindings_c_minimal ()
|
int
|
||||||
|
bindings_c_minimal ()
|
||||||
{
|
{
|
||||||
List bl;
|
List bl;
|
||||||
|
|
||||||
// Ensure a state graph
|
// Ensure a state graph
|
||||||
goal_graph_create ();
|
if (graph == NULL)
|
||||||
|
{
|
||||||
|
goal_graph_create ();
|
||||||
|
// Recompute closure; does that work?
|
||||||
|
if (!warshall (graph, nodes))
|
||||||
|
{
|
||||||
|
// Hmm, cycle
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For all goals
|
// For all goals
|
||||||
bl = sys->bindings;
|
bl = sys->bindings;
|
||||||
while (bl != NULL)
|
while (bl != NULL)
|
||||||
{
|
{
|
||||||
Binding b;
|
Binding b;
|
||||||
int run;
|
|
||||||
int node_from;
|
|
||||||
|
|
||||||
b = (Binding) bl->data;
|
b = (Binding) bl->data;
|
||||||
node_from = node_number (b->run_from, b->ev_from);
|
if (b->done)
|
||||||
// Find all preceding events
|
|
||||||
for (run = 0; run <= sys->maxruns; run++)
|
|
||||||
{
|
{
|
||||||
int ev;
|
int run;
|
||||||
|
int node_from;
|
||||||
|
|
||||||
//!@todo hardcoded reference to step, should be length
|
node_from = node_number (b->run_from, b->ev_from);
|
||||||
for (ev = 0; run < sys->runs[run].step; ev++)
|
// Find all preceding events
|
||||||
|
for (run = 0; run <= sys->maxruns; run++)
|
||||||
{
|
{
|
||||||
int node_comp;
|
int ev;
|
||||||
|
|
||||||
node_comp = node_number (run, ev);
|
//!@todo hardcoded reference to step, should be length
|
||||||
if (graph[ graph_index (node_comp, node_from)] > 0)
|
for (ev = 0; run < sys->runs[run].step; ev++)
|
||||||
{
|
{
|
||||||
// this node is *before* the from node
|
int node_comp;
|
||||||
Roledef rd;
|
|
||||||
|
|
||||||
rd = roledef_shift (sys->runs[run].start, ev);
|
node_comp = node_number (run, ev);
|
||||||
if (termInTerm (rd->message, b->term))
|
if (graph[graph_index (node_comp, node_from)] > 0)
|
||||||
{
|
{
|
||||||
// This term already occurs as interm in a previous node!
|
// this node is *before* the from node
|
||||||
return 0;
|
Roledef rd;
|
||||||
|
|
||||||
|
rd = roledef_shift (sys->runs[run].start, ev);
|
||||||
|
if (termInTerm (rd->message, b->term))
|
||||||
|
{
|
||||||
|
// This term already occurs as interm in a previous node!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bl = bl->next;
|
bl = bl->next;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
struct binding
|
struct binding
|
||||||
{
|
{
|
||||||
int done; //!< Iff true, it is bound
|
int done; //!< Iff true, it is bound
|
||||||
int child; //!< Signifies some tuple unfolding, to remove created bindings.
|
int child; //!< Signifies some tuple unfolding, to remove created bindings.
|
||||||
|
|
||||||
int run_from;
|
int run_from;
|
||||||
int ev_from;
|
int ev_from;
|
||||||
@ -34,7 +34,7 @@ int node_count ();
|
|||||||
int node_number (int run, int ev);
|
int node_number (int run, int ev);
|
||||||
|
|
||||||
|
|
||||||
int binding_print (void *bindany);
|
int binding_print (Binding b);
|
||||||
|
|
||||||
void goal_add (Term term, const int run, const int ev);
|
void goal_add (Term term, const int run, const int ev);
|
||||||
void goal_remove_last ();
|
void goal_remove_last ();
|
||||||
|
@ -109,6 +109,13 @@ makeGlobalConstant (const char *s)
|
|||||||
return levelDeclare (symbolSysConst (s), 0, 0);
|
return levelDeclare (symbolSysConst (s), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Make a global variable
|
||||||
|
Term
|
||||||
|
makeGlobalVariable (const char *s)
|
||||||
|
{
|
||||||
|
return levelDeclare (symbolSysConst (s), 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
//! Clean up afterwards
|
//! Clean up afterwards
|
||||||
void
|
void
|
||||||
compilerDone (void)
|
compilerDone (void)
|
||||||
|
@ -12,6 +12,7 @@ void compile (Tac tc, int maxruns);
|
|||||||
void preprocess (const System sys);
|
void preprocess (const System sys);
|
||||||
Term findGlobalConstant (const char *s);
|
Term findGlobalConstant (const char *s);
|
||||||
Term makeGlobalConstant (const char *s);
|
Term makeGlobalConstant (const char *s);
|
||||||
|
Term makeGlobalVariable (const char *s);
|
||||||
void compute_role_variables (const System sys, Protocol p, Role r);
|
void compute_role_variables (const System sys, Protocol p, Role r);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
48
src/ns3
48
src/ns3
@ -12,8 +12,8 @@ protocol ns3(I,R)
|
|||||||
send_1(I,R, {I,ni}pk(R) );
|
send_1(I,R, {I,ni}pk(R) );
|
||||||
read_2(R,I, {ni,nr}pk(I) );
|
read_2(R,I, {ni,nr}pk(I) );
|
||||||
send_3(I,R, {nr}pk(R) );
|
send_3(I,R, {nr}pk(R) );
|
||||||
claim_4(I,Secret,ni,nr);
|
// claim_4(I,Secret,ni,nr);
|
||||||
claim_6(I,Nisynch);
|
// claim_6(I,Nisynch);
|
||||||
}
|
}
|
||||||
|
|
||||||
role R
|
role R
|
||||||
@ -24,49 +24,13 @@ protocol ns3(I,R)
|
|||||||
read_1(I,R, {I,ni}pk(R) );
|
read_1(I,R, {I,ni}pk(R) );
|
||||||
send_2(R,I, {ni,nr}pk(I) );
|
send_2(R,I, {ni,nr}pk(I) );
|
||||||
read_3(I,R, {nr}pk(R) );
|
read_3(I,R, {nr}pk(R) );
|
||||||
claim_5(R,Secret,ni,nr);
|
claim_5(R,Secret,nr);
|
||||||
claim_7(R,Nisynch);
|
// claim_5(R,Secret,ni,nr);
|
||||||
|
// claim_7(R,Nisynch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We leave out: M (from M_0) and Decryption, because that causes
|
const Alice,Eve: Agent;
|
||||||
// problems with the inverse key.
|
|
||||||
protocol I_MALICE (I_F, I_T, I_V, I_R, I_E)
|
|
||||||
{
|
|
||||||
role I_F {
|
|
||||||
var t;
|
|
||||||
read_if1 (F,F, t);
|
|
||||||
}
|
|
||||||
role I_T {
|
|
||||||
var t;
|
|
||||||
read_it1 (T,T, t);
|
|
||||||
send_it2 (T,T, t);
|
|
||||||
send_it3 (T,T, t);
|
|
||||||
}
|
|
||||||
role I_V {
|
|
||||||
var t1;
|
|
||||||
var t2;
|
|
||||||
read_iv1 (V,V, t1);
|
|
||||||
read_iv2 (V,V, t2);
|
|
||||||
send_iv3 (V,V, (t1,t2));
|
|
||||||
}
|
|
||||||
role I_R {
|
|
||||||
var t1;
|
|
||||||
var t2;
|
|
||||||
read_ir1 (I_R,I_R, (t1,t2));
|
|
||||||
read_ir2 (I_R,I_R, t1);
|
|
||||||
send_ir3 (I_R,I_R, t2);
|
|
||||||
}
|
|
||||||
role I_E {
|
|
||||||
var t1;
|
|
||||||
var t2;
|
|
||||||
read_ie1 (I_E,I_E, t1);
|
|
||||||
read_ie2 (I_E,I_E, t2);
|
|
||||||
send_ie3 (I_E,I_E, {t1}t2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Alice,Bob,Eve: Agent;
|
|
||||||
|
|
||||||
untrusted Eve;
|
untrusted Eve;
|
||||||
const nc: Nonce;
|
const nc: Nonce;
|
||||||
|
66
src/term.c
66
src/term.c
@ -1037,3 +1037,69 @@ term_rolelocals_are_variables ()
|
|||||||
{
|
{
|
||||||
rolelocal_variable = 1;
|
rolelocal_variable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Count the encryption level of a term
|
||||||
|
int
|
||||||
|
term_encryption_level (const Term term)
|
||||||
|
{
|
||||||
|
int level, maxlevel, flag;
|
||||||
|
|
||||||
|
int nodel (const Term term)
|
||||||
|
{
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
if (level > maxlevel)
|
||||||
|
maxlevel = level;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int noder (const Term term)
|
||||||
|
{
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
level--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxlevel = 0;
|
||||||
|
level = 0;
|
||||||
|
flag = term_iterate_deVar (term, NULL, nodel, NULL, noder);
|
||||||
|
return maxlevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Determine 'constrained factor' of a term
|
||||||
|
/**
|
||||||
|
* Actually this is (#vars/structure).
|
||||||
|
* Thus, 0 means very constrained, no variables.
|
||||||
|
* Everything else has higher float, but always <=1. In fact, only a single variable has a level 1.
|
||||||
|
*/
|
||||||
|
float
|
||||||
|
term_constrain_level (const Term term)
|
||||||
|
{
|
||||||
|
int vars;
|
||||||
|
int structure;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
int leaf (const Term t)
|
||||||
|
{
|
||||||
|
structure++;
|
||||||
|
if (realTermVariable (t))
|
||||||
|
vars++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int nodel (const Term t)
|
||||||
|
{
|
||||||
|
structure++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (term == NULL)
|
||||||
|
error ("Cannot determine constrain level of empty term.");
|
||||||
|
|
||||||
|
vars = 0;
|
||||||
|
structure = 0;
|
||||||
|
flag = term_iterate_deVar (term, leaf, nodel, NULL, NULL);
|
||||||
|
return ((float) vars / (float) structure);
|
||||||
|
}
|
||||||
|
@ -175,5 +175,7 @@ int term_iterate_deVar (const Term term, int (*leaf) (), int (*nodel) (),
|
|||||||
int term_iterate_leaves (const Term t, int (*func) ());
|
int term_iterate_leaves (const Term t, int (*func) ());
|
||||||
int term_iterate_open_leaves (const Term term, int (*func) ());
|
int term_iterate_open_leaves (const Term term, int (*func) ());
|
||||||
void term_rolelocals_are_variables ();
|
void term_rolelocals_are_variables ();
|
||||||
|
int term_encryption_level (const Term term);
|
||||||
|
float term_constrain_level (const Term term);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* Temp file. I just forgot Warshall...
|
* Warshall's algorithm for transitive closure computation.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "warshall.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
graph_fill (int *graph, int nodes, int value)
|
graph_fill (int *graph, int nodes, int value)
|
||||||
{
|
{
|
||||||
@ -17,7 +19,8 @@ graph_fill (int *graph, int nodes, int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Show a graph
|
//! Show a graph
|
||||||
void graph_display (int *graph, int nodes)
|
void
|
||||||
|
graph_display (int *graph, int nodes)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -31,9 +34,9 @@ void graph_display (int *graph, int nodes)
|
|||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (j<nodes)
|
while (j < nodes)
|
||||||
{
|
{
|
||||||
eprintf ("%i ", graph[index(i,j)]);
|
eprintf ("%i ", graph[index (i, j)]);
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
eprintf ("\n");
|
eprintf ("\n");
|
||||||
@ -78,11 +81,20 @@ warshall (int *graph, int nodes)
|
|||||||
{
|
{
|
||||||
if (graph[index (k, j)] == 1)
|
if (graph[index (k, j)] == 1)
|
||||||
{
|
{
|
||||||
if (k == i)
|
/**
|
||||||
|
* Previously, we tested k == i (self-loop).
|
||||||
|
* Now we test 2-node loops, i.e. wether there is also a path from i to k.
|
||||||
|
*/
|
||||||
|
if (graph[index (i, k)] > 0)
|
||||||
{
|
{
|
||||||
// Oh no! A cycle.
|
// Oh no! A cycle.
|
||||||
graph [index (k,i)] = 2;
|
graph[index (k, i)] = 2;
|
||||||
graph_display (graph, nodes);
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
graph_display (graph, nodes);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
graph[index (k, i)] = 1;
|
graph[index (k, i)] = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user