- Moved everything about.
This commit is contained in:
parent
ca5202dc0c
commit
0f4e6a5aba
80
src/Makefile
Normal file
80
src/Makefile
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#
|
||||||
|
# Scyther Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# DEBUG or optimization settings: uncomment a single line:
|
||||||
|
#
|
||||||
|
CFLAGS = -g3 -D DEBUG # default usage, for e.g. with valgrind
|
||||||
|
#CFLAGS = -g3 -D DEBUG -pg # for code profiling with gprof
|
||||||
|
#CFLAGS = -O3 -static -finline-functions -fomit-frame-pointer
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compiler and linkage
|
||||||
|
#
|
||||||
|
CC = gcc
|
||||||
|
# Note that these paths must include the path to the argtable library.
|
||||||
|
CPPFLAGS = -I/scratch/ccremers/include -I/usr/local/include -Wall
|
||||||
|
LDFLAGS = -L/scratch/ccremers/lib -L/usr/local/lib
|
||||||
|
LOADLIBS = -lfl
|
||||||
|
LDLIBS = -largtable2
|
||||||
|
OPTIONS = ${CPPFLAGS} ${CFLAGS} ${LDFLAGS}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Module set for the modelchecker
|
||||||
|
#
|
||||||
|
MODULES=memory.o terms.o termlists.o symbols.o knowledge.o runs.o modelchecker.o \
|
||||||
|
report.o debug.o mgu.o substitutions.o \
|
||||||
|
match_basic.o \
|
||||||
|
match_clp.o constraints.o \
|
||||||
|
output.o latex.o \
|
||||||
|
varbuf.o tracebuf.o attackminimize.o \
|
||||||
|
tac.o parser.o compiler.o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dependencies
|
||||||
|
#
|
||||||
|
MODELCHECKER = ${MODULES} main.o
|
||||||
|
|
||||||
|
all: scyther tags
|
||||||
|
|
||||||
|
${Target}.o: ${Target}.c
|
||||||
|
$(CC) $(OPTIONS) ${Target}.c -c
|
||||||
|
|
||||||
|
scanner.c: scanner.lex
|
||||||
|
flex scanner.lex
|
||||||
|
cp lex.yy.c scanner.c
|
||||||
|
|
||||||
|
tok.h: parser.c
|
||||||
|
|
||||||
|
parser.c: parser.y
|
||||||
|
bison -d -v parser.y
|
||||||
|
cp parser.tab.c parser.c
|
||||||
|
cmp -s parser.tab.h tok.h || cp parser.tab.h tok.h
|
||||||
|
|
||||||
|
tags: *.c *.h
|
||||||
|
ctags *.c *.h
|
||||||
|
|
||||||
|
modules: $(MODULES)
|
||||||
|
|
||||||
|
scyther: scanner.o $(MODELCHECKER)
|
||||||
|
$(CC) $(OPTIONS) $(MODELCHECKER) -o scyther $(LOADLIBS) $(LDLIBS)
|
||||||
|
|
||||||
|
ptestmain.o scanner.o : tok.h
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup
|
||||||
|
#
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f scyther
|
||||||
|
rm -f scanner.c
|
||||||
|
rm -f parser.c
|
||||||
|
rm -f tok.h
|
||||||
|
#
|
||||||
|
# Clean and rebuild: 'make new'
|
||||||
|
#
|
||||||
|
new:
|
||||||
|
make clean
|
||||||
|
make all
|
||||||
|
|
33
src/README
Normal file
33
src/README
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
==================
|
||||||
|
# Scyther README #
|
||||||
|
==================
|
||||||
|
|
||||||
|
----------------
|
||||||
|
1. About Scyther
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Scyther bla Cas andsoforth, bla Lutger, yada yada yada.
|
||||||
|
|
||||||
|
---------------
|
||||||
|
2. Requirements
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Scyther compilation depends on a few external items:
|
||||||
|
|
||||||
|
- A C compiler (gcc or anything modern *nixy will do)
|
||||||
|
- The Flex and Bison scanner/compiler generation tools.
|
||||||
|
- The argtable 2 library.
|
||||||
|
|
||||||
|
The first two requirements are usually met by default by any modern *nix
|
||||||
|
variant, such as GNU/Linux.
|
||||||
|
|
||||||
|
The argtable2 library is available under the LGPL license from
|
||||||
|
http://argtable.sourceforge.net/doc/argtable2.html. Make sure the paths
|
||||||
|
in the Makefile include the path to this library.
|
||||||
|
|
||||||
|
If you want LaTeX output we need
|
||||||
|
|
||||||
|
- LaTeX
|
||||||
|
- The MSC macro package msc.sty
|
||||||
|
- preamble.tex and postamble.tex
|
||||||
|
|
131
src/attackminimize.c
Normal file
131
src/attackminimize.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "runs.h"
|
||||||
|
#include "tracebuf.h"
|
||||||
|
|
||||||
|
int cUnk = 0;
|
||||||
|
int cTod = 0;
|
||||||
|
|
||||||
|
void markback(System sys, struct tracebuf *tb, int ev)
|
||||||
|
{
|
||||||
|
int run = tb->run[ev];
|
||||||
|
|
||||||
|
while (ev >= 0)
|
||||||
|
{
|
||||||
|
if (tb->run[ev] == run)
|
||||||
|
{
|
||||||
|
switch (tb->event[ev]->type)
|
||||||
|
{
|
||||||
|
case READ:
|
||||||
|
switch (tb->status[ev])
|
||||||
|
{
|
||||||
|
case S_UNK:
|
||||||
|
cUnk--;
|
||||||
|
case S_RED:
|
||||||
|
tb->status[ev] = S_TOD;
|
||||||
|
cTod++;
|
||||||
|
break;
|
||||||
|
case S_TOD:
|
||||||
|
case S_OKE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEND:
|
||||||
|
case CLAIM:
|
||||||
|
if (tb->status[ev] == S_UNK)
|
||||||
|
{
|
||||||
|
cUnk--;
|
||||||
|
}
|
||||||
|
tb->status[ev] = S_OKE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ev--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void attackMinimize(System sys, struct tracebuf *tb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
cUnk = 0;
|
||||||
|
cTod = 0;
|
||||||
|
|
||||||
|
for (i=0; i < tb->length; i++)
|
||||||
|
{
|
||||||
|
switch (tb->status[i])
|
||||||
|
{
|
||||||
|
case S_UNK:
|
||||||
|
cUnk++;
|
||||||
|
break;
|
||||||
|
case S_TOD:
|
||||||
|
cTod++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
markback(sys, tb, tb->violatedclaim);
|
||||||
|
|
||||||
|
while (cUnk + cTod > 0)
|
||||||
|
{
|
||||||
|
while (cTod > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < tb->length; i++)
|
||||||
|
// kies een i; laten we de eerste maar pakken
|
||||||
|
{
|
||||||
|
if (tb->status[i] == S_TOD)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == tb->length)
|
||||||
|
{
|
||||||
|
printf("Some step error.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
j = i;
|
||||||
|
while (j >= 0 && inKnowledge(tb->know[j], tb->event[i]->message))
|
||||||
|
{
|
||||||
|
// zoek waar m in de kennis komt
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
tb->status[i] = S_OKE;
|
||||||
|
cTod--;
|
||||||
|
if (j>=0)
|
||||||
|
{
|
||||||
|
markback(sys,tb,j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (cTod == 0 && cUnk > 0)
|
||||||
|
{
|
||||||
|
for (i = tb->length-1; i>=0; i--)
|
||||||
|
// pak laatste i
|
||||||
|
{
|
||||||
|
if (tb->status[i] == S_UNK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
printf("Some i<0 error.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tb->status[i] = S_RED;
|
||||||
|
cUnk--;
|
||||||
|
tb->reallength--;
|
||||||
|
|
||||||
|
j = tracebufRebuildKnow(tb);
|
||||||
|
if (j>-1)
|
||||||
|
{
|
||||||
|
tb->reallength++;
|
||||||
|
markback(sys,tb,i);
|
||||||
|
if (j < tb->length)
|
||||||
|
{
|
||||||
|
tb->link[j] = (tb->link[j] > i ? tb->link[j] : i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
src/attackminimize.h
Normal file
1
src/attackminimize.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
void attackMinimize(System sys, struct tracebuf *tb);
|
6
src/cetest-cm.sh
Executable file
6
src/cetest-cm.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Test conform ce stuff, but our version
|
||||||
|
#
|
||||||
|
./scyther -r5 $* <spdl/bkepk.spdl
|
||||||
|
./scyther -r6 $* <spdl/bkepk.spdl | tail -n 1
|
10
src/cetest.sh
Executable file
10
src/cetest.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Test conform ce stuff.
|
||||||
|
#
|
||||||
|
./scyther -r6 $* <spdl/bkepk-ce.spdl
|
||||||
|
./scyther -r7 $* <spdl/bkepk-ce.spdl | tail -n 1
|
||||||
|
./scyther -r8 $* <spdl/bkepk-ce.spdl | tail -n 1
|
||||||
|
./scyther -r7 $* <spdl/bkepk-ce2.spdl | tail -n 1
|
||||||
|
./scyther -r8 $* <spdl/bkepk-ce2.spdl | tail -n 1
|
||||||
|
./scyther -r9 $* <spdl/bkepk-ce2.spdl | tail -n 1
|
732
src/compiler.c
Normal file
732
src/compiler.c
Normal file
@ -0,0 +1,732 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "tac.h"
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Simple sys pointer as a global. Yields cleaner code although it's against programming standards.
|
||||||
|
It is declared as static to hide it from the outside world, and to indicate its status.
|
||||||
|
Other modules will just see a nicely implemented sys parameter of compile, so we can always change
|
||||||
|
it later if somebody complains. Which they won't.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static System sys;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Forward declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void tacProcess (Tac tc);
|
||||||
|
void levelInit (void);
|
||||||
|
void levelDone (void);
|
||||||
|
Term symbolDeclare (Symbol s, int isVar);
|
||||||
|
void levelTacDeclaration (Tac tc, int isVar);
|
||||||
|
Term levelFind (Symbol s, int i);
|
||||||
|
Term symbolFind (Symbol s);
|
||||||
|
Term tacTerm (Tac tc);
|
||||||
|
Termlist tacTermlist (Tac tc);
|
||||||
|
|
||||||
|
#define levelDeclareVar(s) levelTacDeclaration(s,1)
|
||||||
|
#define levelDeclareConst(s) levelTacDeclaration(s,0)
|
||||||
|
#define levelVar(s) symbolDeclare(s,1)
|
||||||
|
#define levelConst(s) symbolDeclare(s,0)
|
||||||
|
|
||||||
|
/* externally used:
|
||||||
|
* TERM_Function in termlists.c for inversekeys
|
||||||
|
* TERM_Type in runs.c for type determination.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term TERM_Agent;
|
||||||
|
Term TERM_Function;
|
||||||
|
Term TERM_Hidden;
|
||||||
|
Term TERM_Type;
|
||||||
|
Term TERM_Nonce;
|
||||||
|
Term TERM_Agent;
|
||||||
|
|
||||||
|
Term TERM_Claim;
|
||||||
|
Term CLAIM_Secret;
|
||||||
|
Term CLAIM_Nisynch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAXLEVELS 3
|
||||||
|
static Termlist leveltl[MAXLEVELS];
|
||||||
|
static int level;
|
||||||
|
static int maxruns;
|
||||||
|
static Protocol thisProtocol;
|
||||||
|
static Role thisRole;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compile the tac into the system
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
compile (System mysys, Tac tc, int maxrunsset)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Init globals */
|
||||||
|
maxruns = maxrunsset;
|
||||||
|
/* transfer to global static variable */
|
||||||
|
sys = mysys;
|
||||||
|
/* init levels */
|
||||||
|
for (i = 0; i < MAXLEVELS; i++)
|
||||||
|
leveltl[i] = NULL;
|
||||||
|
level = -1;
|
||||||
|
levelInit ();
|
||||||
|
|
||||||
|
/* Init system constants */
|
||||||
|
#define langhide(x,y) x = levelConst(symbolSysConst(" _" y "_ "))
|
||||||
|
#define langtype(x,y) x->stype = termlistAdd(x->stype,y);
|
||||||
|
#define langcons(x,y,z) x = levelConst(symbolSysConst(y)); langtype(x,z)
|
||||||
|
|
||||||
|
langhide (TERM_Type, "Type");
|
||||||
|
langhide (TERM_Hidden, "Hidden");
|
||||||
|
langhide (TERM_Claim, "Claim");
|
||||||
|
|
||||||
|
langcons (TERM_Agent, "Agent", TERM_Type);
|
||||||
|
langcons (TERM_Function, "Function", TERM_Type);
|
||||||
|
langcons (TERM_Nonce, "Nonce", TERM_Type);
|
||||||
|
|
||||||
|
langcons (CLAIM_Secret, "Secret", TERM_Claim);
|
||||||
|
langcons (CLAIM_Nisynch, "Nisynch", TERM_Claim);
|
||||||
|
|
||||||
|
/* process the tac */
|
||||||
|
tacProcess (tc);
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
levelDone ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
errorTac (int lineno)
|
||||||
|
{
|
||||||
|
printf (" on line %i.\n", lineno);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
levelInit (void)
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
if (level >= MAXLEVELS)
|
||||||
|
{
|
||||||
|
printf ("ERROR: level is increased too much\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
leveltl[level] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
levelDone (void)
|
||||||
|
{
|
||||||
|
if (level < 0)
|
||||||
|
{
|
||||||
|
printf ("ERROR: level is increased too much\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
leveltl[level] = NULL;
|
||||||
|
level--;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
levelDeclare (Symbol s, int isVar, int level)
|
||||||
|
{
|
||||||
|
Term t;
|
||||||
|
|
||||||
|
t = levelFind (s, level);
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
/* new! */
|
||||||
|
if (isVar)
|
||||||
|
{
|
||||||
|
t = makeTermType (VARIABLE, s, -(level + 1));
|
||||||
|
sys->variables = termlistAdd (sys->variables, t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = makeTermType (GLOBAL, s, -(level + 1));
|
||||||
|
}
|
||||||
|
leveltl[level] = termlistAdd (leveltl[level], t);
|
||||||
|
|
||||||
|
/* add to relevant list */
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sys->locals = termlistAdd (sys->locals, t);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
thisProtocol->locals = termlistAdd (thisProtocol->locals, t);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
thisRole->locals = termlistAdd (thisRole->locals, t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
symbolDeclare (Symbol s, int isVar)
|
||||||
|
{
|
||||||
|
return levelDeclare (s, isVar, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
levelFind (Symbol s, int level)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
tl = leveltl[level];
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (isTermLeaf (tl->term))
|
||||||
|
{
|
||||||
|
if (tl->term->symb == s)
|
||||||
|
{
|
||||||
|
return tl->term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
symbolFind (Symbol s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Term t;
|
||||||
|
|
||||||
|
i = level;
|
||||||
|
while (i >= 0)
|
||||||
|
{
|
||||||
|
t = levelFind (s, i);
|
||||||
|
if (t != NULL)
|
||||||
|
return t;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
defineUsertype (Tac tcdu)
|
||||||
|
{
|
||||||
|
Tac tc;
|
||||||
|
Term t;
|
||||||
|
Term tfind;
|
||||||
|
|
||||||
|
tc = tcdu->tac1;
|
||||||
|
|
||||||
|
if (tc == NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR: empty usertype declaration.\n");
|
||||||
|
errorTac (tcdu->lineno);
|
||||||
|
}
|
||||||
|
while (tc != NULL && tc->op == TAC_STRING)
|
||||||
|
{
|
||||||
|
/* check whether this term is already declared in the same way
|
||||||
|
* (i.e. as a type) */
|
||||||
|
|
||||||
|
tfind = levelFind (tc->sym1, 0);
|
||||||
|
if (tfind == NULL)
|
||||||
|
{
|
||||||
|
/* this is what we expected: this type is not declared yet */
|
||||||
|
t = levelDeclare (tc->sym1, 0, 0);
|
||||||
|
t->stype = termlistAdd (NULL, TERM_Type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* oi!, there's already one. Let's hope is is a type too. */
|
||||||
|
if (inTermlist (tfind->stype, TERM_Type))
|
||||||
|
{
|
||||||
|
/* phew. warn anyway */
|
||||||
|
printf ("WARNING: double declaration of usertype ");
|
||||||
|
termPrint (tfind);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* that's not right! */
|
||||||
|
printf ("ERROR: conflicting definitions for ");
|
||||||
|
termPrint (tfind);
|
||||||
|
printf (" in usertype definition ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tc = tc->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
levelTacDeclaration (Tac tc, int isVar)
|
||||||
|
{
|
||||||
|
Tac tscan;
|
||||||
|
Termlist typetl = NULL;
|
||||||
|
Term t;
|
||||||
|
|
||||||
|
tscan = tc->tac2;
|
||||||
|
if (!isVar && tscan->next != NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR: Multiple types not allowed for constants ");
|
||||||
|
errorTac (tscan->lineno);
|
||||||
|
}
|
||||||
|
while (tscan != NULL && tscan->op == TAC_STRING)
|
||||||
|
{
|
||||||
|
/* apparently there is type info, termlist? */
|
||||||
|
t = levelFind (tscan->sym1, 0);
|
||||||
|
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
/* not declared, that is unacceptable. */
|
||||||
|
printf ("ERROR: type ");
|
||||||
|
symbolPrint (tscan->sym1);
|
||||||
|
printf (" was not declared ");
|
||||||
|
errorTac (tscan->lineno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!inTermlist (t->stype, TERM_Type))
|
||||||
|
{
|
||||||
|
printf ("ERROR: non-type constant in type declaration ");
|
||||||
|
errorTac (tscan->lineno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typetl = termlistAdd (typetl, t);
|
||||||
|
tscan = tscan->next;
|
||||||
|
}
|
||||||
|
/* parse all constants and vars */
|
||||||
|
tscan = tc->tac1;
|
||||||
|
while (tscan != NULL)
|
||||||
|
{
|
||||||
|
t = symbolDeclare (tscan->sym1, isVar);
|
||||||
|
t->stype = typetl;
|
||||||
|
tscan = tscan->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
commEvent (int event, Tac tc)
|
||||||
|
{
|
||||||
|
/* Add an event to the roledef, send or read */
|
||||||
|
Term fromrole = NULL;
|
||||||
|
Term torole = NULL;
|
||||||
|
Term msg = NULL;
|
||||||
|
Term label = NULL;
|
||||||
|
Term claim = NULL;
|
||||||
|
Term claimbig = NULL;
|
||||||
|
int n = 0;
|
||||||
|
Tac trip;
|
||||||
|
|
||||||
|
/* Construct label, if any */
|
||||||
|
if (tc->sym1 == NULL)
|
||||||
|
{
|
||||||
|
label = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = levelFind (tc->sym1, level - 1);
|
||||||
|
if (label == NULL)
|
||||||
|
{
|
||||||
|
/* effectively, labels are bound to the protocol */
|
||||||
|
level--;
|
||||||
|
label = levelConst (tc->sym1);
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trip = tc->tac2;
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case READ:
|
||||||
|
case SEND:
|
||||||
|
/* now parse triplet info */
|
||||||
|
if (trip == NULL || trip->next == NULL || trip->next->next == NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR in %i event ", event);
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
fromrole = tacTerm (trip);
|
||||||
|
torole = tacTerm (trip->next);
|
||||||
|
msg = tacTerm (tacTuple ((trip->next->next)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CLAIM:
|
||||||
|
/* now parse tuple info */
|
||||||
|
if (trip == NULL || trip->next == NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR in %i event ", event);
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
fromrole = tacTerm (trip);
|
||||||
|
claimbig = tacTerm (tacTuple ((trip->next)));
|
||||||
|
/* check for several types */
|
||||||
|
claim = tupleProject (claimbig, 0);
|
||||||
|
torole = claim;
|
||||||
|
/* check for obvious flaws */
|
||||||
|
if (claim == NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR: invalid claim specification ");
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
}
|
||||||
|
if (!inTermlist (claim->stype, TERM_Claim))
|
||||||
|
{
|
||||||
|
printf ("ERROR: unknown claim type ");
|
||||||
|
termPrint (claim);
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
}
|
||||||
|
/* unfold parameters to msg */
|
||||||
|
msg = NULL;
|
||||||
|
n = tupleCount (claimbig) - 1;
|
||||||
|
if (n < 1)
|
||||||
|
{
|
||||||
|
/* no parameters */
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* n parameters */
|
||||||
|
msg = deVar (claimbig)->op2;
|
||||||
|
if (tupleCount (msg) != n)
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
("ERROR: something went wrong in the claim tuple parameter unfolding ");
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handles all claim types differently */
|
||||||
|
|
||||||
|
if (claim == CLAIM_Secret)
|
||||||
|
{
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
("ERROR: secrecy claim requires a list of terms to be secret ");
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (claim == CLAIM_Nisynch)
|
||||||
|
{
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
printf ("ERROR: nisynch claim has no parameters ");
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hmm, no handler yet */
|
||||||
|
|
||||||
|
printf ("ERROR: No know handler for this claim type: ");
|
||||||
|
termPrint (claim);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (trip->next->lineno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* and make that event */
|
||||||
|
thisRole->roledef = roledefAdd (thisRole->roledef, event, label,
|
||||||
|
fromrole, torole, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
normalDeclaration (Tac tc)
|
||||||
|
{
|
||||||
|
switch (tc->op)
|
||||||
|
{
|
||||||
|
case TAC_VAR:
|
||||||
|
levelDeclareVar (tc);
|
||||||
|
if (level < 2 && tc->tac3 == NULL)
|
||||||
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->tac1));
|
||||||
|
break;
|
||||||
|
case TAC_CONST:
|
||||||
|
levelDeclareConst (tc);
|
||||||
|
if (level < 2 && tc->tac3 == NULL)
|
||||||
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->tac1));
|
||||||
|
break;
|
||||||
|
case TAC_SECRET:
|
||||||
|
levelDeclareConst (tc);
|
||||||
|
break;
|
||||||
|
case TAC_COMPROMISED:
|
||||||
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->tac1));
|
||||||
|
break;
|
||||||
|
case TAC_INVERSEKEYS:
|
||||||
|
knowledgeAddInverse (sys->know, tacTerm (tc->tac1), tacTerm (tc->tac2));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* abort with false */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
roleCompile (Term nameterm, Tac tc)
|
||||||
|
{
|
||||||
|
Role r;
|
||||||
|
|
||||||
|
/* make new (empty) current protocol with name */
|
||||||
|
r = roleCreate (nameterm);
|
||||||
|
thisRole = r;
|
||||||
|
/* add protocol to list */
|
||||||
|
r->next = thisProtocol->roles;
|
||||||
|
thisProtocol->roles = r;
|
||||||
|
|
||||||
|
/* parse the content of the role */
|
||||||
|
levelInit ();
|
||||||
|
|
||||||
|
while (tc != NULL)
|
||||||
|
{
|
||||||
|
switch (tc->op)
|
||||||
|
{
|
||||||
|
case TAC_READ:
|
||||||
|
commEvent (READ, tc);
|
||||||
|
break;
|
||||||
|
case TAC_SEND:
|
||||||
|
commEvent (SEND, tc);
|
||||||
|
break;
|
||||||
|
case TAC_CLAIM:
|
||||||
|
commEvent (CLAIM, tc);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!normalDeclaration (tc))
|
||||||
|
{
|
||||||
|
printf ("ERROR: illegal command %i in role ", tc->op);
|
||||||
|
termPrint (thisRole->nameterm);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tc = tc->next;
|
||||||
|
}
|
||||||
|
levelDone ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runInstanceCreate (Tac tc)
|
||||||
|
{
|
||||||
|
/* create an instance of an existing role
|
||||||
|
* tac1 is the dot-separated reference to the role.
|
||||||
|
* tac2 is the list of parameters to be filled in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Protocol p;
|
||||||
|
Role r;
|
||||||
|
Symbol psym, rsym;
|
||||||
|
Termlist instParams;
|
||||||
|
|
||||||
|
/* check whether we can still do it */
|
||||||
|
if (sys->maxruns >= maxruns)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* first, locate the protocol */
|
||||||
|
psym = tc->tac1->sym1;
|
||||||
|
p = sys->protocols;
|
||||||
|
while (p != NULL && p->nameterm->symb != psym)
|
||||||
|
p = p->next;
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
printf ("Trying to create a run of a non-declared protocol ");
|
||||||
|
symbolPrint (psym);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* locate the role */
|
||||||
|
rsym = tc->tac1->sym2;
|
||||||
|
r = p->roles;
|
||||||
|
while (r != NULL && r->nameterm->symb != rsym)
|
||||||
|
r = r->next;
|
||||||
|
if (r == NULL)
|
||||||
|
{
|
||||||
|
printf ("Protocol ");
|
||||||
|
symbolPrint (psym);
|
||||||
|
printf (" has no role called ");
|
||||||
|
symbolPrint (rsym);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we now know what we are instancing, equal numbers? */
|
||||||
|
instParams = tacTermlist (tc->tac2);
|
||||||
|
if (termlistLength (instParams) != termlistLength (p->rolenames))
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
("Run instance has different number of parameters than protocol ");
|
||||||
|
termPrint (p->nameterm);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* equal numbers, so it seems to be safe */
|
||||||
|
roleInstance (sys, p, r, instParams);
|
||||||
|
|
||||||
|
/* after creation analysis */
|
||||||
|
/* AC1: untrusted agents */
|
||||||
|
/* first: determine whether the run is untrusted,
|
||||||
|
* by checking whether one of the untrusted agents occurs
|
||||||
|
* in the run instance */
|
||||||
|
if (untrustedAgent (sys, instParams))
|
||||||
|
{
|
||||||
|
/* nothing yet */
|
||||||
|
/* claims handle this themselves */
|
||||||
|
|
||||||
|
/* some reduction might be possible, by cutting of the last few actions
|
||||||
|
* of such an untrusted run */
|
||||||
|
|
||||||
|
/* but most of it might be handled dynamically */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AC2: originator assumption for CLP ? */
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
protocolCompile (Symbol prots, Tac tc, Tac tcroles)
|
||||||
|
{
|
||||||
|
Protocol pr;
|
||||||
|
Term t;
|
||||||
|
|
||||||
|
if (levelFind (prots, level) != NULL)
|
||||||
|
{
|
||||||
|
printf ("ERROR: Double declaration of protocol ");
|
||||||
|
symbolPrint (prots);
|
||||||
|
printf (" ");
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
/* make new (empty) current protocol with name */
|
||||||
|
pr = protocolCreate (levelConst (prots));
|
||||||
|
thisProtocol = pr;
|
||||||
|
/* add protocol to list */
|
||||||
|
pr->next = sys->protocols;
|
||||||
|
sys->protocols = pr;
|
||||||
|
|
||||||
|
levelInit ();
|
||||||
|
/* add the role names */
|
||||||
|
pr->rolenames = NULL;
|
||||||
|
while (tcroles != NULL)
|
||||||
|
{
|
||||||
|
pr->rolenames =
|
||||||
|
termlistAppend (pr->rolenames, levelConst (tcroles->sym1));
|
||||||
|
tcroles = tcroles->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the content of the protocol */
|
||||||
|
while (tc != NULL)
|
||||||
|
{
|
||||||
|
switch (tc->op)
|
||||||
|
{
|
||||||
|
case TAC_UNTRUSTED:
|
||||||
|
sys->untrusted =
|
||||||
|
termlistConcat (sys->untrusted, tacTermlist (tc->tac1));
|
||||||
|
break;
|
||||||
|
case TAC_ROLE:
|
||||||
|
t = levelFind (tc->sym1, level);
|
||||||
|
if (t != NULL)
|
||||||
|
{
|
||||||
|
roleCompile (t, tc->tac2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("ERROR: undeclared role ");
|
||||||
|
symbolPrint (tc->sym1);
|
||||||
|
printf (" in protocol ");
|
||||||
|
termPrint (pr->nameterm);
|
||||||
|
errorTac (tc->sym1->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!normalDeclaration (tc))
|
||||||
|
{
|
||||||
|
printf ("ERROR: illegal command %i in protocol ", tc->op);
|
||||||
|
termPrint (thisProtocol->nameterm);
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tc = tc->next;
|
||||||
|
}
|
||||||
|
levelDone ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tacProcess (Tac tc)
|
||||||
|
{
|
||||||
|
while (tc != NULL)
|
||||||
|
{
|
||||||
|
switch (tc->op)
|
||||||
|
{
|
||||||
|
case TAC_PROTOCOL:
|
||||||
|
protocolCompile (tc->sym1, tc->tac2, tc->tac3);
|
||||||
|
break;
|
||||||
|
case TAC_UNTRUSTED:
|
||||||
|
sys->untrusted =
|
||||||
|
termlistConcat (sys->untrusted, tacTermlist (tc->tac1));
|
||||||
|
break;
|
||||||
|
case TAC_RUN:
|
||||||
|
runInstanceCreate (tc);
|
||||||
|
break;
|
||||||
|
case TAC_USERTYPE:
|
||||||
|
defineUsertype (tc);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!normalDeclaration (tc))
|
||||||
|
{
|
||||||
|
printf ("ERROR: illegal command %i at the global level.\n",
|
||||||
|
tc->op);
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tc = tc->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
tacTerm (Tac tc)
|
||||||
|
{
|
||||||
|
switch (tc->op)
|
||||||
|
{
|
||||||
|
case TAC_ENCRYPT:
|
||||||
|
return makeTermEncrypt (tacTerm (tc->tac1), tacTerm (tc->tac2));
|
||||||
|
case TAC_TUPLE:
|
||||||
|
return makeTermTuple (tacTerm (tc->tac1), tacTerm (tc->tac2));
|
||||||
|
case TAC_STRING:
|
||||||
|
{
|
||||||
|
Term t = symbolFind (tc->sym1);
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
printf ("Undeclared symbol ");
|
||||||
|
symbolPrint (tc->sym1);
|
||||||
|
errorTac (tc->lineno);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
tacTermlist (Tac tc)
|
||||||
|
{
|
||||||
|
Termlist tl = NULL;
|
||||||
|
|
||||||
|
while (tc != NULL)
|
||||||
|
{
|
||||||
|
tl = termlistAppend (tl, tacTerm (tc));
|
||||||
|
tc = tc->next;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
6
src/compiler.h
Normal file
6
src/compiler.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef COMPILER
|
||||||
|
#define COMPILER
|
||||||
|
|
||||||
|
void compile (System sys, Tac tc, int maxruns);
|
||||||
|
|
||||||
|
#endif
|
336
src/constraints.c
Normal file
336
src/constraints.c
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "memory.h"
|
||||||
|
#include "constraints.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* constraints currently are shallow copies */
|
||||||
|
|
||||||
|
Constraint
|
||||||
|
makeConstraint (Term term, Knowledge know)
|
||||||
|
{
|
||||||
|
/* maybe knowDup can just be a link, but then it needs to be moved from destroy as well */
|
||||||
|
Constraint co = memAlloc (sizeof (struct constraint));
|
||||||
|
co->term = term;
|
||||||
|
//co->know = knowledgeDuplicate(know);
|
||||||
|
co->know = know;
|
||||||
|
return co;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Constraint
|
||||||
|
constraintDuplicate (Constraint co)
|
||||||
|
{
|
||||||
|
return makeConstraint (co->term, co->know);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
constraintDestroy (Constraint cons)
|
||||||
|
{
|
||||||
|
//knowledgeDelete(cons->know);
|
||||||
|
if (cons != NULL)
|
||||||
|
memFree (cons, sizeof (struct constraint));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constraints are typically added at the end, to maintain the order in which they were added */
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistAdd (Constraintlist cl, Constraint co)
|
||||||
|
{
|
||||||
|
Constraintlist clnew = memAlloc (sizeof (struct constraintlist));
|
||||||
|
|
||||||
|
clnew->constraint = co;
|
||||||
|
clnew->next = NULL;
|
||||||
|
if (cl == NULL)
|
||||||
|
{
|
||||||
|
clnew->prev = NULL;
|
||||||
|
return clnew;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Constraintlist scan;
|
||||||
|
|
||||||
|
scan = cl;
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = clnew;
|
||||||
|
clnew->prev = scan;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistConcat (Constraintlist cl1, Constraintlist cl2)
|
||||||
|
{
|
||||||
|
Constraintlist scan;
|
||||||
|
|
||||||
|
if (cl1 == NULL)
|
||||||
|
return cl2;
|
||||||
|
scan = cl1;
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = cl2;
|
||||||
|
return cl1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistRewind (Constraintlist cl)
|
||||||
|
{
|
||||||
|
if (cl == NULL)
|
||||||
|
return NULL;
|
||||||
|
while (cl->prev != NULL)
|
||||||
|
cl = cl->prev;
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistInsert (Constraintlist cl, Term term, Knowledge know)
|
||||||
|
{
|
||||||
|
Constraintlist clnew = memAlloc (sizeof (struct constraintlist));
|
||||||
|
|
||||||
|
clnew->constraint = makeConstraint (term, know);
|
||||||
|
if (cl != NULL)
|
||||||
|
{
|
||||||
|
if (cl->next != NULL)
|
||||||
|
{
|
||||||
|
clnew->next = cl->next;
|
||||||
|
cl->next->prev = cl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clnew->next = NULL;
|
||||||
|
}
|
||||||
|
clnew->prev = cl;
|
||||||
|
cl->next = clnew;
|
||||||
|
return constraintlistRewind (cl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clnew->next = NULL;
|
||||||
|
clnew->prev = NULL;
|
||||||
|
return clnew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlink a single constraint */
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistUnlink (Constraintlist cl)
|
||||||
|
{
|
||||||
|
Constraintlist clnext, clprev;
|
||||||
|
|
||||||
|
if (cl == NULL)
|
||||||
|
return NULL;
|
||||||
|
clprev = cl->prev;
|
||||||
|
clnext = cl->next;
|
||||||
|
|
||||||
|
if (clnext != NULL)
|
||||||
|
{
|
||||||
|
clnext->prev = clprev;
|
||||||
|
cl->next = NULL;
|
||||||
|
}
|
||||||
|
if (clprev != NULL)
|
||||||
|
{
|
||||||
|
clprev->next = clnext;
|
||||||
|
cl->prev = NULL;
|
||||||
|
return constraintlistRewind (clprev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return clnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* remove a single constraint */
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistRemove (Constraintlist cl)
|
||||||
|
{
|
||||||
|
Constraintlist clnew;
|
||||||
|
|
||||||
|
clnew = constraintlistUnlink (cl);
|
||||||
|
memFree (cl, sizeof (struct constraintlist));
|
||||||
|
return clnew;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove all constraints from this point onwards */
|
||||||
|
|
||||||
|
void
|
||||||
|
constraintlistDelete (Constraintlist cl)
|
||||||
|
{
|
||||||
|
Constraintlist cldel;
|
||||||
|
|
||||||
|
/* no empty cl */
|
||||||
|
if (cl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* cut off previous */
|
||||||
|
if (cl->prev != NULL)
|
||||||
|
{
|
||||||
|
/* TODO maybe this should cause a warning? */
|
||||||
|
printf ("WARNING: clDelete with non-empty prev\n");
|
||||||
|
cl->prev->next = NULL;
|
||||||
|
}
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
cldel = cl;
|
||||||
|
cl = cl->next;
|
||||||
|
memFree (cldel, sizeof (struct constraintlist));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
constraintlistDestroy (Constraintlist cl)
|
||||||
|
{
|
||||||
|
Constraintlist cldel;
|
||||||
|
|
||||||
|
/* no empty cl */
|
||||||
|
if (cl == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* cut off previous */
|
||||||
|
if (cl->prev != NULL)
|
||||||
|
{
|
||||||
|
/* TODO maybe this should cause a warning? */
|
||||||
|
printf ("WARNING: clDestroy with non-empty prev\n");
|
||||||
|
cl->prev = NULL;
|
||||||
|
}
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
cldel = cl;
|
||||||
|
cl = cl->next;
|
||||||
|
constraintDestroy (cldel->constraint);
|
||||||
|
memFree (cldel, sizeof (struct constraintlist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistDuplicate (Constraintlist oldcl)
|
||||||
|
{
|
||||||
|
Constraintlist newcl = NULL;
|
||||||
|
|
||||||
|
while (oldcl != NULL)
|
||||||
|
{
|
||||||
|
newcl =
|
||||||
|
constraintlistAdd (newcl, constraintDuplicate (oldcl->constraint));
|
||||||
|
oldcl = oldcl->next;
|
||||||
|
}
|
||||||
|
return newcl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
constraintlistShallow (Constraintlist oldcl)
|
||||||
|
{
|
||||||
|
Constraintlist newcl = NULL;
|
||||||
|
|
||||||
|
while (oldcl != NULL)
|
||||||
|
{
|
||||||
|
newcl = constraintlistAdd (newcl, oldcl->constraint);
|
||||||
|
oldcl = oldcl->next;
|
||||||
|
}
|
||||||
|
return newcl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------
|
||||||
|
|
||||||
|
Print stuff
|
||||||
|
|
||||||
|
---------------------------------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
constraintPrint (Constraint co)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Constraint ");
|
||||||
|
if (co == NULL)
|
||||||
|
{
|
||||||
|
printf ("[empty]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
termPrint (co->term);
|
||||||
|
printf (" :\n");
|
||||||
|
knowledgePrint (co->know);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
constraintlistPrint (Constraintlist cl)
|
||||||
|
{
|
||||||
|
if (cl == NULL)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("[empty constraintlist]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
constraintPrint (cl->constraint);
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------
|
||||||
|
|
||||||
|
Now some real logic for the constraints
|
||||||
|
|
||||||
|
---------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* eliminate all standalone variables */
|
||||||
|
|
||||||
|
void
|
||||||
|
msElim (Constraint co)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
/* simple variables can only exist in basic */
|
||||||
|
if (co->know == NULL)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug (5, "Exiting because co->know is empty.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tl = co->know->basic;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (isTermVariable (tl->term))
|
||||||
|
{
|
||||||
|
tl = termlistDelTerm (tl);
|
||||||
|
co->know->basic = tl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* find the first constraint such that m is not a variable */
|
||||||
|
/* also, apply standalone elimination to it */
|
||||||
|
|
||||||
|
Constraintlist
|
||||||
|
firstNonVariable (Constraintlist cl)
|
||||||
|
{
|
||||||
|
while (cl != NULL && isTermVariable (cl->constraint->term))
|
||||||
|
{
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
if (cl != NULL)
|
||||||
|
{
|
||||||
|
msElim (cl->constraint);
|
||||||
|
cl->constraint->term = deVar (cl->constraint->term);
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
42
src/constraints.h
Normal file
42
src/constraints.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef CONSTRAINTS
|
||||||
|
#define CONSTRAINTS
|
||||||
|
#include "terms.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
|
||||||
|
struct constraint
|
||||||
|
{
|
||||||
|
Term term;
|
||||||
|
Knowledge know;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct constraint *Constraint;
|
||||||
|
|
||||||
|
struct constraintlist
|
||||||
|
{
|
||||||
|
Constraint constraint;
|
||||||
|
struct constraintlist *next;
|
||||||
|
struct constraintlist *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct constraintlist *Constraintlist;
|
||||||
|
|
||||||
|
Constraint makeConstraint (Term term, Knowledge know);
|
||||||
|
Constraint constraintDuplicate (Constraint co);
|
||||||
|
void constraintDestroy (Constraint cons);
|
||||||
|
Constraintlist constraintlistAdd (Constraintlist cl, Constraint co);
|
||||||
|
Constraintlist constraintlistConcat (Constraintlist cl1, Constraintlist cl2);
|
||||||
|
Constraintlist constraintlistRewind (Constraintlist cl);
|
||||||
|
Constraintlist constraintlistInsert (Constraintlist cl, Term term,
|
||||||
|
Knowledge know);
|
||||||
|
Constraintlist constraintlistUnlink (Constraintlist cl);
|
||||||
|
Constraintlist constraintlistRemove (Constraintlist cl);
|
||||||
|
void constraintlistDestroy (Constraintlist cl);
|
||||||
|
void constraintlistDelete (Constraintlist cl);
|
||||||
|
Constraintlist constraintlistShallow (Constraintlist oldcl);
|
||||||
|
Constraintlist constraintlistDuplicate (Constraintlist oldcl);
|
||||||
|
void constraintPrint (Constraint co);
|
||||||
|
void constraintlistPrint (Constraintlist cl);
|
||||||
|
|
||||||
|
Constraintlist firstNonVariable (Constraintlist cl);
|
||||||
|
|
||||||
|
#endif
|
30
src/debug.c
Normal file
30
src/debug.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "debug.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
static int debuglevel;
|
||||||
|
|
||||||
|
void
|
||||||
|
debugSet (int level)
|
||||||
|
{
|
||||||
|
debuglevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
debugCond (int level)
|
||||||
|
{
|
||||||
|
return (level <= debuglevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
debug (int level, char *string)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (debugCond (level))
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("DEBUG [%i]: %s\n", level, string);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
10
src/debug.h
Normal file
10
src/debug.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef DEBUG_H
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
void debugSet (int level);
|
||||||
|
int debugCond (int level);
|
||||||
|
void debug (int level, char *string);
|
||||||
|
|
||||||
|
#define DEBUGL(a) debugCond(a)
|
||||||
|
|
||||||
|
#endif
|
7
src/debuglevels.txt
Normal file
7
src/debuglevels.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Conventions for debug levels; ifdef DEBUG
|
||||||
|
|
||||||
|
-D1 meta show compiled code, meta dynamic results
|
||||||
|
-D2 claims show results of claims
|
||||||
|
-D3 events show executed events
|
||||||
|
-D4 internalsHigh interesting internals (traces that were cut off)
|
||||||
|
-D5 internalsLow usually uninteresting stuff
|
47
src/design.txt
Normal file
47
src/design.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
Design Issues for the Model Checker
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
- For secrecy, we can trigger all sends at once. For synchronisation,
|
||||||
|
this is not the case.
|
||||||
|
|
||||||
|
- Modules have to be split up sensibly.
|
||||||
|
|
||||||
|
- Although 'knowledge' and 'term matching' seem to different items,
|
||||||
|
their intertwined workings suggest that they should be implemented
|
||||||
|
in parallel.
|
||||||
|
|
||||||
|
- State generation (as in creating instances) might already allow for
|
||||||
|
a lot of static analysis.
|
||||||
|
|
||||||
|
- We should make a list of required operations. Ingmar's work can serve
|
||||||
|
as a starting point.
|
||||||
|
|
||||||
|
- For now, there will be no parser, and test cases will be input by
|
||||||
|
hand.
|
||||||
|
|
||||||
|
- Synchronisation is more difficult to test, so we focus on secrecy
|
||||||
|
first. I've got some good ideas on Synchronisation testing though
|
||||||
|
(with narrowing sets of possible partners). Synchronisation is very
|
||||||
|
hard to prune, I presume. I have to prove that though ;)
|
||||||
|
|
||||||
|
Sketch for secrecy:
|
||||||
|
|
||||||
|
SimulateStep(F,M,constraints):
|
||||||
|
if Empty(F):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
for (s in PossibleSends):
|
||||||
|
add s.message to M
|
||||||
|
if (secrecy violated):
|
||||||
|
halt
|
||||||
|
remove s from F
|
||||||
|
ReadSets = supersetTransitions(F)
|
||||||
|
for (ReadSet in ReadSets):
|
||||||
|
for (s in ReadSet):
|
||||||
|
// dit is vaag
|
||||||
|
if NonMatch goto next ReadSet
|
||||||
|
constraint = F,M,match()
|
||||||
|
SimulateStep(F \ s,M,constraints)
|
||||||
|
|
||||||
|
|
||||||
|
|
474
src/knowledge.c
Normal file
474
src/knowledge.c
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Knowledge stuff
|
||||||
|
*
|
||||||
|
* Note that a really weird thing is going on involving unpropagated substitutions.
|
||||||
|
* Idea:
|
||||||
|
*
|
||||||
|
* 1. Substitute terms by filling in ->subst.
|
||||||
|
* Now, either:
|
||||||
|
* 2a. Undo this by knowledgeUndo.
|
||||||
|
* 2b. Propagate it, modifying the knowledge beyond repair by knowledgeSubstDo. Now inKnowledge works again.
|
||||||
|
* 2c. inKnowledge/knowledgeSet if something is in the knowledge: this does not consider the substitutions!, and
|
||||||
|
* they now have some overhead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeInit (void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeDone (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
makeKnowledge ()
|
||||||
|
{
|
||||||
|
return (Knowledge) memAlloc (sizeof (struct knowledge));
|
||||||
|
}
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
emptyKnowledge ()
|
||||||
|
{
|
||||||
|
Knowledge know;
|
||||||
|
|
||||||
|
know = makeKnowledge ();
|
||||||
|
know->basic = NULL;
|
||||||
|
know->encrypt = NULL;
|
||||||
|
know->inverses = NULL;
|
||||||
|
know->vars = NULL;
|
||||||
|
return know;
|
||||||
|
}
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
knowledgeDuplicate (Knowledge know)
|
||||||
|
{
|
||||||
|
Knowledge newknow;
|
||||||
|
|
||||||
|
if (know == NULL)
|
||||||
|
{
|
||||||
|
printf ("Warning! Trying to copy empty knowledge!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
newknow = makeKnowledge ();
|
||||||
|
newknow->basic = termlistShallow (know->basic);
|
||||||
|
newknow->encrypt = termlistShallow (know->encrypt);
|
||||||
|
newknow->vars = termlistShallow (know->vars);
|
||||||
|
newknow->inverses = know->inverses;
|
||||||
|
return newknow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeDelete (Knowledge know)
|
||||||
|
{
|
||||||
|
if (know != NULL)
|
||||||
|
{
|
||||||
|
termlistDelete (know->basic);
|
||||||
|
termlistDelete (know->encrypt);
|
||||||
|
termlistDelete (know->vars);
|
||||||
|
memFree (know, sizeof (struct knowledge));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeDestroy (Knowledge know)
|
||||||
|
{
|
||||||
|
if (know != NULL)
|
||||||
|
{
|
||||||
|
termlistDestroy (know->basic);
|
||||||
|
termlistDestroy (know->encrypt);
|
||||||
|
termlistDestroy (know->vars);
|
||||||
|
// termlistDestroy(know->inverses);
|
||||||
|
memFree (know, sizeof (struct knowledge));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* knowledgeAddTerm
|
||||||
|
*
|
||||||
|
* returns a boolean:
|
||||||
|
* true iff the term was actually new, and added.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
knowledgeAddTerm (Knowledge know, Term term)
|
||||||
|
{
|
||||||
|
if (know == NULL)
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
("Warning: trying to add term to uninitialised (NULL) Know pointer.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (term == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
term = deVar (term);
|
||||||
|
|
||||||
|
/* test whether we knew it before */
|
||||||
|
if (inKnowledge (know, term))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (isTermTuple (term))
|
||||||
|
{
|
||||||
|
knowledgeAddTerm (know, term->op1);
|
||||||
|
knowledgeAddTerm (know, term->op2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adding variables? */
|
||||||
|
know->vars = termlistAddVariables (know->vars, term);
|
||||||
|
|
||||||
|
knowledgeSimplify (know, term);
|
||||||
|
if (isTermLeaf (term))
|
||||||
|
{
|
||||||
|
know->basic = termlistAdd (know->basic, term);
|
||||||
|
}
|
||||||
|
if (term->type == ENCRYPT)
|
||||||
|
{
|
||||||
|
Term invkey = inverseKey (know->inverses, term->key);
|
||||||
|
if (inKnowledge (know, invkey))
|
||||||
|
{
|
||||||
|
/* we can decrypt it */
|
||||||
|
knowledgeAddTerm (know, term->op);
|
||||||
|
if (!inKnowledge (know, term->key))
|
||||||
|
{
|
||||||
|
/* we know the op now, but not the key, so add it anyway */
|
||||||
|
know->encrypt = termlistAdd (know->encrypt, term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* we cannot decrypt it, and from the initial test we know we could not construct it */
|
||||||
|
know->encrypt = termlistAdd (know->encrypt, term);
|
||||||
|
}
|
||||||
|
termDelete (invkey);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: the input is a key k, i.e. it can decrypt
|
||||||
|
anything that was encrypted with k^{-1}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeSimplify (Knowledge know, Term key)
|
||||||
|
{
|
||||||
|
Termlist tldecrypts = NULL;
|
||||||
|
Termlist scan = know->encrypt;
|
||||||
|
Term invkey = inverseKey (know->inverses, key);
|
||||||
|
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual ((scan->term)->key, invkey))
|
||||||
|
{
|
||||||
|
tldecrypts = termlistAdd (tldecrypts, (scan->term)->op);
|
||||||
|
know->encrypt = termlistDelTerm (scan);
|
||||||
|
scan = know->encrypt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
termDelete (invkey);
|
||||||
|
knowledgeAddTermlist (know, tldecrypts);
|
||||||
|
termlistDelete (tldecrypts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a whole termlist.
|
||||||
|
*
|
||||||
|
* Returns true iff there was at least one new item.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
knowledgeAddTermlist (Knowledge know, Termlist tl)
|
||||||
|
{
|
||||||
|
int flag = 0;
|
||||||
|
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
flag = knowledgeAddTerm (know, tl->term) || flag;
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
add an inverse pair to the knowledge
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeAddInverse (Knowledge know, Term t1, Term t2)
|
||||||
|
{
|
||||||
|
know->inverses = termlistAdd (know->inverses, t1);
|
||||||
|
know->inverses = termlistAdd (know->inverses, t2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
same, but for list. List pointer is simply copied, so don't delete it later!
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeSetInverses (Knowledge know, Termlist tl)
|
||||||
|
{
|
||||||
|
know->inverses = tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
inKnowledge
|
||||||
|
|
||||||
|
Is a term a part of the knowledge?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
inKnowledge (const Knowledge know, Term term)
|
||||||
|
{
|
||||||
|
/* if there is no term, then it's okay 'fur sure' */
|
||||||
|
if (term == NULL)
|
||||||
|
return 1;
|
||||||
|
/* if there is a term, but no knowledge, we're in trouble */
|
||||||
|
if (know == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mindwipe (know, inKnowledge (know, term));
|
||||||
|
|
||||||
|
term = deVar (term);
|
||||||
|
if (isTermLeaf (term))
|
||||||
|
{
|
||||||
|
return inTermlist (know->basic, term);
|
||||||
|
}
|
||||||
|
if (term->type == ENCRYPT)
|
||||||
|
{
|
||||||
|
return inTermlist (know->encrypt, term) ||
|
||||||
|
(inKnowledge (know, term->key) && inKnowledge (know, term->op));
|
||||||
|
}
|
||||||
|
if (term->type == TUPLE)
|
||||||
|
{
|
||||||
|
return (inTermlist (know->encrypt, term) ||
|
||||||
|
(inKnowledge (know, term->op1) &&
|
||||||
|
inKnowledge (know, term->op2)));
|
||||||
|
}
|
||||||
|
return 0; /* unrecognized term type, weird */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isKnowledgeEqual (Knowledge know1, Knowledge know2)
|
||||||
|
{
|
||||||
|
if (know1 == NULL || know2 == NULL)
|
||||||
|
{
|
||||||
|
if (know1 == NULL && know2 == NULL)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!isTermlistEqual (know1->encrypt, know2->encrypt))
|
||||||
|
return 0;
|
||||||
|
return isTermlistEqual (know1->basic, know2->basic);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgePrint (Knowledge know)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
if (know == NULL)
|
||||||
|
{
|
||||||
|
printf ("Empty.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf (" [Basic]: ");
|
||||||
|
termlistPrint (know->basic);
|
||||||
|
printf ("\n");
|
||||||
|
indent ();
|
||||||
|
printf (" [Encrp]: ");
|
||||||
|
termlistPrint (know->encrypt);
|
||||||
|
printf ("\n");
|
||||||
|
indent ();
|
||||||
|
printf (" [Vars]: ");
|
||||||
|
termlistPrint (know->vars);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
print inverses
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeInversesPrint (Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
int after = 0;
|
||||||
|
|
||||||
|
if (know == NULL)
|
||||||
|
{
|
||||||
|
printf ("Empty knowledge.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tl = knowledgeGetInverses (know);
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
printf ("None.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (tl != NULL && tl->next != NULL)
|
||||||
|
{
|
||||||
|
if (after)
|
||||||
|
{
|
||||||
|
printf (",");
|
||||||
|
}
|
||||||
|
printf ("(");
|
||||||
|
termPrint (tl->term);
|
||||||
|
printf (",");
|
||||||
|
termPrint (tl->next->term);
|
||||||
|
printf (")");
|
||||||
|
after = 1;
|
||||||
|
tl = tl->next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
give the set of representatives for the knowledge.
|
||||||
|
Note: this is a shallow copy, and needs to be termlistDelete'd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
knowledgeSet (Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist tl1, tl2;
|
||||||
|
|
||||||
|
tl1 = termlistShallow (know->basic);
|
||||||
|
tl2 = termlistShallow (know->encrypt);
|
||||||
|
return termlistConcat (tl1, tl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
get the inverses pointer of the knowledge.
|
||||||
|
Essentially the inverse function of knowledgeSetInverses
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
knowledgeGetInverses (Knowledge know)
|
||||||
|
{
|
||||||
|
if (know == NULL)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return know->inverses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check whether any substitutions where made at all.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
knowledgeSubstNeeded (const Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
if (know == NULL)
|
||||||
|
return 0;
|
||||||
|
tl = know->vars;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (tl->term->subst != NULL)
|
||||||
|
return 1;
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* knowledgeReconstruction
|
||||||
|
*
|
||||||
|
* This is useful after e.g. substitutions.
|
||||||
|
* Just rebuilds the knowledge in a new (shallow) copy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
knowledgeReconstruction (const Knowledge know)
|
||||||
|
{
|
||||||
|
Knowledge newknow = emptyKnowledge ();
|
||||||
|
|
||||||
|
newknow->inverses = know->inverses;
|
||||||
|
knowledgeAddTermlist (newknow, know->basic);
|
||||||
|
knowledgeAddTermlist (newknow, know->encrypt);
|
||||||
|
return newknow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* propagate any substitutions just made.
|
||||||
|
*
|
||||||
|
* This usually involves reconstruction of the complete knowledge, which is
|
||||||
|
* 'cheaper' than a thorough analysis, so we always make a copy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
knowledgeSubstDo (const Knowledge know)
|
||||||
|
{
|
||||||
|
/* otherwise a copy (for deletion) is returned. */
|
||||||
|
return knowledgeReconstruction (know);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Undo the substitutions just made. Note that this does not work anymore after knowledgeSubstDo!
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
knowledgeSubstUndo (const Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
tl = know->vars;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
tl->term->subst = NULL;
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* knowledgeNew(old,new)
|
||||||
|
*
|
||||||
|
* yield a termlist (or NULL) that represents the reduced items that are
|
||||||
|
* in the new set, but not in the old one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
knowledgeNew (const Knowledge oldk, const Knowledge newk)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
|
||||||
|
newtl = NULL;
|
||||||
|
|
||||||
|
void addNewStuff (Termlist tl)
|
||||||
|
{
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (!inKnowledge (oldk, tl->term))
|
||||||
|
{
|
||||||
|
newtl = termlistAdd (newtl, tl->term);
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addNewStuff (newk->basic);
|
||||||
|
addNewStuff (newk->encrypt);
|
||||||
|
return newtl;
|
||||||
|
}
|
60
src/knowledge.h
Normal file
60
src/knowledge.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef KNOWLEDGE
|
||||||
|
#define KNOWLEDGE
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
|
||||||
|
struct knowledge
|
||||||
|
{
|
||||||
|
Termlist basic;
|
||||||
|
Termlist encrypt;
|
||||||
|
Termlist inverses;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Termlist vars; // special: denotes unsubstituted variables
|
||||||
|
struct knowledge *next; // use for alternative memory management.
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct knowledge *Knowledge;
|
||||||
|
|
||||||
|
void knowledgeInit (void);
|
||||||
|
void knowledgeDone (void);
|
||||||
|
Knowledge makeKnowledge ();
|
||||||
|
Knowledge emptyKnowledge ();
|
||||||
|
Knowledge knowledgeDuplicate (Knowledge know);
|
||||||
|
void knowledgeDelete (Knowledge know);
|
||||||
|
void knowledgeDestroy (Knowledge know);
|
||||||
|
int knowledgeAddTerm (Knowledge know, Term term);
|
||||||
|
int knowledgeAddTermlist (Knowledge know, Termlist tl);
|
||||||
|
void knowledgeAddInverse (Knowledge know, Term t1, Term t2);
|
||||||
|
void knowledgeSetInverses (Knowledge know, Termlist tl);
|
||||||
|
void knowledgeSimplify (Knowledge know, Term decryptkey);
|
||||||
|
int inKnowledge (const Knowledge know, Term term);
|
||||||
|
void knowledgePrint (Knowledge know);
|
||||||
|
void knowledgeInversesPrint (Knowledge know);
|
||||||
|
int isKnowledgeEqual (Knowledge know1, Knowledge know2);
|
||||||
|
Termlist knowledgeSet (Knowledge know);
|
||||||
|
Termlist knowledgeGetInverses (Knowledge know);
|
||||||
|
int knowledgeSubstNeeded (const Knowledge know);
|
||||||
|
Knowledge knowledgeSubstDo (const Knowledge know);
|
||||||
|
void knowledgeSubstUndo (const Knowledge know);
|
||||||
|
Termlist knowledgeNew (const Knowledge oldk, const Knowledge newk);
|
||||||
|
|
||||||
|
#define mindwipe(k,recurse) \
|
||||||
|
if (k != NULL && k->vars != NULL) { \
|
||||||
|
Termlist tl = k->vars; \
|
||||||
|
while (tl != NULL) { \
|
||||||
|
if (tl->term->subst != NULL) { \
|
||||||
|
Term oldsubst = tl->term->subst; \
|
||||||
|
tl->term->subst = NULL; \
|
||||||
|
int flag = recurse; \
|
||||||
|
tl->term->subst = oldsubst; \
|
||||||
|
return flag; \
|
||||||
|
} \
|
||||||
|
tl = tl->next; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
46
src/language.txt
Normal file
46
src/language.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Language
|
||||||
|
--------
|
||||||
|
|
||||||
|
language := (<def>)*
|
||||||
|
def := (<directive> | <protocol> | <rundef> | <unstrusted>)
|
||||||
|
|
||||||
|
//directive := <dir_require>
|
||||||
|
//dir_require := require <filename>;
|
||||||
|
|
||||||
|
protocol := protocol <protocolname> ( <rolelist> ) { <roledef>* } optsc
|
||||||
|
protocolname := <id>
|
||||||
|
|
||||||
|
intruderknow := public <termlist>;
|
||||||
|
roledef := role <rolename> { <actions> } optsc
|
||||||
|
rolename := <id>
|
||||||
|
actions := (<action>;)+
|
||||||
|
action := (<read> | <send> | <claim>)
|
||||||
|
decl := (<const> | <var>)+
|
||||||
|
const := const <termlist> [ : <typeterm> ];
|
||||||
|
var := var <termlist> [ : <typelist> ];
|
||||||
|
|
||||||
|
read := read [_<label>] (<term>,<term>,<term>);
|
||||||
|
send := send [_<label>] (<term>,<term>,<term>);
|
||||||
|
claim := claim [_<label>] (<term>,<termlist>);
|
||||||
|
label := <id>;
|
||||||
|
|
||||||
|
rundef := <protocolname>.<rolename> ( <instancelist> ) ;
|
||||||
|
instancelist := (<agent>|<typeterm>)*
|
||||||
|
|
||||||
|
agent := <term>
|
||||||
|
typeterm := <term>
|
||||||
|
typelist := <termlist>
|
||||||
|
|
||||||
|
untrusted := untrusted <termlist>;
|
||||||
|
|
||||||
|
termlist := <term> [, <termlist>]
|
||||||
|
term := (<baseterm> | <encterm> | <tupleterm> | <function>)
|
||||||
|
encterm := { <term> } <term>
|
||||||
|
function := <term> ( <term> )
|
||||||
|
baseterm := (<variable> | <const>)
|
||||||
|
variable := <id>
|
||||||
|
const := <id>
|
||||||
|
|
||||||
|
optsc := [ ; ]
|
||||||
|
id := (<digit>|<uppercase>|<lowercase>)+
|
||||||
|
|
797
src/latex.c
Normal file
797
src/latex.c
Normal file
@ -0,0 +1,797 @@
|
|||||||
|
/*
|
||||||
|
* LaTeX output component
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "runs.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "modelchecker.h"
|
||||||
|
#include "tracebuf.h"
|
||||||
|
#include "varbuf.h"
|
||||||
|
#include "output.h"
|
||||||
|
|
||||||
|
#define EVENTSPACE 1
|
||||||
|
#define LINKTHRESHOLD 0.95
|
||||||
|
|
||||||
|
extern const char *progname;
|
||||||
|
extern const char *releasetag;
|
||||||
|
extern int globalLatex;
|
||||||
|
extern Term TERM_Function;
|
||||||
|
|
||||||
|
/* struct for additional info */
|
||||||
|
|
||||||
|
struct traceinfo {
|
||||||
|
int match;
|
||||||
|
int position;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* global variables for this module */
|
||||||
|
|
||||||
|
struct traceinfo *tinfo;
|
||||||
|
int width;
|
||||||
|
int landscape = 0;
|
||||||
|
int *runPerm;
|
||||||
|
|
||||||
|
/* code */
|
||||||
|
|
||||||
|
void latexInit(const System sys, int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("\\documentclass{article}\n");
|
||||||
|
printf("\\usepackage{msc}\n");
|
||||||
|
printf("%%\n");
|
||||||
|
printf("%% LaTeX output generated by %s\n", progname);
|
||||||
|
printf("%% Input:\n");
|
||||||
|
|
||||||
|
/* print command line */
|
||||||
|
printf("%% $");
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf(" %s", argv[i]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("%%\n");
|
||||||
|
printf("\\begin{document}\n\n");
|
||||||
|
|
||||||
|
/* comment macro (used for debugging) */
|
||||||
|
printf("\\newcommand{\\comment}[1]{}\n");
|
||||||
|
|
||||||
|
/* preamble */
|
||||||
|
printf("\\input{preamble}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexDone(const System sys)
|
||||||
|
{
|
||||||
|
printf("\\input{postamble}\n");
|
||||||
|
printf("\n\\end{document}\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
latexTermPrint (Term term, Termlist highlight)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
{
|
||||||
|
printf ("Empty term");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!DEBUGL (1))
|
||||||
|
{
|
||||||
|
term = deVar (term);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
term = deVar (term);
|
||||||
|
#endif
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
{
|
||||||
|
if (inTermlist(highlight, term))
|
||||||
|
printf("\\mathbf{");
|
||||||
|
symbolPrint (term->symb);
|
||||||
|
if (realTermVariable (term))
|
||||||
|
printf ("V");
|
||||||
|
if (term->runid >= 0)
|
||||||
|
{
|
||||||
|
printf ("\\sharp%i", term->runid);
|
||||||
|
}
|
||||||
|
if (term->subst != NULL)
|
||||||
|
{
|
||||||
|
printf ("\\rightarrow");
|
||||||
|
latexTermPrint (term->subst, highlight);
|
||||||
|
}
|
||||||
|
if (inTermlist(highlight, term))
|
||||||
|
printf("}");
|
||||||
|
}
|
||||||
|
if (realTermTuple (term))
|
||||||
|
{
|
||||||
|
printf ("(");
|
||||||
|
while (realTermTuple (term))
|
||||||
|
{
|
||||||
|
latexTermPrint (term->op1, highlight);
|
||||||
|
printf (",");
|
||||||
|
term = term->op2;
|
||||||
|
if (!realTermTuple (term))
|
||||||
|
latexTermPrint (term, highlight);
|
||||||
|
|
||||||
|
}
|
||||||
|
printf (")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
if (isTermLeaf (term->key)
|
||||||
|
&& inTermlist (term->key->stype, TERM_Function))
|
||||||
|
{
|
||||||
|
/* function application */
|
||||||
|
latexTermPrint (term->key, highlight);
|
||||||
|
printf ("(");
|
||||||
|
latexTermPrint (term->op, highlight);
|
||||||
|
printf (")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* normal encryption */
|
||||||
|
printf ("\\{");
|
||||||
|
latexTermPrint (term->op, highlight);
|
||||||
|
printf ("\\}_{");
|
||||||
|
latexTermPrint (term->key, highlight);
|
||||||
|
printf ("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
latexTermlistPrint (Termlist tl, Termlist highlight)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
printf ("[Empty]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf ("[");
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
latexTermPrint (tl->term, highlight);
|
||||||
|
tl = tl->next;
|
||||||
|
if (tl != NULL)
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
printf ("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexTimers(const System sys)
|
||||||
|
{
|
||||||
|
void endline(void) {
|
||||||
|
printf("\\\\ \\hline\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\\begin{tabular}{|r|r|c|r|} \\hline\n");
|
||||||
|
|
||||||
|
/* display stats, header first */
|
||||||
|
|
||||||
|
printf("Time & States & Attack & st/sec");
|
||||||
|
endline();
|
||||||
|
|
||||||
|
/* print time */
|
||||||
|
|
||||||
|
double seconds;
|
||||||
|
seconds = (double) clock() / CLOCKS_PER_SEC;
|
||||||
|
printf("$%.3e$ &", seconds);
|
||||||
|
|
||||||
|
/* states traversed */
|
||||||
|
|
||||||
|
printf("$");
|
||||||
|
statesPrintShort(sys);
|
||||||
|
printf("$ &");
|
||||||
|
|
||||||
|
/* flag
|
||||||
|
*
|
||||||
|
* L n Attack of length <n>
|
||||||
|
* None failed claim
|
||||||
|
* NoClaim no claims
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sys->claims == 0) {
|
||||||
|
printf("NoClaim & ");
|
||||||
|
} else {
|
||||||
|
if (sys->failed > 0)
|
||||||
|
printf("L:%i & ", attackLength(sys->attack));
|
||||||
|
else
|
||||||
|
printf("None & ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("%.3e (%li) claims encountered.\n",(double)
|
||||||
|
sys->claims, sys->claims);
|
||||||
|
printf("%.3e (%li) claims failed.\n",(double)
|
||||||
|
sys->failed, sys->failed);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* states per second */
|
||||||
|
|
||||||
|
if (seconds > 0) {
|
||||||
|
printf("$%.3e$ ",
|
||||||
|
(double) (sys->statesLow +
|
||||||
|
(sys->statesHigh * ULONG_MAX)) / seconds);
|
||||||
|
} else {
|
||||||
|
printf("$\\infty$ ");
|
||||||
|
}
|
||||||
|
endline();
|
||||||
|
|
||||||
|
printf("\\end{tabular}\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexMSCStart()
|
||||||
|
{
|
||||||
|
if (landscape)
|
||||||
|
printf("\\begin{landscape}\n");
|
||||||
|
|
||||||
|
printf("\\begin{msc}{attack}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexMSCEnd()
|
||||||
|
{
|
||||||
|
printf("\\end{msc}\n");
|
||||||
|
|
||||||
|
if (landscape)
|
||||||
|
printf("\\end{landscape}\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexDeclInst(const System sys, int run)
|
||||||
|
{
|
||||||
|
Term bar = NULL;
|
||||||
|
|
||||||
|
bar = agentOfRun(sys, run);
|
||||||
|
printf("\\declinst{run%d}{$", run);
|
||||||
|
termPrint(bar);
|
||||||
|
printf("\\sharp%i$}{$", run);
|
||||||
|
agentsOfRunPrint(sys, run);
|
||||||
|
printf("$}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexEventSpace(int amount)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
//printf("%% number of newlines: %d\n",amount);
|
||||||
|
for (i = 0; i < EVENTSPACE * amount; i++)
|
||||||
|
printf("\\nextlevel\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void latexMessagePrint(struct tracebuf *tb, int from, int to)
|
||||||
|
{
|
||||||
|
|
||||||
|
Term sendTerm = NULL;
|
||||||
|
Term readTerm = NULL;
|
||||||
|
|
||||||
|
if (from == -1 && to == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (from != -1) {
|
||||||
|
sendTerm = tb->event[from]->message;
|
||||||
|
}
|
||||||
|
if (to != -1) {
|
||||||
|
readTerm = tb->event[to]->message;
|
||||||
|
}
|
||||||
|
if (from == -1 && to != -1) {
|
||||||
|
printf("\\found{$");
|
||||||
|
termPrint(readTerm);
|
||||||
|
printf("$}{}{run%d}\n", tb->run[to]);
|
||||||
|
} else if (from != -1 && to == -1) {
|
||||||
|
printf("\\lost{$");
|
||||||
|
termPrint(sendTerm);
|
||||||
|
printf("$}{}{run%d}\n", tb->run[from]);
|
||||||
|
} else if (from != -1 && to != -1) {
|
||||||
|
|
||||||
|
printf("\\mess{$");
|
||||||
|
|
||||||
|
termPrint(sendTerm);
|
||||||
|
|
||||||
|
if (!isTermEqual(sendTerm, readTerm)) {
|
||||||
|
printf("\\rightarrow");
|
||||||
|
termPrint(readTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("$}{run%d", tb->run[from]);
|
||||||
|
printf("}{run%d}[%d]", tb->run[to],
|
||||||
|
EVENTSPACE * (tinfo[to].position -
|
||||||
|
tinfo[from].position));
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void latexMessagePrintHighlight(struct tracebuf *tb, int from, int to, Termlist highlight)
|
||||||
|
{
|
||||||
|
|
||||||
|
Term sendTerm = NULL;
|
||||||
|
Term readTerm = NULL;
|
||||||
|
|
||||||
|
if (from == -1 && to == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (from != -1) {
|
||||||
|
sendTerm = tb->event[from]->message;
|
||||||
|
}
|
||||||
|
if (to != -1) {
|
||||||
|
readTerm = tb->event[to]->message;
|
||||||
|
}
|
||||||
|
if (from == -1 && to != -1) {
|
||||||
|
printf("\\found{$");
|
||||||
|
latexTermPrint(readTerm, highlight);
|
||||||
|
printf("$}{}{run%d}\n", tb->run[to]);
|
||||||
|
} else if (from != -1 && to == -1) {
|
||||||
|
printf("\\lost{$");
|
||||||
|
latexTermPrint(sendTerm, highlight);
|
||||||
|
printf("$}{}{run%d}\n", tb->run[from]);
|
||||||
|
} else if (from != -1 && to != -1) {
|
||||||
|
|
||||||
|
printf("\\mess{$");
|
||||||
|
|
||||||
|
latexTermPrint(sendTerm, highlight);
|
||||||
|
|
||||||
|
if (!isTermEqual(sendTerm, readTerm)) {
|
||||||
|
printf("\\rightarrow");
|
||||||
|
latexTermPrint(readTerm, highlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("$}{run%d", tb->run[from]);
|
||||||
|
printf("}{run%d}[%d]", tb->run[to],
|
||||||
|
EVENTSPACE * (tinfo[to].position -
|
||||||
|
tinfo[from].position));
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void latexLearnComment(struct tracebuf *tb, int index, Termlist tl)
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("\\msccomment[4ex]{$I_%d=I_%d\\oplus ", index + 1,
|
||||||
|
index);
|
||||||
|
termlistPrint(tl);
|
||||||
|
printf("$}{envright}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexAction(struct tracebuf *tb, int te)
|
||||||
|
{
|
||||||
|
printf("\\action{$");
|
||||||
|
termPrint(tb->event[te]->message);
|
||||||
|
printf("$}{run%d}\n", tb->run[te]);
|
||||||
|
//printf("\\nextlevel\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void latexClaim(struct tracebuf *tb, int run, Termlist tl)
|
||||||
|
{
|
||||||
|
printf("\\condition{$");
|
||||||
|
printf("\\neg secret ");
|
||||||
|
termlistPrint(tl);
|
||||||
|
printf("$}{run%d}\n", run);
|
||||||
|
}
|
||||||
|
|
||||||
|
int latexCorrespondingSend(struct tracebuf *tb, int rd)
|
||||||
|
{
|
||||||
|
|
||||||
|
int labelMatch = 0;
|
||||||
|
int toMatch = 0;
|
||||||
|
int fromMatch = 0;
|
||||||
|
int tofromMatch = 0;
|
||||||
|
int messageMatch = 0;
|
||||||
|
int nMatches = 0;
|
||||||
|
int maxNMatches = 0;
|
||||||
|
|
||||||
|
int readEvent = rd;
|
||||||
|
int sendEvent = -1;
|
||||||
|
int bestSendEvent = -1;
|
||||||
|
|
||||||
|
for (sendEvent = readEvent; sendEvent >= 0; sendEvent--) {
|
||||||
|
if (tb->event[sendEvent]->type == SEND) {
|
||||||
|
/* do all the different kind of matchings first */
|
||||||
|
|
||||||
|
labelMatch =
|
||||||
|
isTermEqual(tb->event[sendEvent]->label,
|
||||||
|
tb->event[readEvent]->label);
|
||||||
|
toMatch =
|
||||||
|
isTermEqual(tb->event[sendEvent]->to,
|
||||||
|
tb->event[readEvent]->to);
|
||||||
|
fromMatch =
|
||||||
|
isTermEqual(tb->event[sendEvent]->from,
|
||||||
|
tb->event[readEvent]->from);
|
||||||
|
tofromMatch = toMatch || fromMatch;
|
||||||
|
messageMatch =
|
||||||
|
isTermEqual(tb->event[sendEvent]->message,
|
||||||
|
tb->event[readEvent]->message);
|
||||||
|
|
||||||
|
/* calculate the score */
|
||||||
|
|
||||||
|
nMatches = labelMatch + tofromMatch + messageMatch;
|
||||||
|
|
||||||
|
if (nMatches == 3) {
|
||||||
|
/* bingo! success on all matches */
|
||||||
|
|
||||||
|
//printf("Found perfect match: %d\n", s);
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nMatches > maxNMatches) {
|
||||||
|
if (labelMatch && messageMatch) {
|
||||||
|
/* strongest restriction: message and label should match */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
|
||||||
|
} else if (messageMatch) {
|
||||||
|
/* if label AND message don't match: */
|
||||||
|
/* at least message should match */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
} else if (labelMatch) {
|
||||||
|
/* if message doesn't match */
|
||||||
|
/* the label should matches */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//bestSendEvent = NULL;
|
||||||
|
if (bestSendEvent == -1) {
|
||||||
|
|
||||||
|
int u;
|
||||||
|
|
||||||
|
for (u = 0; u < rd; u++) {
|
||||||
|
if (tb->event[u]->type == SEND) {
|
||||||
|
//knowledgePrint(sys->traceKnow[u]);
|
||||||
|
if (inKnowledge
|
||||||
|
(tb->know[u + 1], tb->event[readEvent]->message)) {
|
||||||
|
bestSendEvent = u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestSendEvent == -1) {
|
||||||
|
printf("%% Could not find a matching SEND\n");
|
||||||
|
}
|
||||||
|
return bestSendEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
newInKnowledge (const Knowledge know, Term term)
|
||||||
|
{
|
||||||
|
/* if there is no term, then it's okay 'fur sure' */
|
||||||
|
if (term == NULL)
|
||||||
|
return 1;
|
||||||
|
/* if there is a term, but no knowledge, we're in trouble */
|
||||||
|
if (know == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mindwipe (know, inKnowledge (know, term));
|
||||||
|
|
||||||
|
term = deVar (term);
|
||||||
|
if (isTermLeaf (term))
|
||||||
|
{
|
||||||
|
return inTermlist (know->basic, term);
|
||||||
|
}
|
||||||
|
if (term->type == ENCRYPT)
|
||||||
|
{
|
||||||
|
return inTermlist (know->encrypt, term) ||
|
||||||
|
(inKnowledge (know, term->key) || inKnowledge (know, term->op));
|
||||||
|
}
|
||||||
|
if (term->type == TUPLE)
|
||||||
|
{
|
||||||
|
return (inTermlist (know->encrypt, term) ||
|
||||||
|
(inKnowledge (know, term->op1) ||
|
||||||
|
inKnowledge (know, term->op2)));
|
||||||
|
}
|
||||||
|
return 0; /* unrecognized term type, weird */
|
||||||
|
}
|
||||||
|
|
||||||
|
int latexCorrespondingSend2(struct tracebuf *tb, int readEvent)
|
||||||
|
{
|
||||||
|
int u;
|
||||||
|
|
||||||
|
for (u = tb->length - 1; u>=0 ; u--)
|
||||||
|
{
|
||||||
|
if (tb->event[u]->type == SEND)
|
||||||
|
{
|
||||||
|
if (!inKnowledge (tb->know[u], tb->event[readEvent]->message))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
printf("%% term[");
|
||||||
|
printf("]#%d is introduced at traceEvent[%d] ",readEvent,u);
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display knowledge in LaTeX format.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void knowledgePrintLatex(Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
if (know == NULL)
|
||||||
|
{
|
||||||
|
printf("\\emptyset");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tl = knowledgeSet(know);
|
||||||
|
termlistPrint(tl);
|
||||||
|
termlistDelete(tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void attackDisplayLatex(System sys)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct tracebuf *tb;
|
||||||
|
int *runPosition;
|
||||||
|
int currRun;
|
||||||
|
int position;
|
||||||
|
int eventSize;
|
||||||
|
Termlist tl;
|
||||||
|
Termlist newtl;
|
||||||
|
Termlist claimDetails;
|
||||||
|
Termlist highlights = NULL;
|
||||||
|
int cKnowledge;
|
||||||
|
int bestSend;
|
||||||
|
|
||||||
|
tb = sys->attack;
|
||||||
|
if (tb == NULL) {
|
||||||
|
printf("Attack pointer empty: nothing to display.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* set variables */
|
||||||
|
varbufSet (sys, tb->variables);
|
||||||
|
|
||||||
|
/* Rebuild knowledge. Strange, this ought to be good.
|
||||||
|
* Maybe reconstruct dependencies as well. */
|
||||||
|
tracebufRebuildKnow(tb);
|
||||||
|
|
||||||
|
/* Make a comment in which the trace is displayed, for debugging etc. */
|
||||||
|
printf("\n\\comment{ TRACE\n\n");
|
||||||
|
printf("Length: %i\n",tb->length);
|
||||||
|
printf("Reallength: %i\n",tb->reallength);
|
||||||
|
printf("\n");
|
||||||
|
i = 0;
|
||||||
|
while (i <= tb->length)
|
||||||
|
{
|
||||||
|
printf("Knowledge %i:\n",i);
|
||||||
|
knowledgePrint(tb->know[i]);
|
||||||
|
printf(" [Inverses]: ");
|
||||||
|
knowledgeInversesPrint(tb->know[i]);
|
||||||
|
printf("\n\n");
|
||||||
|
if (i < tb->length)
|
||||||
|
{
|
||||||
|
printf("Event %i\t[",i);
|
||||||
|
switch (tb->status[i])
|
||||||
|
{
|
||||||
|
case S_UNK:
|
||||||
|
printf("?");
|
||||||
|
break;
|
||||||
|
case S_RED:
|
||||||
|
printf("redundant");
|
||||||
|
break;
|
||||||
|
case S_TOD:
|
||||||
|
printf("to do");
|
||||||
|
break;
|
||||||
|
case S_OKE:
|
||||||
|
printf("okay");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("illegal status code");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("]\t");
|
||||||
|
termPrint(tb->event[i]->message);
|
||||||
|
printf("\t#%i",tb->run[i]);
|
||||||
|
printf("\n");
|
||||||
|
roledefPrint(tb->event[i]);
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
|
||||||
|
/* display initial knowledge */
|
||||||
|
printf("$I_0 = \\emptyset \\oplus ");
|
||||||
|
knowledgePrintLatex(tb->know[0]);
|
||||||
|
printf("$\n\n");
|
||||||
|
|
||||||
|
tinfo =
|
||||||
|
(struct traceinfo *) memAlloc((tb->length+1) *
|
||||||
|
sizeof(struct traceinfo));
|
||||||
|
|
||||||
|
width = 1;
|
||||||
|
for (i = 0; i < tb->length; i++) {
|
||||||
|
if (tb->run[i] >= width)
|
||||||
|
width = tb->run[i] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < tb->length; i++) {
|
||||||
|
tb->link[i] = -1;
|
||||||
|
tinfo[i].match = -1;
|
||||||
|
tinfo[i].position = i;
|
||||||
|
}
|
||||||
|
tinfo[i].match = -1;
|
||||||
|
tinfo[i].position = i;
|
||||||
|
|
||||||
|
runPosition = (int *) memAlloc(width * sizeof(int));
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
runPosition[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = tb->length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (tb->status[i] != S_RED)
|
||||||
|
{
|
||||||
|
if (tb->event[i]->type == READ && !tb->event[i]->internal)
|
||||||
|
{
|
||||||
|
bestSend = latexCorrespondingSend2(tb, i);
|
||||||
|
printf("%% match: %d <-> %d\n",i, bestSend);
|
||||||
|
if (bestSend == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tb->link[i] = bestSend;
|
||||||
|
tb->link[bestSend] = i;
|
||||||
|
}
|
||||||
|
if (tb->event[i]->type == CLAIM)
|
||||||
|
{
|
||||||
|
claimDetails = claimViolationDetails(sys, tb->run[i], tb->event[i], tb->know[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\\comment{ claimDetails :\n");
|
||||||
|
termlistPrint(claimDetails);
|
||||||
|
printf("\n}\n");
|
||||||
|
|
||||||
|
// landscape = (width > 4); // not for the time being
|
||||||
|
|
||||||
|
position = 0;
|
||||||
|
currRun = 0;
|
||||||
|
eventSize = 0;
|
||||||
|
for (i = 0; i < tb->length; i++)
|
||||||
|
{
|
||||||
|
if (tb->status[i] != S_RED)
|
||||||
|
{
|
||||||
|
tinfo[i].position = position;
|
||||||
|
eventSize = 1;
|
||||||
|
currRun = tb->run[i];
|
||||||
|
|
||||||
|
switch (tb->event[i]->type) {
|
||||||
|
case SEND:
|
||||||
|
position++;
|
||||||
|
tinfo[i].position++;
|
||||||
|
break;
|
||||||
|
case READ:
|
||||||
|
if (tb->link[i] != -1) {
|
||||||
|
if (termDistance(tb->event[i]->message,tb->event[tb->link[i]]->message) < LINKTHRESHOLD)
|
||||||
|
{
|
||||||
|
/* disconnect read-send */
|
||||||
|
tb->link[tb->link[i]] = -1;
|
||||||
|
tb->link[i] = -1;
|
||||||
|
} else {
|
||||||
|
if (runPosition[currRun] <= tinfo[tb->link[i]].position &&
|
||||||
|
currRun != tb->run[tb->link[i]])
|
||||||
|
{
|
||||||
|
printf("\\comment{\n");
|
||||||
|
termPrint(tb->event[i]->message);
|
||||||
|
printf("\n");
|
||||||
|
termPrint(tb->event[tb->link[i]]->message);
|
||||||
|
printf("\n");
|
||||||
|
printf("%% termDistance: %f\n",
|
||||||
|
termDistance(tb->event[i]->message,
|
||||||
|
tb->event[tb->link[i]]->message));
|
||||||
|
printf("}\n");
|
||||||
|
tinfo[i].position = tinfo[tb->link[i]].position;
|
||||||
|
eventSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tb->event[i]->internal) {
|
||||||
|
eventSize = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLAIM:
|
||||||
|
if (claimDetails != NULL && claimDetails != (Termlist) -1) {
|
||||||
|
eventSize = 2;
|
||||||
|
} else {
|
||||||
|
eventSize = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(tb->event[i]->type == READ && tb->event[i]->internal))
|
||||||
|
runPosition[currRun] = tinfo[i].position + eventSize;
|
||||||
|
/* printf("%% Event %d at %d\n", i, position); */
|
||||||
|
position += eventSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
latexMSCStart();
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
if (runPosition[i] > 0)
|
||||||
|
latexDeclInst(sys, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//for (j=-1; j<=sys->step; j++)
|
||||||
|
position = 0;
|
||||||
|
cKnowledge = 0;
|
||||||
|
for (i = 0; i < tb->length; i++)
|
||||||
|
{
|
||||||
|
if (tb->status[i] != S_RED)
|
||||||
|
{
|
||||||
|
latexEventSpace(tinfo[i].position - position);
|
||||||
|
if (tinfo[i].position >= position)
|
||||||
|
{
|
||||||
|
position = tinfo[i].position;
|
||||||
|
}
|
||||||
|
switch (tb->event[i]->type) {
|
||||||
|
case SEND:
|
||||||
|
newtl = knowledgeNew(tb->know[i], tb->know[i + 1]);
|
||||||
|
highlights = NULL;
|
||||||
|
/* Build a Termlist of terms that from the claimViolationDetails,
|
||||||
|
that appear in the knowledge */
|
||||||
|
if (newtl != NULL)
|
||||||
|
{
|
||||||
|
tl = claimDetails;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (inTermlist(newtl, tl->term))
|
||||||
|
{
|
||||||
|
highlights = termlistAdd(highlights, tl->term);
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
printf("\\msccomment[4ex]{$I_%d=I_%d\\oplus ", cKnowledge + 1,
|
||||||
|
cKnowledge);
|
||||||
|
cKnowledge++;
|
||||||
|
latexTermlistPrint(newtl, highlights);
|
||||||
|
printf("$}{envright}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb->link[i] != -1 && i < tb->length) {
|
||||||
|
latexMessagePrintHighlight(tb, i, tb->link[i], highlights);
|
||||||
|
} else {
|
||||||
|
latexMessagePrintHighlight(tb, i, -1, highlights); //lost message
|
||||||
|
}
|
||||||
|
termlistDelete(highlights);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case READ:
|
||||||
|
if (tb->event[i]->internal) {
|
||||||
|
} else if (tb->link[i] == -1) {
|
||||||
|
latexMessagePrint(tb, -1, i); //found message
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLAIM:
|
||||||
|
if (claimDetails != NULL && claimDetails != (Termlist) -1) {
|
||||||
|
latexClaim(tb, tb->run[i], claimDetails);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; //kannie!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
latexEventSpace(2);
|
||||||
|
latexMSCEnd();
|
||||||
|
memFree(runPosition, width * sizeof(int));
|
||||||
|
memFree(tinfo, (tb->length+1) * sizeof(struct traceinfo));
|
||||||
|
}
|
21
src/latex.h
Normal file
21
src/latex.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* LaTeX output component header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LATEX
|
||||||
|
#define LATEX
|
||||||
|
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
void latexInit(const System sys, int argc, char **argv);
|
||||||
|
void latexDone(const System sys);
|
||||||
|
void latexTimers(const System sys);
|
||||||
|
void latexMSCStart();
|
||||||
|
void latexMSCEnd();
|
||||||
|
void latexDeclInst(const System sys);
|
||||||
|
void latexMessagePrint(const System sys, int from, int to);
|
||||||
|
void latexLearnComment(const System sys, Termlist tl);
|
||||||
|
void latexTracePrint(System sys);
|
||||||
|
void attackDisplayLatex(System sys);
|
||||||
|
|
||||||
|
#endif
|
4
src/license.txt
Normal file
4
src/license.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- GNU getopt
|
||||||
|
- GNU bison/flex
|
||||||
|
- ARGTABLE http://argtable.sourceforge.net/
|
||||||
|
- de rest (c) Cas
|
1
src/lutger-todo.txt
Normal file
1
src/lutger-todo.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
- TODO vullen
|
548
src/main.c
Normal file
548
src/main.c
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "runs.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "modelchecker.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "pheading.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "tok.h"
|
||||||
|
#include "tac.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "latex.h"
|
||||||
|
#include "output.h"
|
||||||
|
|
||||||
|
#include "argtable2.h"
|
||||||
|
|
||||||
|
extern struct tacnode *spdltac;
|
||||||
|
void scanner_cleanup (void);
|
||||||
|
void strings_cleanup (void);
|
||||||
|
int yyparse (void);
|
||||||
|
|
||||||
|
void MC_incRuns (const System sys);
|
||||||
|
void MC_incTraces (const System sys);
|
||||||
|
void MC_single (const System sys);
|
||||||
|
int modelCheck (const System sys);
|
||||||
|
|
||||||
|
const char *progname = "scyther";
|
||||||
|
const char *releasetag = "alpha2-devel";
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
System sys;
|
||||||
|
|
||||||
|
struct arg_int *traversal = arg_int0 ("t", "traverse", NULL,
|
||||||
|
"set traversal method, partial order reduction (default is 8)");
|
||||||
|
struct arg_rem *trav1 = arg_rem (NULL, "1 : nondeterministic.");
|
||||||
|
struct arg_rem *trav2 = arg_rem (NULL, "2 : nonreads first.");
|
||||||
|
struct arg_rem *trav3 = arg_rem (NULL, "3 : nonreads; supertransition.");
|
||||||
|
struct arg_rem *trav4 =
|
||||||
|
arg_rem (NULL, "4 : nonreads; supertransition; forbidden");
|
||||||
|
struct arg_rem *trav5 = arg_rem (NULL,
|
||||||
|
"5 : nonreads; supertransition; forbidden; remove hopeless");
|
||||||
|
struct arg_rem *trav6 =
|
||||||
|
arg_rem (NULL, "6 : secrecy p.o. reduction, new style");
|
||||||
|
struct arg_rem *trav7 = arg_rem (NULL,
|
||||||
|
"7 : nonreads; supertransition; forbidden; remove hopeless V2");
|
||||||
|
struct arg_rem *trav8 =
|
||||||
|
arg_rem (NULL, "8 : nondeterministic knowledge brancher");
|
||||||
|
struct arg_int *match =
|
||||||
|
arg_int0 ("m", "match", NULL, "matching method (default is 0)");
|
||||||
|
struct arg_rem *match0 = arg_rem (NULL, "0 : typed.");
|
||||||
|
struct arg_rem *match1 = arg_rem (NULL, "1 : basic typeflaws.");
|
||||||
|
struct arg_rem *match2 = arg_rem (NULL, "2 : full typeflaws");
|
||||||
|
struct arg_lit *clp =
|
||||||
|
arg_lit0 ("c", "cl", "use constraint logic, non-associative.");
|
||||||
|
struct arg_int *prune = arg_int0 ("p", "prune", NULL,
|
||||||
|
"pruning method (default is 2)");
|
||||||
|
struct arg_rem *prune0 =
|
||||||
|
arg_rem (NULL, "0 : search all traces, no pruning.");
|
||||||
|
struct arg_rem *prune1 = arg_rem (NULL,
|
||||||
|
"1 : search traces of any length until a violation occurs.");
|
||||||
|
struct arg_rem *prune2 = arg_rem (NULL,
|
||||||
|
"2 : search progessively shorter traces after a violated claim.");
|
||||||
|
struct arg_rem *prune3 = arg_rem (NULL, "3 : quit after a violated claim.");
|
||||||
|
struct arg_int *maxlength = arg_int0 ("l", "max-length", NULL,
|
||||||
|
"prune traces longer than <int> events.");
|
||||||
|
struct arg_lit *incTraces = arg_lit0 (NULL, "increment-traces",
|
||||||
|
"incremental search using the length of the traces.");
|
||||||
|
struct arg_int *maxruns =
|
||||||
|
arg_int0 ("r", "max-runs", NULL, "create at most <int> runs.");
|
||||||
|
struct arg_lit *incRuns = arg_lit0 (NULL, "increment-runs",
|
||||||
|
"incremental search using the number of runs.");
|
||||||
|
struct arg_lit *latex = arg_lit0 (NULL, "latex", "output in LaTeX format.");
|
||||||
|
struct arg_lit *noreport =
|
||||||
|
arg_lit0 ("d", "disable-report", "don't report violations.");
|
||||||
|
struct arg_int *switchS = arg_int0 ("s", "states", NULL,
|
||||||
|
"report total number of states and claims traversed.");
|
||||||
|
struct arg_rem *switchS0 =
|
||||||
|
arg_rem (NULL, "if <int> is not 0, report progress after <int> states.");
|
||||||
|
// struct arg_file *outfile = arg_file0("o",NULL,"<output>", "output file (default is \"-\")");
|
||||||
|
#ifdef DEBUG
|
||||||
|
struct arg_int *porparam = arg_int0 (NULL, "pp", NULL, "POR parameter.");
|
||||||
|
struct arg_lit *switchI = arg_lit0 ("I", "debug-indent",
|
||||||
|
"indent the debug output using trace length.");
|
||||||
|
struct arg_int *debugl =
|
||||||
|
arg_int0 ("D", "debug", NULL, "set debug level (default is 0)");
|
||||||
|
#endif
|
||||||
|
struct arg_lit *help = arg_lit0 (NULL, "help", "print this help and exit");
|
||||||
|
struct arg_lit *version =
|
||||||
|
arg_lit0 (NULL, "version", "print version information and exit");
|
||||||
|
//struct arg_file *infiles = arg_filen(NULL,NULL,"FILE",0,argc+2, "input file(s)");
|
||||||
|
struct arg_end *end = arg_end (30);
|
||||||
|
void *argtable[] = {
|
||||||
|
traversal, trav1, trav2, trav3, trav4, trav5, trav6, trav7, trav8,
|
||||||
|
match, match0, match1, match2,
|
||||||
|
clp,
|
||||||
|
prune, prune0, prune1, prune2, prune3,
|
||||||
|
maxlength, incTraces,
|
||||||
|
maxruns, incRuns,
|
||||||
|
latex,
|
||||||
|
noreport,
|
||||||
|
switchS, switchS0,
|
||||||
|
#ifdef DEBUG
|
||||||
|
porparam,
|
||||||
|
switchI,
|
||||||
|
debugl,
|
||||||
|
#endif
|
||||||
|
help, version,
|
||||||
|
// infiles,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
int nerrors;
|
||||||
|
int exitcode = 0;
|
||||||
|
|
||||||
|
/* verify the argtable[] entries were allocated sucessfully */
|
||||||
|
if (arg_nullcheck (argtable) != 0)
|
||||||
|
{
|
||||||
|
/* NULL entries were detected, some allocations must have failed */
|
||||||
|
printf ("%s: insufficient memory\n", progname);
|
||||||
|
exitcode = 1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* defaults
|
||||||
|
* set any command line default values prior to parsing */
|
||||||
|
#ifdef DEBUG
|
||||||
|
debugl->ival[0] = 0;
|
||||||
|
porparam->ival[0] = 0;
|
||||||
|
#endif
|
||||||
|
traversal->ival[0] = 8;
|
||||||
|
match->ival[0] = 0;
|
||||||
|
maxlength->ival[0] = -1;
|
||||||
|
maxruns->ival[0] = INT_MAX;
|
||||||
|
prune->ival[0] = 2;
|
||||||
|
switchS->ival[0] = 0;
|
||||||
|
|
||||||
|
/* Parse the command line as defined by argtable[] */
|
||||||
|
nerrors = arg_parse (argc, argv, argtable);
|
||||||
|
|
||||||
|
/* special case: '--help' takes precedence over error reporting */
|
||||||
|
if (help->count > 0)
|
||||||
|
{
|
||||||
|
printf ("Usage: %s ", progname);
|
||||||
|
arg_print_syntax (stdout, argtable, "\n");
|
||||||
|
printf
|
||||||
|
("This program can model check security protocols for various\n");
|
||||||
|
printf ("properties, given a finite scenario.\n\n");
|
||||||
|
arg_print_glossary (stdout, argtable, " %-25s %s\n");
|
||||||
|
exitcode = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case: '--version' takes precedence error reporting */
|
||||||
|
if (version->count > 0)
|
||||||
|
{
|
||||||
|
printf ("'%s' model checker for security protocols.\n", progname);
|
||||||
|
printf ("%s release.\n", releasetag);
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf ("Compiled with debugging support.\n");
|
||||||
|
#endif
|
||||||
|
printf ("December 2003--, Cas Cremers\n");
|
||||||
|
exitcode = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the parser returned any errors then display them and exit */
|
||||||
|
if (nerrors > 0)
|
||||||
|
{
|
||||||
|
/* Display the error details contained in the arg_end struct. */
|
||||||
|
arg_print_errors (stdout, end, progname);
|
||||||
|
printf ("Try '%s --help' for more information.\n", progname);
|
||||||
|
exitcode = 1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* special case: uname with no command line options induces brief help */
|
||||||
|
/*
|
||||||
|
if (argc==1)
|
||||||
|
{
|
||||||
|
printf("Try '%s --help' for more information.\n",progname);
|
||||||
|
exitcode=0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arguments have been parsed by argtable,
|
||||||
|
* continue with main code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Lutger-tries-to-test-with-broken-methods detector */
|
||||||
|
if (clp->count > 0)
|
||||||
|
{
|
||||||
|
printf ("For the time being, this method is not supported, \n");
|
||||||
|
printf ("as too many changes have been made to the normal \n");
|
||||||
|
printf ("matching logic, and CL simply isn't reliable in \nmany ");
|
||||||
|
printf ("ways. Try again in a few weeks.\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle debug level */
|
||||||
|
#ifdef DEBUG
|
||||||
|
debugSet (debugl->ival[0]);
|
||||||
|
if (DEBUGL (1))
|
||||||
|
{
|
||||||
|
/* print command line */
|
||||||
|
int i;
|
||||||
|
printf ("$");
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf (" %s", argv[i]);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
debugSet (0);
|
||||||
|
#endif
|
||||||
|
/* Initialize memory routines */
|
||||||
|
memInit ();
|
||||||
|
|
||||||
|
/* initialize symbols */
|
||||||
|
termsInit ();
|
||||||
|
termlistsInit ();
|
||||||
|
knowledgeInit ();
|
||||||
|
symbolsInit ();
|
||||||
|
tacInit ();
|
||||||
|
|
||||||
|
/* generate system */
|
||||||
|
sys = systemInit ();
|
||||||
|
#ifdef DEBUG
|
||||||
|
sys->porparam = porparam->ival[0];
|
||||||
|
#endif
|
||||||
|
sys->latex = latex->count;
|
||||||
|
sys->know = emptyKnowledge ();
|
||||||
|
|
||||||
|
/* parse input */
|
||||||
|
|
||||||
|
yyparse ();
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (1))
|
||||||
|
tacPrint (spdltac);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* compile */
|
||||||
|
|
||||||
|
compile (sys, spdltac, maxruns->ival[0]);
|
||||||
|
scanner_cleanup ();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (1))
|
||||||
|
{
|
||||||
|
printf ("\nCompilation yields:\n\n");
|
||||||
|
printf ("untrusted agents: ");
|
||||||
|
termlistPrint (sys->untrusted);
|
||||||
|
printf ("\n");
|
||||||
|
knowledgePrint (sys->know);
|
||||||
|
printf ("inverses: ");
|
||||||
|
knowledgeInversesPrint (sys->know);
|
||||||
|
printf ("\n");
|
||||||
|
locVarPrint (sys->locals);
|
||||||
|
protocolsPrint (sys->protocols);
|
||||||
|
|
||||||
|
printf ("\nInstantiated runs:\n\n");
|
||||||
|
runsPrint (sys);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* allocate memory for traces, based on runs */
|
||||||
|
systemStart (sys);
|
||||||
|
sys->traceKnow[0] = sys->know; // store initial knowledge
|
||||||
|
|
||||||
|
/* add parameters to system */
|
||||||
|
|
||||||
|
sys->clp = (clp->count > 0 ? 1 : 0);
|
||||||
|
|
||||||
|
sys->traverse = traversal->ival[0];
|
||||||
|
sys->match = match->ival[0];
|
||||||
|
sys->prune = prune->ival[0];
|
||||||
|
sys->switchS = switchS->ival[0];
|
||||||
|
|
||||||
|
/* TODO for now, warning for -m2 and non-clp */
|
||||||
|
if (sys->match == 2 && !sys->clp)
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
("Warning: -m2 is only supported for constraint logic programming.\n");
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* in debugging mode, some extra switches */
|
||||||
|
if (switchI->count > 0)
|
||||||
|
indentActivate ();
|
||||||
|
if (DEBUGL (1))
|
||||||
|
printf ("Using traversal method %i.\n", sys->traverse);
|
||||||
|
#else
|
||||||
|
/* non-debug defaults */
|
||||||
|
sys->switchM = 0;
|
||||||
|
#endif
|
||||||
|
if (noreport->count > 0)
|
||||||
|
sys->report = 0;
|
||||||
|
if (maxlength->ival[0] >= 0)
|
||||||
|
sys->switch_maxtracelength = maxlength->ival[0];
|
||||||
|
|
||||||
|
/* latex header? */
|
||||||
|
if (sys->latex)
|
||||||
|
latexInit (sys, argc, argv);
|
||||||
|
|
||||||
|
/* model check system */
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (1))
|
||||||
|
printf ("Start modelchecking system.\n");
|
||||||
|
#endif
|
||||||
|
if (incRuns->count > 0)
|
||||||
|
{
|
||||||
|
MC_incRuns (sys);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (incTraces->count > 0)
|
||||||
|
{
|
||||||
|
MC_incTraces (sys);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MC_single (sys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display shortest attack, if any */
|
||||||
|
|
||||||
|
if (sys->attack != NULL && sys->attack->length != 0)
|
||||||
|
{
|
||||||
|
attackDisplay(sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* latex closeup */
|
||||||
|
if (sys->latex)
|
||||||
|
latexDone (sys);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we clean up any memory that was allocated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
knowledgeDestroy (sys->know);
|
||||||
|
systemDone (sys);
|
||||||
|
|
||||||
|
/* done symbols */
|
||||||
|
tacDone ();
|
||||||
|
symbolsDone ();
|
||||||
|
knowledgeDone ();
|
||||||
|
termlistsDone ();
|
||||||
|
termsDone ();
|
||||||
|
|
||||||
|
/* memory clean up? */
|
||||||
|
strings_cleanup ();
|
||||||
|
memDone ();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* deallocate each non-null entry in argtable[] */
|
||||||
|
arg_free (argtable);
|
||||||
|
|
||||||
|
return exitcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
timersPrint (const System sys)
|
||||||
|
{
|
||||||
|
/* display stats, header first */
|
||||||
|
|
||||||
|
printf ("Time\t\tStates\t\tAttack\t\tst/sec\n");
|
||||||
|
|
||||||
|
/* print time */
|
||||||
|
|
||||||
|
double seconds;
|
||||||
|
seconds = (double) clock () / CLOCKS_PER_SEC;
|
||||||
|
printf ("%.3e\t", seconds);
|
||||||
|
|
||||||
|
/* states traversed */
|
||||||
|
|
||||||
|
statesPrintShort (sys);
|
||||||
|
printf ("\t");
|
||||||
|
|
||||||
|
/* flag
|
||||||
|
*
|
||||||
|
* L n Attack of length <n>
|
||||||
|
* None failed claim
|
||||||
|
* NoClaim no claims
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sys->claims == 0)
|
||||||
|
{
|
||||||
|
printf ("NoClaim\t\t");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sys->failed > 0)
|
||||||
|
printf ("L:%i\t\t", attackLength(sys->attack));
|
||||||
|
else
|
||||||
|
printf ("None\t\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("%.3e (%li) claims encountered.\n",(double)
|
||||||
|
sys->claims, sys->claims);
|
||||||
|
printf("%.3e (%li) claims failed.\n",(double)
|
||||||
|
sys->failed, sys->failed);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* states per second */
|
||||||
|
|
||||||
|
if (seconds > 0)
|
||||||
|
{
|
||||||
|
printf ("%.3e\t",
|
||||||
|
(double) (sys->statesLow +
|
||||||
|
(sys->statesHigh * ULONG_MAX)) / seconds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("<inf>\t\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Analyse the model.
|
||||||
|
*
|
||||||
|
* This procedure considers mainly incremental searches, and settings
|
||||||
|
* parameters for that. The real work is handled by modelCheck.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
MC_incRuns (const System sys)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* incremental runs check
|
||||||
|
*
|
||||||
|
* note: we assume that at least one run needs to be checked.
|
||||||
|
*/
|
||||||
|
int maxruns = sys->maxruns;
|
||||||
|
int runs = 1;
|
||||||
|
int flag = 1;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
systemReset (sys);
|
||||||
|
sys->maxruns = runs;
|
||||||
|
printf ("%i of %i runs in incremental runs search.\n", runs, maxruns);
|
||||||
|
res = modelCheck (sys);
|
||||||
|
printf ("\n");
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
/* Apparently a violation occurred. If we are searching
|
||||||
|
* the whole space, then we just continue. However, if
|
||||||
|
* we're looking to prune, ``the buck stops here''. */
|
||||||
|
|
||||||
|
if (sys->prune != 0)
|
||||||
|
{
|
||||||
|
flag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runs++;
|
||||||
|
}
|
||||||
|
while (flag && runs <= maxruns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MC_incTraces (const System sys)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* incremental traces check
|
||||||
|
*
|
||||||
|
* note: we assume that at least one run needs to be checked.
|
||||||
|
*/
|
||||||
|
int maxtracelen;
|
||||||
|
int tracelen;
|
||||||
|
int tracestep;
|
||||||
|
|
||||||
|
tracestep = 3; /* what is a sensible stepping size? */
|
||||||
|
maxtracelen = getMaxTraceLength (sys);
|
||||||
|
tracelen = maxtracelen - tracestep;
|
||||||
|
while (tracelen > 6) /* what is a reasonable minimum? */
|
||||||
|
tracelen -= tracestep;
|
||||||
|
|
||||||
|
int flag = 1;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
systemReset (sys);
|
||||||
|
sys->maxtracelength = tracelen;
|
||||||
|
printf ("%i of %i trace length in incremental trace length search.\n",
|
||||||
|
tracelen, maxtracelen);
|
||||||
|
res = modelCheck (sys);
|
||||||
|
printf ("\n");
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
/* Apparently a violation occurred. If we are searching
|
||||||
|
* the whole space, then we just continue. However, if
|
||||||
|
* we're looking to prune, ``the buck stops here''. */
|
||||||
|
|
||||||
|
if (sys->prune != 0)
|
||||||
|
{
|
||||||
|
flag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tracelen += tracestep;
|
||||||
|
}
|
||||||
|
while (flag && tracelen <= maxtracelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Traditional handywork
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
MC_single (const System sys)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* simple one-time check
|
||||||
|
*/
|
||||||
|
|
||||||
|
systemReset (sys); // reset any globals
|
||||||
|
modelCheck (sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Model check the system, given all parameters.
|
||||||
|
*
|
||||||
|
* Precondition: the system was reset with the corresponding parameters.
|
||||||
|
* This also reports on time and states traversed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
modelCheck (const System sys)
|
||||||
|
{
|
||||||
|
traverse (sys); // start model checking
|
||||||
|
if (sys->latex)
|
||||||
|
{
|
||||||
|
latexTimers (sys);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timersPrint (sys);
|
||||||
|
}
|
||||||
|
return (sys->failed);
|
||||||
|
}
|
298
src/match_basic.c
Normal file
298
src/match_basic.c
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "memory.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "modelchecker.h"
|
||||||
|
#include "match_basic.h"
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
candidates (const Knowledge know)
|
||||||
|
{
|
||||||
|
Termlist knowset;
|
||||||
|
Termlist candlist;
|
||||||
|
|
||||||
|
/* candidates for typeless basic stuff */
|
||||||
|
knowset = knowledgeSet (know);
|
||||||
|
candlist = termlistAddBasics (NULL, knowset);
|
||||||
|
termlistDelete (knowset);
|
||||||
|
return candlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct fvpass
|
||||||
|
{
|
||||||
|
int (*solution) (struct fvpass, Knowledge);
|
||||||
|
|
||||||
|
System sys;
|
||||||
|
int run;
|
||||||
|
Roledef roledef;
|
||||||
|
int (*proceed) (System, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fix variables in a message, and check whether it can be accepted.
|
||||||
|
*
|
||||||
|
* fp.sys is only accessed for the matching type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fixVariablelist (const struct fvpass fp, const Knowledge know,
|
||||||
|
Termlist varlist, const Term message)
|
||||||
|
{
|
||||||
|
int flag = 0;
|
||||||
|
|
||||||
|
Termlist tlscan;
|
||||||
|
Termlist candlist;
|
||||||
|
|
||||||
|
if (varlist != NULL)
|
||||||
|
{
|
||||||
|
if (!isTermVariable (varlist->term))
|
||||||
|
{
|
||||||
|
while (varlist != NULL && !isTermVariable (varlist->term))
|
||||||
|
{
|
||||||
|
varlist = varlist->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cond: varlist == NULL || isTermvariable(varlist->term) */
|
||||||
|
|
||||||
|
if (varlist == NULL)
|
||||||
|
{
|
||||||
|
/* there are no (more) variables to be fixed. */
|
||||||
|
/* actually trigger it if possible */
|
||||||
|
|
||||||
|
int copied;
|
||||||
|
Knowledge tempknow;
|
||||||
|
|
||||||
|
/* first we propagate the substitutions in the knowledge */
|
||||||
|
/* TODO this must also be done for all agent knowledge!! */
|
||||||
|
|
||||||
|
if (knowledgeSubstNeeded (know))
|
||||||
|
{
|
||||||
|
copied = 1;
|
||||||
|
tempknow = knowledgeSubstDo (know);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copied = 0;
|
||||||
|
tempknow = know;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inKnowledge (tempknow, message))
|
||||||
|
{
|
||||||
|
if (fp.solution != NULL)
|
||||||
|
{
|
||||||
|
flag = fp.solution (fp, tempknow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
flag = 0;
|
||||||
|
|
||||||
|
/* restore state */
|
||||||
|
if (copied)
|
||||||
|
{
|
||||||
|
knowledgeDelete (tempknow);
|
||||||
|
knowledgeSubstUndo (know);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cond: isTermvariable(varlist->term) */
|
||||||
|
varlist->term = deVar (varlist->term);
|
||||||
|
/* cond: realTermvariable(varlist->term) */
|
||||||
|
candlist = candidates (know);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Set ");
|
||||||
|
termPrint (varlist->term);
|
||||||
|
printf (" with type ");
|
||||||
|
termlistPrint (varlist->term->stype);
|
||||||
|
printf (" from candidates ");
|
||||||
|
termlistPrint (candlist);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now check all candidates. Do they work as candidates? */
|
||||||
|
tlscan = candlist;
|
||||||
|
while (tlscan != NULL && !(flag && fp.solution == NULL))
|
||||||
|
{
|
||||||
|
if (!isTermEqual (varlist->term, tlscan->term))
|
||||||
|
{
|
||||||
|
/* substitute */
|
||||||
|
varlist->term->subst = tlscan->term;
|
||||||
|
if (validSubst (fp.sys->match, varlist->term))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Substituting ");
|
||||||
|
termPrint (varlist->term);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* now we may need to substitute more */
|
||||||
|
flag = fixVariablelist (fp, know, varlist->next, message)
|
||||||
|
|| flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tlscan = tlscan->next;
|
||||||
|
}
|
||||||
|
/* restore state: variable is not instantiated. */
|
||||||
|
varlist->term->subst = NULL;
|
||||||
|
|
||||||
|
/* garbage collect */
|
||||||
|
termlistDelete (candlist);
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check whether a roledef, given some newer knowledge substitutions, can survive
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define enabled_basic(sys,know,newterm) !inKnowledge(know,newterm)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* matchRead
|
||||||
|
*
|
||||||
|
* try to execute a read event. It must be able to be construct it from the
|
||||||
|
* current intruder knowledge (Inject), but not from the forbidden knowledge
|
||||||
|
* set, which we tried earlier.
|
||||||
|
*
|
||||||
|
* returns 0 if it is not enabled, 1 if it was enabled (and routes explored)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
matchRead_basic (const System sys, const int run,
|
||||||
|
int (*proceed) (System, int))
|
||||||
|
{
|
||||||
|
Roledef rd;
|
||||||
|
int flag = 0;
|
||||||
|
struct fvpass fp;
|
||||||
|
|
||||||
|
int solution (struct fvpass fp, Knowledge know)
|
||||||
|
{
|
||||||
|
Knowledge oldknow;
|
||||||
|
Term newterm;
|
||||||
|
|
||||||
|
/* remove variable linkages */
|
||||||
|
newterm = termDuplicateUV (fp.roledef->message);
|
||||||
|
/* a candidate, but if this is a t4 traversal, is it also an old one? */
|
||||||
|
if (fp.sys->traverse < 4 ||
|
||||||
|
fp.roledef->forbidden == NULL ||
|
||||||
|
enabled_basic (fp.sys, fp.roledef->forbidden, newterm))
|
||||||
|
{
|
||||||
|
/* it is enabled, i.e. not forbidden */
|
||||||
|
oldknow = fp.sys->know;
|
||||||
|
fp.sys->know = know;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
printf ("+");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fp.proceed (fp.sys, fp.run);
|
||||||
|
fp.sys->know = oldknow;
|
||||||
|
termDelete (newterm);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* blocked */
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
printf ("-");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
termDelete (newterm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rd = runPointerGet (sys, run);
|
||||||
|
Termlist varlist = termlistAddVariables (NULL, rd->message);
|
||||||
|
|
||||||
|
fp.sys = sys;
|
||||||
|
fp.run = run;
|
||||||
|
fp.roledef = rd;
|
||||||
|
fp.proceed = proceed;
|
||||||
|
fp.solution = solution;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("{\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
flag = fixVariablelist (fp, sys->know, varlist, rd->message);
|
||||||
|
termlistDelete (varlist);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("} with flag %i\n", flag);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* block
|
||||||
|
*
|
||||||
|
* Skips over an event. Because the intruder knowledge is incremental, we can
|
||||||
|
* just overwrite the old value of forbidden.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
block_basic (const System sys, const int run)
|
||||||
|
{
|
||||||
|
Knowledge pushKnow;
|
||||||
|
Roledef rd;
|
||||||
|
|
||||||
|
rd = runPointerGet (sys, run);
|
||||||
|
pushKnow = rd->forbidden;
|
||||||
|
rd->forbidden = sys->know;
|
||||||
|
traverse (sys);
|
||||||
|
rd->forbidden = pushKnow;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
send_basic (const System sys, const int run)
|
||||||
|
{
|
||||||
|
Roledef rd = runPointerGet (sys, run);
|
||||||
|
/* execute send, push knowledge? */
|
||||||
|
if (inKnowledge (sys->know, rd->message))
|
||||||
|
{
|
||||||
|
/* no new knowledge, so this remains */
|
||||||
|
explorify (sys, run);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* new knowledge, must store old state */
|
||||||
|
Knowledge oldknow = sys->know;
|
||||||
|
sys->know = knowledgeDuplicate (sys->know);
|
||||||
|
|
||||||
|
sys->knowPhase++;
|
||||||
|
knowledgeAddTerm (sys->know, rd->message);
|
||||||
|
explorify (sys, run);
|
||||||
|
sys->knowPhase--;
|
||||||
|
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
11
src/match_basic.h
Normal file
11
src/match_basic.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef MATCHBASIC
|
||||||
|
#define MATCHBASIC
|
||||||
|
|
||||||
|
int matchRead_basic (const System sys, const int run,
|
||||||
|
int (*proceed) (System, int));
|
||||||
|
int enabled_basic (const System sys, const Knowledge know,
|
||||||
|
const Term newterm);
|
||||||
|
int block_basic (const System sys, const int run);
|
||||||
|
int send_basic (const System sys, const int run);
|
||||||
|
|
||||||
|
#endif
|
502
src/match_clp.c
Normal file
502
src/match_clp.c
Normal file
@ -0,0 +1,502 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "match_clp.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "constraints.h"
|
||||||
|
#include "mgu.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "match_clp.h"
|
||||||
|
#include "modelchecker.h"
|
||||||
|
|
||||||
|
struct solvepass
|
||||||
|
{
|
||||||
|
int (*solution) (struct solvepass, Constraintlist);
|
||||||
|
|
||||||
|
System sys;
|
||||||
|
int run;
|
||||||
|
int (*proceed) (System, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
solve (const struct solvepass sp, Constraintlist solvecons)
|
||||||
|
{
|
||||||
|
Constraintlist activecl, cl, beforecl;
|
||||||
|
Constraint activeco;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
flag = 0;
|
||||||
|
|
||||||
|
/* locate first non-variable constraint */
|
||||||
|
activecl = firstNonVariable (solvecons);
|
||||||
|
|
||||||
|
if (activecl == NULL)
|
||||||
|
{
|
||||||
|
/* no such thing, so that's nice */
|
||||||
|
if (sp.solution != NULL)
|
||||||
|
sp.solution (sp, solvecons);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* there is an active constraint */
|
||||||
|
/* detach it from the list, but retain */
|
||||||
|
beforecl = activecl->prev;
|
||||||
|
solvecons = constraintlistUnlink (activecl);
|
||||||
|
activeco = activecl->constraint;
|
||||||
|
if (isTermTuple (activeco->term))
|
||||||
|
{
|
||||||
|
/* it's a tuple, so we unfold it first */
|
||||||
|
Constraintlist oldcl = solvecons;
|
||||||
|
cl = constraintlistDuplicate (solvecons);
|
||||||
|
cl =
|
||||||
|
constraintlistAdd (cl,
|
||||||
|
makeConstraint (deVar (activeco->term)->op1,
|
||||||
|
activeco->know));
|
||||||
|
cl =
|
||||||
|
constraintlistAdd (cl,
|
||||||
|
makeConstraint (deVar (activeco->term)->op2,
|
||||||
|
activeco->know));
|
||||||
|
solvecons = cl;
|
||||||
|
flag = solve (sp, solvecons) || flag;
|
||||||
|
constraintlistDestroy (solvecons);
|
||||||
|
solvecons = oldcl;
|
||||||
|
if (flag && sp.solution == NULL)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* not a tuple. does it unify? */
|
||||||
|
|
||||||
|
//TODO or remove: termNormalize(activeco->term);
|
||||||
|
void examine (Termlist tl)
|
||||||
|
{
|
||||||
|
Termlist tlres, tlscan;
|
||||||
|
int goodsubst;
|
||||||
|
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
//TODO or remove: termNormalize(tl->term);
|
||||||
|
tlres = termMguTerm (activeco->term, tl->term);
|
||||||
|
|
||||||
|
/* check whether this is a valid
|
||||||
|
* substitution */
|
||||||
|
goodsubst = 1;
|
||||||
|
tlscan = tlres;
|
||||||
|
while (tlscan != NULL && tlres != MGUFAIL)
|
||||||
|
{
|
||||||
|
if (validSubst (sp.sys->match, tlscan->term))
|
||||||
|
{
|
||||||
|
tlscan = tlscan->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goodsubst = 0;
|
||||||
|
tlscan = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tlres != MGUFAIL && goodsubst)
|
||||||
|
{
|
||||||
|
/* maybe this has modified current and previous knowledge! */
|
||||||
|
/* modify and copy _all_ knowledge instances, if needed, that is
|
||||||
|
all constraints as well as all agent knowledge! */
|
||||||
|
Constraintlist oldcl = NULL;
|
||||||
|
int copied = 0;
|
||||||
|
|
||||||
|
if (tlres != NULL)
|
||||||
|
{
|
||||||
|
copied = 1;
|
||||||
|
/* sometimes not needed, when no substitutions took place */
|
||||||
|
oldcl = solvecons;
|
||||||
|
solvecons = constraintlistDuplicate (solvecons);
|
||||||
|
Constraintlist cl = solvecons;
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
cl->constraint->know =
|
||||||
|
knowledgeSubstDo (cl->constraint->know);
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* explore this new state */
|
||||||
|
flag = solve (sp, solvecons) || flag;
|
||||||
|
|
||||||
|
/* undo changes */
|
||||||
|
if (copied)
|
||||||
|
{
|
||||||
|
Constraintlist cl;
|
||||||
|
cl = solvecons;
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
knowledgeDelete (cl->constraint->know);
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
constraintlistDestroy (solvecons);
|
||||||
|
solvecons = oldcl;
|
||||||
|
cl = solvecons;
|
||||||
|
while (cl != NULL)
|
||||||
|
{
|
||||||
|
knowledgeSubstUndo (cl->constraint->know);
|
||||||
|
cl = cl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* unification failed */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlres != MGUFAIL)
|
||||||
|
{
|
||||||
|
tlscan = tlres;
|
||||||
|
while (tlscan != NULL)
|
||||||
|
{
|
||||||
|
tlscan->term->subst = NULL;
|
||||||
|
tlscan = tlscan->next;
|
||||||
|
}
|
||||||
|
termlistDelete (tlres);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* abort if necessary */
|
||||||
|
if (flag && sp.solution == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
examine (activeco->know->basic);
|
||||||
|
if (flag && sp.solution == NULL)
|
||||||
|
return 1;
|
||||||
|
examine (activeco->know->encrypt);
|
||||||
|
if (flag && sp.solution == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (isTermEncrypt (activecl->constraint->term))
|
||||||
|
{
|
||||||
|
/* shouldn't this be a branch? TODO */
|
||||||
|
|
||||||
|
Constraintlist oldcl = solvecons;
|
||||||
|
cl = constraintlistDuplicate (oldcl);
|
||||||
|
cl =
|
||||||
|
constraintlistAdd (cl,
|
||||||
|
makeConstraint (activeco->term->op,
|
||||||
|
activeco->know));
|
||||||
|
cl =
|
||||||
|
constraintlistAdd (cl,
|
||||||
|
makeConstraint (activeco->term->key,
|
||||||
|
activeco->know));
|
||||||
|
solvecons = cl;
|
||||||
|
flag = solve (sp, solvecons) || flag;
|
||||||
|
constraintlistDestroy (solvecons);
|
||||||
|
solvecons = oldcl;
|
||||||
|
if (flag && sp.solution == NULL)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* relink detached link */
|
||||||
|
if (beforecl == NULL)
|
||||||
|
{
|
||||||
|
solvecons = constraintlistConcat (activecl, solvecons);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activecl->prev = beforecl;
|
||||||
|
activecl->next = beforecl->next;
|
||||||
|
beforecl->next = activecl;
|
||||||
|
if (activecl->next != NULL)
|
||||||
|
activecl->next->prev = activecl;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
matchRead_clp (const System sys, const int run, int (*proceed) (System, int))
|
||||||
|
{
|
||||||
|
Constraintlist oldcl, newcl;
|
||||||
|
Constraint co;
|
||||||
|
Roledef runPoint;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
|
||||||
|
/* save old state */
|
||||||
|
oldcl = sys->constraints;
|
||||||
|
newcl = constraintlistShallow (oldcl);
|
||||||
|
|
||||||
|
/* creat new state */
|
||||||
|
runPoint = runPointerGet (sys, run);
|
||||||
|
|
||||||
|
/* we know this is a read */
|
||||||
|
co = makeConstraint (runPoint->message, sys->know);
|
||||||
|
newcl = constraintlistAdd (newcl, co);
|
||||||
|
sys->constraints = newcl;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
constraintlistPrint (newcl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* check solvability */
|
||||||
|
int solution (const struct solvepass sp, const Constraintlist cl)
|
||||||
|
{
|
||||||
|
Knowledge oldknow = NULL;
|
||||||
|
Constraintlist oldcl = sys->constraints;
|
||||||
|
int flag = 0;
|
||||||
|
int copied = 0;
|
||||||
|
|
||||||
|
sys->constraints = cl;
|
||||||
|
if (knowledgeSubstNeeded (sys->know))
|
||||||
|
{
|
||||||
|
copied = 1;
|
||||||
|
oldknow = sys->know;
|
||||||
|
sys->know = knowledgeSubstDo (sys->know);
|
||||||
|
}
|
||||||
|
flag = sp.proceed (sys, run);
|
||||||
|
if (copied)
|
||||||
|
{
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
knowledgeSubstUndo (sys->know);
|
||||||
|
}
|
||||||
|
sys->constraints = oldcl;
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct solvepass sp;
|
||||||
|
sp.solution = solution;
|
||||||
|
sp.sys = sys;
|
||||||
|
sp.run = run;
|
||||||
|
sp.proceed = proceed;
|
||||||
|
flag = solve (sp, sys->constraints);
|
||||||
|
|
||||||
|
/* restore memory allocation */
|
||||||
|
constraintDestroy (co);
|
||||||
|
constraintlistDelete (newcl);
|
||||||
|
sys->constraints = oldcl;
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
enabled_clp (const System sys, const int run)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
block_clp (const System sys, const int run)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
secret_clp (const System sys, const Term t)
|
||||||
|
{
|
||||||
|
Constraintlist oldcl, newcl;
|
||||||
|
Constraint co;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
/* save old state */
|
||||||
|
oldcl = sys->constraints;
|
||||||
|
newcl = constraintlistShallow (oldcl);
|
||||||
|
|
||||||
|
/* we know this is a read */
|
||||||
|
co = makeConstraint (t, sys->know);
|
||||||
|
newcl = constraintlistAdd (newcl, co);
|
||||||
|
sys->constraints = newcl;
|
||||||
|
|
||||||
|
/* check solvability */
|
||||||
|
|
||||||
|
struct solvepass sp;
|
||||||
|
sp.solution = NULL;
|
||||||
|
sp.sys = sys;
|
||||||
|
flag = !solve (sp, sys->constraints);
|
||||||
|
|
||||||
|
/* restore memory allocation */
|
||||||
|
constraintDestroy (co);
|
||||||
|
constraintlistDelete (newcl);
|
||||||
|
sys->constraints = oldcl;
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sendAdd_clp (const System sys, const int run, const Termlist tl)
|
||||||
|
{
|
||||||
|
Term t;
|
||||||
|
Termlist tl2;
|
||||||
|
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
/* TODO because the constraints might have changed, we can try to solve them again... */
|
||||||
|
explorify (sys, run);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t = deVar (tl->term);
|
||||||
|
if (realTermLeaf (t))
|
||||||
|
{
|
||||||
|
/* leaf: simply add it */
|
||||||
|
knowledgeAddTerm (sys->know, t);
|
||||||
|
sendAdd_clp (sys, run, tl->next);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* node */
|
||||||
|
if (realTermTuple (t))
|
||||||
|
{
|
||||||
|
/* tuple */
|
||||||
|
tl2 = termlistShallow (tl->next);
|
||||||
|
tl2 = termlistAdd (tl2, t->op1);
|
||||||
|
tl2 = termlistAdd (tl2, t->op2);
|
||||||
|
sendAdd_clp (sys, run, tl2);
|
||||||
|
termlistDelete (tl2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* encrypt */
|
||||||
|
Term invkey;
|
||||||
|
|
||||||
|
invkey = inverseKey (sys->know->inverses, t->key);
|
||||||
|
if (!hasTermVariable (invkey))
|
||||||
|
{
|
||||||
|
/* simple case: no variable inside */
|
||||||
|
knowledgeAddTerm (sys->know, t);
|
||||||
|
tl2 = termlistShallow (tl->next);
|
||||||
|
if (inKnowledge (sys->know, invkey) && hasTermVariable (t->op))
|
||||||
|
tl2 = termlistAdd (tl2, t->op);
|
||||||
|
sendAdd_clp (sys, run, tl2);
|
||||||
|
termlistDelete (tl2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* difficult case: variable in inverse
|
||||||
|
* key. We have to branch. */
|
||||||
|
|
||||||
|
/* branch 1 : invkey not in knowledge */
|
||||||
|
/* TODO this yields a negative constraint, which we omit for the time being */
|
||||||
|
Knowledge oldknow = knowledgeDuplicate (sys->know);
|
||||||
|
|
||||||
|
knowledgeAddTerm (sys->know, t);
|
||||||
|
sendAdd_clp (sys, run, tl->next);
|
||||||
|
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
|
||||||
|
/* branch 2 : invkey in knowledge */
|
||||||
|
oldknow = knowledgeDuplicate (sys->know);
|
||||||
|
Constraintlist clold = sys->constraints;
|
||||||
|
Constraintlist clbuf = constraintlistShallow (clold);
|
||||||
|
tl2 = termlistShallow (tl->next);
|
||||||
|
|
||||||
|
Constraint co = makeConstraint (invkey, sys->know);
|
||||||
|
sys->constraints = constraintlistAdd (clbuf, co);
|
||||||
|
/* we _could_ explore first if this is solveable */
|
||||||
|
knowledgeAddTerm (sys->know, t);
|
||||||
|
tl2 = termlistAdd (tl2, t->op);
|
||||||
|
sendAdd_clp (sys, run, tl2);
|
||||||
|
|
||||||
|
termlistDelete (tl2);
|
||||||
|
constraintDestroy (co);
|
||||||
|
constraintlistDelete (clbuf);
|
||||||
|
sys->constraints = clold;
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
send_clp (const System sys, const int run)
|
||||||
|
{
|
||||||
|
Roledef rd = runPointerGet (sys, run);
|
||||||
|
/* execute send, push knowledge? */
|
||||||
|
if (inKnowledge (sys->know, rd->message))
|
||||||
|
{
|
||||||
|
/* no new knowledge, so this remains */
|
||||||
|
explorify (sys, run);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* new knowledge, must store old state */
|
||||||
|
Knowledge oldknow;
|
||||||
|
oldknow = sys->know;
|
||||||
|
sys->know = knowledgeDuplicate (sys->know);
|
||||||
|
|
||||||
|
Termlist tl = termlistAdd (NULL, rd->message);
|
||||||
|
sendAdd_clp (sys, run, tl);
|
||||||
|
termlistDelete (tl);
|
||||||
|
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isPossible_clp (const System sys, const int run, int
|
||||||
|
(*proceed) (System, int), const Term t, const Knowledge k)
|
||||||
|
{
|
||||||
|
Constraintlist oldcl, newcl;
|
||||||
|
Constraint co;
|
||||||
|
Roledef runPoint;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
/* save old state */
|
||||||
|
oldcl = sys->constraints;
|
||||||
|
newcl = constraintlistShallow (oldcl);
|
||||||
|
|
||||||
|
/* creat new state */
|
||||||
|
runPoint = runPointerGet (sys, run);
|
||||||
|
|
||||||
|
/* add the new constraint */
|
||||||
|
co = makeConstraint (t, k);
|
||||||
|
newcl = constraintlistAdd (newcl, co);
|
||||||
|
sys->constraints = newcl;
|
||||||
|
|
||||||
|
/* check solvability */
|
||||||
|
int solution (const struct solvepass sp, const Constraintlist cl)
|
||||||
|
{
|
||||||
|
Knowledge oldknow = NULL;
|
||||||
|
Constraintlist oldcl = sys->constraints;
|
||||||
|
int flag = 0;
|
||||||
|
int copied = 0;
|
||||||
|
|
||||||
|
sys->constraints = cl;
|
||||||
|
if (knowledgeSubstNeeded (sys->know))
|
||||||
|
{
|
||||||
|
copied = 1;
|
||||||
|
oldknow = sys->know;
|
||||||
|
sys->know = knowledgeSubstDo (sys->know);
|
||||||
|
}
|
||||||
|
flag = sp.proceed (sys, run);
|
||||||
|
if (copied)
|
||||||
|
{
|
||||||
|
knowledgeDelete (sys->know);
|
||||||
|
sys->know = oldknow;
|
||||||
|
knowledgeSubstUndo (sys->know);
|
||||||
|
}
|
||||||
|
sys->constraints = oldcl;
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct solvepass sp;
|
||||||
|
sp.solution = solution;
|
||||||
|
sp.sys = sys;
|
||||||
|
sp.run = run;
|
||||||
|
sp.proceed = proceed;
|
||||||
|
flag = solve (sp, sys->constraints);
|
||||||
|
|
||||||
|
/* restore memory allocation */
|
||||||
|
constraintDestroy (co);
|
||||||
|
constraintlistDelete (newcl);
|
||||||
|
sys->constraints = oldcl;
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
13
src/match_clp.h
Normal file
13
src/match_clp.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef MATCHCLP
|
||||||
|
#define MATCHCLP
|
||||||
|
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
int matchRead_clp (const System sys, const int run,
|
||||||
|
int (*proceed) (System, int));
|
||||||
|
int enabled_clp (const System sys, const int run);
|
||||||
|
int block_clp (const System sys, const int run);
|
||||||
|
int secret_clp (const System sys, const Term t);
|
||||||
|
int send_clp (const System sys, const int run);
|
||||||
|
|
||||||
|
#endif
|
48
src/memory.c
Normal file
48
src/memory.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* my own memory functions (not yet) */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <mcheck.h>
|
||||||
|
#include "memory.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* for displaying the sizes */
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
memInit ()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (DEBUGL (5))
|
||||||
|
{
|
||||||
|
void sp (char *txt, int size)
|
||||||
|
{
|
||||||
|
printf ("Size of %s : %i\n", txt, size);
|
||||||
|
}
|
||||||
|
printf ("Data structure size.\n\n");
|
||||||
|
sp ("pointer", sizeof (Term));
|
||||||
|
sp ("term node", sizeof (struct term));
|
||||||
|
sp ("termlist node", sizeof (struct termlist));
|
||||||
|
sp ("knowledge node", sizeof (struct knowledge));
|
||||||
|
sp ("substituition node", sizeof (struct substitution));
|
||||||
|
sp ("substlist node", sizeof (struct substitutionlist));
|
||||||
|
sp ("roledef node", sizeof (struct roledef));
|
||||||
|
sp ("system node", sizeof (struct system));
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
mtrace ();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memDone (int sw)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
14
src/memory.h
Normal file
14
src/memory.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef MEMORY
|
||||||
|
#define MEMORY
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
void memInit ();
|
||||||
|
void memDone ();
|
||||||
|
#define memAlloc(t) malloc(t)
|
||||||
|
#define memFree(p,t) free(p)
|
||||||
|
#define memRealloc(p,t) realloc(p,t);
|
||||||
|
|
||||||
|
#endif
|
151
src/mgu.c
Normal file
151
src/mgu.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
#include "mgu.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Most General Unifier
|
||||||
|
|
||||||
|
Unification etc.
|
||||||
|
|
||||||
|
New version yields a termlist with substituted variables, which can later be reset to NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistSubstReset (Termlist tl)
|
||||||
|
{
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
tl->term->subst = NULL;
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termMguTerm (Term t1, Term t2)
|
||||||
|
{
|
||||||
|
/* added for speed */
|
||||||
|
t1 = deVar (t1);
|
||||||
|
t2 = deVar (t2);
|
||||||
|
if (t1 == t2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void showSubst (Term t)
|
||||||
|
{
|
||||||
|
if (!DEBUGL (5))
|
||||||
|
return;
|
||||||
|
|
||||||
|
indent ();
|
||||||
|
printf ("Substituting ");
|
||||||
|
termPrint (t);
|
||||||
|
printf (", typed ");
|
||||||
|
termlistPrint (t->stype);
|
||||||
|
printf ("->");
|
||||||
|
termlistPrint (t->subst->stype);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(hasTermVariable (t1) || hasTermVariable (t2)))
|
||||||
|
{
|
||||||
|
if (isTermEqual (t1, t2))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* symmetrical tests for single variable */
|
||||||
|
if (isTermVariable (t1))
|
||||||
|
{
|
||||||
|
if (termOccurs (t2, t1))
|
||||||
|
return MGUFAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t1->subst = t2;
|
||||||
|
#ifdef DEBUG
|
||||||
|
showSubst (t1);
|
||||||
|
#endif
|
||||||
|
return termlistAdd (NULL, t1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isTermVariable (t2))
|
||||||
|
{
|
||||||
|
if (termOccurs (t1, t2))
|
||||||
|
return MGUFAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t2->subst = t1;
|
||||||
|
#ifdef DEBUG
|
||||||
|
showSubst (t2);
|
||||||
|
#endif
|
||||||
|
return termlistAdd (NULL, t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* left & right are compounds with variables */
|
||||||
|
if (t1->type != t2->type)
|
||||||
|
return MGUFAIL;
|
||||||
|
|
||||||
|
/* identical compounds */
|
||||||
|
/* encryption first */
|
||||||
|
if (isTermEncrypt (t1))
|
||||||
|
{
|
||||||
|
Termlist tl1, tl2;
|
||||||
|
|
||||||
|
tl1 = termMguTerm (t1->key, t2->key);
|
||||||
|
if (tl1 == MGUFAIL)
|
||||||
|
{
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tl2 = termMguTerm (t1->op, t2->op);
|
||||||
|
if (tl2 == MGUFAIL)
|
||||||
|
{
|
||||||
|
termlistSubstReset (tl1);
|
||||||
|
termlistDelete (tl1);
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return termlistConcat (tl1, tl2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tupling second
|
||||||
|
non-associative version ! TODO other version */
|
||||||
|
if (isTermTuple (t1))
|
||||||
|
{
|
||||||
|
Termlist tl1, tl2;
|
||||||
|
|
||||||
|
tl1 = termMguTerm (t1->op1, t2->op1);
|
||||||
|
if (tl1 == MGUFAIL)
|
||||||
|
{
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tl2 = termMguTerm (t1->op2, t2->op2);
|
||||||
|
if (tl2 == MGUFAIL)
|
||||||
|
{
|
||||||
|
termlistSubstReset (tl1);
|
||||||
|
termlistDelete (tl1);
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return termlistConcat (tl1, tl2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MGUFAIL;
|
||||||
|
}
|
12
src/mgu.h
Normal file
12
src/mgu.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef MGU
|
||||||
|
#define MGU
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
|
||||||
|
#define MGUFAIL (Termlist) -1
|
||||||
|
|
||||||
|
Termlist termMguTerm (Term t1, Term t2);
|
||||||
|
|
||||||
|
#endif
|
1171
src/modelchecker.c
Normal file
1171
src/modelchecker.c
Normal file
File diff suppressed because it is too large
Load Diff
6
src/modelchecker.h
Normal file
6
src/modelchecker.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
int traverse (const System oldsys);
|
||||||
|
int explorify (const System sys, const int run);
|
||||||
|
int executeStep (const System sys, const int run);
|
||||||
|
int propertyCheck (const System sys);
|
||||||
|
Termlist claimViolationDetails (const System sys, const int run, const Roledef
|
||||||
|
rd, const Knowledge know);
|
76
src/notes.txt
Normal file
76
src/notes.txt
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
- best heuristic currently for -t8: ignore sendsfirst, just look at the
|
||||||
|
previous event and continue at that run.
|
||||||
|
- termPrint must currently be encapsulated in a math environment to work in
|
||||||
|
latex output, I wil change this later to some ensure mathmode construct,
|
||||||
|
probably with something like latexTermPrint.
|
||||||
|
- Repository to apache2 webdav.
|
||||||
|
- The trace incremental search should start at something like 'distance of
|
||||||
|
first claim + SOMECONST * runs'. SOMECONST relates to the partial-order
|
||||||
|
induced trace prolonings.
|
||||||
|
- For now, CLP is non-working and not checked. Reconsider this later.
|
||||||
|
- Because the properties checked are related to the partial order reductions,
|
||||||
|
it makes sense to check 'all secrecy claims' or 'all synchronisation claims'
|
||||||
|
at once.
|
||||||
|
- Once an attack is generated, we know the actual scenario and the trace
|
||||||
|
length. We might re-use this information to generate the shortest attack
|
||||||
|
using no partial order reduction. Note that choosing a wise method of
|
||||||
|
finding that is a mathematical issue: searching -t1 is exponential, so how
|
||||||
|
do we step trough these traces in order to find the shortest trace in the
|
||||||
|
quickest way? This can be determined under some (statistical) assumptions.
|
||||||
|
- The incremental check can be done much easier, by just retrying the main
|
||||||
|
loop explore with different parameters. It keeps everything nicely intact.
|
||||||
|
We must check for fails however, and how pruning is affected.
|
||||||
|
- Incremental check can at least be done in two ways: either by limiting the
|
||||||
|
number of runs (big axe method) or by limiting the trace length (nice).
|
||||||
|
There is a drawback to trace length only: the superfluous sends of the
|
||||||
|
algorithm in a scenario with many runs might interfere with the usefulness
|
||||||
|
of short traces. Maybe some heuristic that reduces the runs automatically is
|
||||||
|
required. (e.g. 'number of runs is at most MaxTraceLength/MaxRoleLength' or
|
||||||
|
something like that). Do analysis.
|
||||||
|
- If synch checking is expensive, introduce a limit (for -p0 stuff).
|
||||||
|
Basically, after the limit (if -p0 is set), we stop checking synch claims.
|
||||||
|
This then is default behaviour, to be overridden or changed by a switch.
|
||||||
|
- clp does not yet consider the matching for variables that have not been
|
||||||
|
instantiated. This *might* lead to some improvement, e.g. when there is only
|
||||||
|
one candidate for the variable. In general, I don't think it will help.
|
||||||
|
- match_clp.c 1.25 introduced the variable_in_invkey brancher, which hasn't
|
||||||
|
been thoroughly tested yet. Please do test.
|
||||||
|
- Brutus is slower than -t4. CLP is much, much faster however than both.
|
||||||
|
- It is very important to have variables in the run agent list, because it
|
||||||
|
dramatically decreases the complexity of the system, as opposed to just
|
||||||
|
creating runs for all possibilities. However, this explicitly introduces the
|
||||||
|
clp problem of var encryptions (see above).
|
||||||
|
- Given originator assumptions and such, we might want to implement the
|
||||||
|
compiler, that for non-typed matching, it will ignore all type definitions
|
||||||
|
in the code (as in, putting them in stype, but still considering Function).
|
||||||
|
Then, for 'any agent' we can use stype silently. The modelchecker should
|
||||||
|
then always consider the types with -m0 and -m1.
|
||||||
|
- In a paper concerning the CASRUL compiler, they mention associativity for
|
||||||
|
the equality relations. Note that CASRUL restricts the intruder actions,
|
||||||
|
and sometimes uses approximations.
|
||||||
|
- MS and CE never mention associativity as a restriction.
|
||||||
|
- For now, clp stuff will use pairing and simple mgu. Maybe a -m3 switch will
|
||||||
|
add the associative variant later.
|
||||||
|
- MALLOC_TRACE is the environment variable that triggers mtrace() output.
|
||||||
|
- Several memory leak detectors are still in place, they can all be located by
|
||||||
|
searching for "lead" or "diff" and destroying the code.
|
||||||
|
- knowledgeAddTerm might be improved by scanning through key list only with
|
||||||
|
things that are newly added.
|
||||||
|
- Associativity and unification don't play together well; consider other
|
||||||
|
algorithms. Maybe a simple explore (x,y),z and explore x,(y,z) will do, e.g.
|
||||||
|
take any split point for both sequences.
|
||||||
|
- POR (-t3) is actually worse than -t2: sends first. After some pondering I
|
||||||
|
now know why. It's because simultaneous reads yield traces in which there
|
||||||
|
are attacks that are also in the ones where we have R0S0S0;R1 (i.e. is thus
|
||||||
|
equivalent with R0;R1;S0S0)
|
||||||
|
- Knowledge is monotonous. So, if we say 'R#0' cannot be triggered by some
|
||||||
|
knowledge, we can just use a pointer for it. If we do want to trigger it, we
|
||||||
|
need to compare two knowledge pointers. As they don't have a unique
|
||||||
|
representation, it is more difficult. For now, I will just forbid specific
|
||||||
|
branches of the read when a message is in some previous knowledge, which is
|
||||||
|
more precise.
|
||||||
|
- Comparisons with Casper are in order.
|
||||||
|
- It is a good idea to have any number of input files, and parse them all, to
|
||||||
|
combine scenarios. A command should be "require <file>", because that would
|
||||||
|
enable scenarios to load the required role definitions. It's require instead
|
||||||
|
of include, because of possible multiple occurrences.
|
443
src/output.c
Normal file
443
src/output.c
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
/*
|
||||||
|
* output.c
|
||||||
|
*
|
||||||
|
* Outputs an attack.
|
||||||
|
* Currently, every attack is printed.
|
||||||
|
* TODO move attacks to a buffer, and print _only_ the shortest one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "runs.h"
|
||||||
|
#include "latex.h"
|
||||||
|
|
||||||
|
|
||||||
|
void linePrint(int i)
|
||||||
|
{
|
||||||
|
indent();
|
||||||
|
while (i > 0) {
|
||||||
|
printf("--------");
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int correspondingSend(System sys, int rd)
|
||||||
|
{
|
||||||
|
|
||||||
|
int labelMatch = 0;
|
||||||
|
int toMatch = 0;
|
||||||
|
int fromMatch = 0;
|
||||||
|
int tofromMatch = 0;
|
||||||
|
int messageMatch = 0;
|
||||||
|
int nMatches = 0;
|
||||||
|
int maxNMatches = 0;
|
||||||
|
|
||||||
|
int readEvent = rd;
|
||||||
|
int sendEvent = -1;
|
||||||
|
int bestSendEvent = -1;
|
||||||
|
|
||||||
|
for (sendEvent = readEvent; sendEvent >= 0; sendEvent--) {
|
||||||
|
if (sys->traceEvent[sendEvent]->type == SEND) {
|
||||||
|
/* do all the different kind of matchings first */
|
||||||
|
|
||||||
|
labelMatch =
|
||||||
|
isTermEqualFn(sys->traceEvent[sendEvent]->label,
|
||||||
|
sys->traceEvent[readEvent]->label);
|
||||||
|
toMatch =
|
||||||
|
isTermEqualFn(sys->traceEvent[sendEvent]->to,
|
||||||
|
sys->traceEvent[readEvent]->to);
|
||||||
|
fromMatch =
|
||||||
|
isTermEqualFn(sys->traceEvent[sendEvent]->from,
|
||||||
|
sys->traceEvent[readEvent]->from);
|
||||||
|
tofromMatch = toMatch || fromMatch;
|
||||||
|
messageMatch =
|
||||||
|
isTermEqualFn(sys->traceEvent[sendEvent]->message,
|
||||||
|
sys->traceEvent[readEvent]->message);
|
||||||
|
|
||||||
|
/* calculate the score */
|
||||||
|
|
||||||
|
nMatches = labelMatch + tofromMatch + messageMatch;
|
||||||
|
|
||||||
|
if (nMatches == 3) {
|
||||||
|
/* bingo! success on all matches */
|
||||||
|
|
||||||
|
//printf("Found perfect match: %d\n", s);
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nMatches > maxNMatches) {
|
||||||
|
/* if we found a better candidate than we already had, we'll update */
|
||||||
|
|
||||||
|
//printf("Comparing SEND #%d: ",s);
|
||||||
|
//if (labelMatch) printf("label ");
|
||||||
|
//if (toMatch) printf("to ");
|
||||||
|
//if (fromMatch) printf("from ");
|
||||||
|
//if (messageMatch) printf("message ");
|
||||||
|
//printf("\n");
|
||||||
|
|
||||||
|
/* however, we first want to be sure that at least some matches are successful */
|
||||||
|
|
||||||
|
if (labelMatch && messageMatch) {
|
||||||
|
/* strongest restriction: message and label should match */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
|
||||||
|
} else if (messageMatch) {
|
||||||
|
/* if label AND message don't match: */
|
||||||
|
/* at least message should match */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
} else if (labelMatch) {
|
||||||
|
/* if message doesn't match */
|
||||||
|
/* the label should matches */
|
||||||
|
|
||||||
|
maxNMatches = nMatches;
|
||||||
|
bestSendEvent = sendEvent;
|
||||||
|
}
|
||||||
|
//printf("Best match: %d maxNMatches: %d\n", s, maxNMatches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//bestSendEvent = NULL;
|
||||||
|
if (bestSendEvent == -1) {
|
||||||
|
/*Termlist tl;
|
||||||
|
Term t;
|
||||||
|
|
||||||
|
//newtl = knowledgeNew(sys->traceKnow[i],sys->traceKnow[i+1]);
|
||||||
|
|
||||||
|
for (tl = sys->traceKnow[rd]->basic; tl != NULL; tl = tl->next)
|
||||||
|
{
|
||||||
|
t = tl->term;
|
||||||
|
termPrint(t);
|
||||||
|
printf(" - ");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (tl = sys->traceKnow[rd]->encrypt; tl != NULL; tl = tl->next)
|
||||||
|
{
|
||||||
|
t = tl->term;
|
||||||
|
termPrint(t);
|
||||||
|
printf(" - ");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (tl = sys->traceKnow[rd]->inverses; tl != NULL; tl = tl->next)
|
||||||
|
{
|
||||||
|
t = tl->term;
|
||||||
|
termPrint(t);
|
||||||
|
printf(" - ");
|
||||||
|
}
|
||||||
|
printf("\n"); */
|
||||||
|
|
||||||
|
int u;
|
||||||
|
|
||||||
|
for (u = 0; u < rd; u++) {
|
||||||
|
if (sys->traceEvent[u]->type == SEND) {
|
||||||
|
|
||||||
|
|
||||||
|
//termPrint(readEvent->message);
|
||||||
|
//printf("\n");
|
||||||
|
knowledgePrint(sys->traceKnow[u]);
|
||||||
|
//printf("Is received message in knowledge after SEND %d? %d\n", u, inKnowledge(sys->traceKnow[u+1],readEvent->message));
|
||||||
|
if (inKnowledge
|
||||||
|
(sys->traceKnow[u + 1],
|
||||||
|
sys->traceEvent[readEvent]->message)) {
|
||||||
|
bestSendEvent = u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestSendEvent == -1) {
|
||||||
|
printf("!! Could not find a matching SEND\n");
|
||||||
|
} else {
|
||||||
|
//latexMessagePrint(sys, bestSendEvent, readEvent);
|
||||||
|
//printf("Latex: ");
|
||||||
|
//termPrint(bestSendEvent->from);
|
||||||
|
//printf(" -> ");
|
||||||
|
if (!isTermEqualFn
|
||||||
|
(sys->traceEvent[bestSendEvent]->to,
|
||||||
|
sys->traceEvent[readEvent]->to)) {
|
||||||
|
//termPrint(bestSendEvent->to);
|
||||||
|
//printf(" -> ");
|
||||||
|
}
|
||||||
|
if (!isTermEqualFn
|
||||||
|
(sys->traceEvent[bestSendEvent]->from,
|
||||||
|
sys->traceEvent[readEvent]->from)) {
|
||||||
|
//termPrint(readEvent->from);
|
||||||
|
//printf(" -> ");
|
||||||
|
}
|
||||||
|
//termPrint(readEvent->to);
|
||||||
|
//printf("\n");
|
||||||
|
}
|
||||||
|
return bestSendEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tracePrint(System sys)
|
||||||
|
{
|
||||||
|
if (sys->latex) {
|
||||||
|
//latexTracePrint(sys);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
int lastrid;
|
||||||
|
int width;
|
||||||
|
Termlist newtl;
|
||||||
|
|
||||||
|
/* fix the 'next' knowledge, this is required because sometimes
|
||||||
|
* when calling this function, the next knowledge is not stored
|
||||||
|
* yet, but required for the general form of the output . */
|
||||||
|
|
||||||
|
sys->traceKnow[sys->step + 1] = sys->know;
|
||||||
|
|
||||||
|
|
||||||
|
/* how wide is the trace? */
|
||||||
|
width = 0;
|
||||||
|
for (i = 0; i <= sys->step; i++) {
|
||||||
|
if (sys->traceRun[i] >= width)
|
||||||
|
width = sys->traceRun[i] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
indent();
|
||||||
|
printf("Dumping trace:\n");
|
||||||
|
linePrint(width);
|
||||||
|
|
||||||
|
/* first some parameter issues */
|
||||||
|
|
||||||
|
knowledgePrint(sys->traceKnow[0]);
|
||||||
|
/* also print inverses */
|
||||||
|
indent();
|
||||||
|
printf("Inverses: ");
|
||||||
|
knowledgeInversesPrint(sys->traceKnow[0]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* Trace columns header. First the run identifier and role. On the
|
||||||
|
* second line we have the perceived agents for each partner role.
|
||||||
|
* These are printed in the same order as the role specification in the
|
||||||
|
* protocol. */
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
indent();
|
||||||
|
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
termPrint(sys->runs[i].role->nameterm);
|
||||||
|
printf("#%i\t", i);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
termPrint(agentOfRun(sys, i));
|
||||||
|
printf("\t");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
agentsOfRunPrint(sys, i);
|
||||||
|
printf("\t");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* now we print the actual trace */
|
||||||
|
|
||||||
|
void sticks(int i) {
|
||||||
|
while (i > 0) {
|
||||||
|
printf("|\t");
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sticksLine(void) {
|
||||||
|
sticks(width);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
lastrid = -1;
|
||||||
|
for (i = 0; i <= sys->step; i++) {
|
||||||
|
/* yields extra newlines between switching of runs */
|
||||||
|
|
||||||
|
j = sys->traceRun[i];
|
||||||
|
if (j != lastrid) {
|
||||||
|
sticksLine();
|
||||||
|
lastrid = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print the actual event */
|
||||||
|
|
||||||
|
indent();
|
||||||
|
sticks(j);
|
||||||
|
roledefPrint(sys->traceEvent[i]);
|
||||||
|
|
||||||
|
//if (sys->traceEvent[i]->type == READ && !sys->traceEvent[i]->internal)
|
||||||
|
//{
|
||||||
|
/* calls routine to find the best SEND-candidate */
|
||||||
|
/* the result is not yet being used */
|
||||||
|
|
||||||
|
// printf("\n");
|
||||||
|
// correspondingSend(sys, i);
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* have we learnt anything new? */
|
||||||
|
newtl = knowledgeNew(sys->traceKnow[i], sys->traceKnow[i + 1]);
|
||||||
|
if (newtl != NULL) {
|
||||||
|
printf("\n");
|
||||||
|
sticksLine();
|
||||||
|
sticks(width);
|
||||||
|
printf("/* Intruder learns ");
|
||||||
|
termlistPrint(newtl);
|
||||||
|
termlistDelete(newtl);
|
||||||
|
printf(" */");
|
||||||
|
lastrid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* new line */
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sys->clp) {
|
||||||
|
case 1:
|
||||||
|
indent();
|
||||||
|
printf("---[ constraints ]-----\n");
|
||||||
|
constraintlistPrint(sys->constraints);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
linePrint(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void attackDisplayAscii(System sys)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int length;
|
||||||
|
int lastrid;
|
||||||
|
int width;
|
||||||
|
Termlist newtl;
|
||||||
|
struct tracebuf *tb;
|
||||||
|
|
||||||
|
/* attack trace buffer */
|
||||||
|
tb = sys->attack;
|
||||||
|
length = sys->attack->length;
|
||||||
|
|
||||||
|
/* set variables */
|
||||||
|
varbufSet (sys, tb->variables);
|
||||||
|
|
||||||
|
/* how wide is the trace? */
|
||||||
|
width = 0;
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
if (tb->run[i] >= width)
|
||||||
|
width = tb->run[i] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
indent();
|
||||||
|
printf("Dumping trace:\n");
|
||||||
|
linePrint(width);
|
||||||
|
|
||||||
|
/* first some parameter issues */
|
||||||
|
|
||||||
|
knowledgePrint(tb->know[0]);
|
||||||
|
printf ("Variables: ");
|
||||||
|
termlistPrint (sys->variables);
|
||||||
|
printf ("\n");
|
||||||
|
|
||||||
|
/* Trace columns header. First the run identifier and role. On the
|
||||||
|
* second line we have the perceived agents for each partner role.
|
||||||
|
* These are printed in the same order as the role specification in the
|
||||||
|
* protocol. */
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
indent();
|
||||||
|
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
termPrint(sys->runs[i].role->nameterm);
|
||||||
|
printf("#%i\t", i);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
termPrint(agentOfRun(sys, i));
|
||||||
|
printf("\t");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
agentsOfRunPrint(sys, i);
|
||||||
|
printf("\t");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* now we print the actual trace */
|
||||||
|
|
||||||
|
void sticks(int i) {
|
||||||
|
while (i > 0) {
|
||||||
|
printf("|\t");
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sticksLine(void) {
|
||||||
|
sticks(width);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
lastrid = -1;
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
/* yields extra newlines between switching of runs */
|
||||||
|
|
||||||
|
j = tb->run[i];
|
||||||
|
if (j != lastrid) {
|
||||||
|
sticksLine();
|
||||||
|
lastrid = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print the actual event */
|
||||||
|
|
||||||
|
indent();
|
||||||
|
sticks(j);
|
||||||
|
roledefPrint(tb->event[i]);
|
||||||
|
|
||||||
|
//if (sys->traceEvent[i]->type == READ && !sys->traceEvent[i]->internal)
|
||||||
|
//{
|
||||||
|
/* calls routine to find the best SEND-candidate */
|
||||||
|
/* the result is not yet being used */
|
||||||
|
|
||||||
|
// printf("\n");
|
||||||
|
// correspondingSend(sys, i);
|
||||||
|
//}
|
||||||
|
|
||||||
|
/* have we learnt anything new? */
|
||||||
|
newtl = knowledgeNew(tb->know[i], tb->know[i + 1]);
|
||||||
|
if (newtl != NULL) {
|
||||||
|
printf("\n");
|
||||||
|
sticksLine();
|
||||||
|
sticks(width);
|
||||||
|
printf("/* Intruder learns ");
|
||||||
|
termlistPrint(newtl);
|
||||||
|
termlistDelete(newtl);
|
||||||
|
printf(" */");
|
||||||
|
lastrid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* new line */
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
linePrint(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void attackDisplay(System sys)
|
||||||
|
{
|
||||||
|
if (sys->latex) {
|
||||||
|
attackDisplayLatex(sys);
|
||||||
|
} else {
|
||||||
|
attackDisplayAscii(sys);
|
||||||
|
}
|
||||||
|
}
|
9
src/output.h
Normal file
9
src/output.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef OUTPUT
|
||||||
|
#define OUTPUT
|
||||||
|
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
void tracePrint(System sys);
|
||||||
|
void attackDisplay(System sys);
|
||||||
|
|
||||||
|
#endif
|
281
src/parser.y
Normal file
281
src/parser.y
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
%{
|
||||||
|
#include "pheading.h"
|
||||||
|
#include "scanner.c"
|
||||||
|
#include "tac.h"
|
||||||
|
|
||||||
|
struct tacnode* spdltac;
|
||||||
|
|
||||||
|
int yyerror(char *s);
|
||||||
|
int yylex(void);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union{
|
||||||
|
char* str;
|
||||||
|
struct tacnode* tac;
|
||||||
|
Symbol symb;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token <symb> ID
|
||||||
|
%token PROTOCOL
|
||||||
|
%token ROLE
|
||||||
|
%token READT
|
||||||
|
%token SENDT
|
||||||
|
%token CLAIMT
|
||||||
|
%token VAR
|
||||||
|
%token CONST
|
||||||
|
%token RUN
|
||||||
|
%token SECRET
|
||||||
|
%token COMPROMISED
|
||||||
|
%token INVERSEKEYS
|
||||||
|
%token UNTRUSTED
|
||||||
|
%token USERTYPE
|
||||||
|
|
||||||
|
%type <tac> spdlcomplete
|
||||||
|
%type <tac> spdlrep
|
||||||
|
%type <tac> spdl
|
||||||
|
%type <tac> roles
|
||||||
|
%type <tac> role
|
||||||
|
%type <tac> roledef
|
||||||
|
%type <tac> event
|
||||||
|
%type <tac> declaration
|
||||||
|
%type <tac> secretpref
|
||||||
|
%type <tac> typeinfo1
|
||||||
|
%type <tac> typeinfoN
|
||||||
|
%type <tac> term
|
||||||
|
%type <tac> termlist
|
||||||
|
%type <tac> key
|
||||||
|
%type <tac> roleref
|
||||||
|
|
||||||
|
%type <symb> label
|
||||||
|
|
||||||
|
%start spdlcomplete
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
spdlcomplete : spdlrep
|
||||||
|
{ spdltac = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
spdlrep : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| spdl spdlrep
|
||||||
|
{ $$ = tacCat($1,$2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
spdl : UNTRUSTED termlist ';'
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_UNTRUSTED);
|
||||||
|
t->tac1 = $2;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| RUN roleref '(' termlist ')' ';'
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_RUN);
|
||||||
|
t->tac1 = $2;
|
||||||
|
t->tac2 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| PROTOCOL ID '(' termlist ')' '{' roles '}' optclosing
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_PROTOCOL);
|
||||||
|
t->sym1 = $2;
|
||||||
|
t->tac2 = $7;
|
||||||
|
t->tac3 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| USERTYPE termlist ';'
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_USERTYPE);
|
||||||
|
t->tac1 = $2;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| declaration
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
roles : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| role roles
|
||||||
|
{ $$ = tacCat($1,$2); }
|
||||||
|
| declaration roles
|
||||||
|
{ $$ = tacCat($1,$2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
role : ROLE ID '{' roledef '}' optclosing
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_ROLE);
|
||||||
|
t->sym1 = $2;
|
||||||
|
t->tac2 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
optclosing : /* empty */
|
||||||
|
{ }
|
||||||
|
| ';'
|
||||||
|
{ }
|
||||||
|
;
|
||||||
|
|
||||||
|
roledef : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| event roledef
|
||||||
|
{ $$ = tacCat($1,$2); }
|
||||||
|
| declaration roledef
|
||||||
|
{ $$ = tacCat($1,$2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
event : READT label '(' termlist ')' ';'
|
||||||
|
{ Tac t = tacCreate(TAC_READ);
|
||||||
|
t->sym1 = $2;
|
||||||
|
/* TODO test here: tac2 should have at least 3 elements */
|
||||||
|
t->tac2 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| SENDT label '(' termlist ')' ';'
|
||||||
|
{ Tac t = tacCreate(TAC_SEND);
|
||||||
|
t->sym1 = $2;
|
||||||
|
/* TODO test here: tac2 should have at least 3 elements */
|
||||||
|
t->tac2 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| CLAIMT label '(' termlist ')' ';'
|
||||||
|
/* TODO maybe claims should be in the syntax */
|
||||||
|
{ Tac t = tacCreate(TAC_CLAIM);
|
||||||
|
t->sym1 = $2;
|
||||||
|
t->tac2 = $4;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
roleref : ID '.' ID
|
||||||
|
{ Tac t = tacCreate(TAC_ROLEREF);
|
||||||
|
t->sym1 = $1;
|
||||||
|
t->sym2 = $3;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration : secretpref CONST termlist typeinfo1 ';'
|
||||||
|
{ Tac t = tacCreate(TAC_CONST);
|
||||||
|
t->tac1 = $3;
|
||||||
|
t->tac2 = $4;
|
||||||
|
t->tac3 = $1;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| secretpref VAR termlist typeinfoN ';'
|
||||||
|
{ Tac t = tacCreate(TAC_VAR);
|
||||||
|
t->tac1 = $3;
|
||||||
|
t->tac2 = $4;
|
||||||
|
t->tac3 = $1;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| SECRET termlist typeinfo1 ';'
|
||||||
|
{ Tac t = tacCreate(TAC_SECRET);
|
||||||
|
t->tac1 = $2;
|
||||||
|
t->tac2 = $3;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| INVERSEKEYS '(' term ',' term ')' ';'
|
||||||
|
{ Tac t = tacCreate(TAC_INVERSEKEYS);
|
||||||
|
t->tac1 = $3;
|
||||||
|
t->tac2 = $5;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| COMPROMISED termlist ';'
|
||||||
|
{ Tac t = tacCreate(TAC_COMPROMISED);
|
||||||
|
t->tac1= $2;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
secretpref : /* empty */
|
||||||
|
{
|
||||||
|
$$ = NULL;
|
||||||
|
}
|
||||||
|
| SECRET
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_SECRET);
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
typeinfo1 : /* empty */
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_UNDEF);
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| ':' ID
|
||||||
|
{ Tac t = tacCreate(TAC_STRING);
|
||||||
|
t->sym1 = $2;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
typeinfoN : /* empty */
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_UNDEF);
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| ':' termlist
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
label : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| '_' ID
|
||||||
|
{ $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
term : ID
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_STRING);
|
||||||
|
t->sym1 = $1;
|
||||||
|
$$ = t;
|
||||||
|
}
|
||||||
|
| ID '(' termlist ')'
|
||||||
|
{
|
||||||
|
Tac t = tacCreate(TAC_STRING);
|
||||||
|
t->sym1 = $1;
|
||||||
|
$$ = tacJoin(TAC_ENCRYPT,tacTuple($3),t,NULL);
|
||||||
|
}
|
||||||
|
| '{' termlist '}' key
|
||||||
|
{
|
||||||
|
$$ = tacJoin(TAC_ENCRYPT,tacTuple($2),$4,NULL);
|
||||||
|
}
|
||||||
|
| '(' termlist ')'
|
||||||
|
{
|
||||||
|
$$ = tacTuple($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
termlist : term
|
||||||
|
{ }
|
||||||
|
| term ',' termlist
|
||||||
|
{ $$ = tacCat($1,$3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
key : term
|
||||||
|
{ }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
// error handler routing
|
||||||
|
int yyerror(char *s)
|
||||||
|
{
|
||||||
|
extern int yylineno; // defined and maintained in lex.c
|
||||||
|
extern char *yytext; // defined and maintained in lex.c
|
||||||
|
|
||||||
|
printf("\nERROR %s at symbol %s on line %i.\n", s, yytext, yylineno);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
13
src/pheading.h
Normal file
13
src/pheading.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef PHEADING
|
||||||
|
#define PHEADING
|
||||||
|
|
||||||
|
#define YY_NO_UNPUT
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "tac.h"
|
||||||
|
#endif
|
33
src/releases.txt
Normal file
33
src/releases.txt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
? bonk
|
||||||
|
- New partial order reduction method.
|
||||||
|
Maybe CLP/t4
|
||||||
|
maybe MSC stuff
|
||||||
|
|
||||||
|
2004-02-19 billionaire
|
||||||
|
- replace substitutions with implicit substitutions.
|
||||||
|
- many syntax updates.
|
||||||
|
- many speed improvements.
|
||||||
|
|
||||||
|
2004-01-20 alpha1
|
||||||
|
teehee_valley with a couple of minor bugfixes.
|
||||||
|
- Shows error line correctly on parse.
|
||||||
|
- Allows for multi-line comments.
|
||||||
|
|
||||||
|
2004-01-20 teehee_valley
|
||||||
|
Nicely working role-based release, can test stdin scenario files.
|
||||||
|
- Preliminary untrusted support.
|
||||||
|
- Public, inversekeys are working.
|
||||||
|
- No tickets yet.
|
||||||
|
|
||||||
|
2004-01-19 amoxicillin
|
||||||
|
Preliminary compiler test release.
|
||||||
|
- Compiler works in ptest, now we can integrate it into the main
|
||||||
|
part, and throw out the scenarios.
|
||||||
|
|
||||||
|
2003 dead_ringers
|
||||||
|
A first working release.
|
||||||
|
- -t0 through -t2 implemented.
|
||||||
|
- Typed matching matches all basic terms.
|
||||||
|
- CLP matching works (-m2), but is not compatible with -t2.
|
||||||
|
- Hard coded protocols, inclusion through Makefile.
|
||||||
|
|
75
src/report.c
Normal file
75
src/report.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "output.h"
|
||||||
|
|
||||||
|
extern int globalLatex;
|
||||||
|
|
||||||
|
/* reportQuit is called after each violation, because it might need to abort the process */
|
||||||
|
void
|
||||||
|
reportQuit (System sys)
|
||||||
|
{
|
||||||
|
/* determine quit or not */
|
||||||
|
if (sys->prune >= 3)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Quitting after %li claims, at the first violated claim.\n",
|
||||||
|
sys->claims);
|
||||||
|
sys->maxtracelength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reportStart (System sys)
|
||||||
|
{
|
||||||
|
if (!sys->latex)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("<REPORT>\n");
|
||||||
|
indent ();
|
||||||
|
}
|
||||||
|
statesPrint (sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reportMid (System sys)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Trace length %i.\n", 1 + sys->step);
|
||||||
|
if (globalLatex)
|
||||||
|
printf("\n");
|
||||||
|
tracePrint (sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
reportEnd (System sys)
|
||||||
|
{
|
||||||
|
if (!sys->latex)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("<REPORT>\n");
|
||||||
|
}
|
||||||
|
reportQuit (sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reportSecrecy (System sys, Term t)
|
||||||
|
{
|
||||||
|
if (!sys->report)
|
||||||
|
{
|
||||||
|
reportQuit (sys);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reportStart (sys);
|
||||||
|
indent ();
|
||||||
|
printf ("Secrecy violation of $");
|
||||||
|
termPrint (t);
|
||||||
|
printf ("$\n");
|
||||||
|
if (globalLatex)
|
||||||
|
printf("\n");
|
||||||
|
reportMid (sys);
|
||||||
|
reportEnd (sys);
|
||||||
|
}
|
6
src/report.h
Normal file
6
src/report.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef REPORT
|
||||||
|
#define REPORT
|
||||||
|
|
||||||
|
void reportSecrecy (System sys, Term t);
|
||||||
|
|
||||||
|
#endif
|
844
src/runs.c
Normal file
844
src/runs.c
Normal file
@ -0,0 +1,844 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "runs.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "constraints.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "tracebuf.h"
|
||||||
|
|
||||||
|
/* from compiler.o */
|
||||||
|
extern Term TERM_Type;
|
||||||
|
|
||||||
|
/* for e.g. termprinting */
|
||||||
|
int globalLatex;
|
||||||
|
|
||||||
|
static int indentState = 0;
|
||||||
|
static int indentDepth = 0;
|
||||||
|
|
||||||
|
Run
|
||||||
|
makeRun ()
|
||||||
|
{
|
||||||
|
return (Run) memAlloc (sizeof (struct run));
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
makeRoledef ()
|
||||||
|
{
|
||||||
|
return (Roledef) memAlloc (sizeof (struct roledef));
|
||||||
|
}
|
||||||
|
|
||||||
|
System
|
||||||
|
systemInit ()
|
||||||
|
{
|
||||||
|
System sys = (System) memAlloc (sizeof (struct system));
|
||||||
|
|
||||||
|
/* initially, no trace ofcourse */
|
||||||
|
sys->step = 0;
|
||||||
|
sys->shortestattack = INT_MAX;
|
||||||
|
sys->attack = tracebufInit();
|
||||||
|
|
||||||
|
/* switches */
|
||||||
|
sys->porparam = 0; // multi-purpose parameter
|
||||||
|
sys->latex = 0; // latex output?
|
||||||
|
|
||||||
|
/* set illegal traversal by default, to make sure it is set
|
||||||
|
later */
|
||||||
|
sys->traverse = 0;
|
||||||
|
sys->report = 1;
|
||||||
|
sys->switch_maxtracelength = INT_MAX;
|
||||||
|
sys->maxtracelength = INT_MAX;
|
||||||
|
|
||||||
|
/* init rundefs */
|
||||||
|
sys->maxruns = 0;
|
||||||
|
sys->runs = NULL;
|
||||||
|
/* no protocols yet */
|
||||||
|
sys->protocols = NULL;
|
||||||
|
sys->locals = NULL;
|
||||||
|
sys->variables = NULL;
|
||||||
|
sys->untrusted = NULL;
|
||||||
|
sys->secrets = NULL; // list of claimed secrets
|
||||||
|
sys->attack = NULL;
|
||||||
|
|
||||||
|
/* matching CLP */
|
||||||
|
sys->constraints = NULL; // no initial constraints
|
||||||
|
|
||||||
|
/* reset global counters */
|
||||||
|
systemReset (sys);
|
||||||
|
|
||||||
|
return sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systemReset (const System sys)
|
||||||
|
{
|
||||||
|
/* some initial counters */
|
||||||
|
sys->statesLow = 0; // number of explored states
|
||||||
|
sys->statesHigh = 0; // this is not as ridiculous as it might seem
|
||||||
|
sys->explore = 1; // do explore the space
|
||||||
|
sys->claims = 0; // number of claims encountered
|
||||||
|
sys->failed = 0; // number of failed claims
|
||||||
|
sys->knowPhase = 0; // knowledge transition id
|
||||||
|
|
||||||
|
termlistDestroy (sys->secrets); // remove old secrets list
|
||||||
|
sys->secrets = NULL; // list of claimed secrets
|
||||||
|
|
||||||
|
/* transfer switches */
|
||||||
|
sys->maxtracelength = sys->switch_maxtracelength;
|
||||||
|
|
||||||
|
/* POR init */
|
||||||
|
sys->PORphase = -1;
|
||||||
|
sys->PORdone = 1; // mark as 'something done' with previous reads
|
||||||
|
|
||||||
|
/* global latex switch: ugly, but otherwise I must carry it into every
|
||||||
|
* single subprocedure such as termPrint */
|
||||||
|
|
||||||
|
globalLatex = sys->latex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systemDone (System sys)
|
||||||
|
{
|
||||||
|
int run;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
/* clear globals, which were defined in systemStart */
|
||||||
|
|
||||||
|
s = sys->maxtracelength + 1;
|
||||||
|
memFree (sys->traceEvent, s * sizeof (Roledef));
|
||||||
|
memFree (sys->traceRun, s * sizeof (int));
|
||||||
|
memFree (sys->traceKnow, s * sizeof (Knowledge));
|
||||||
|
|
||||||
|
/* clear roledefs */
|
||||||
|
for (run = 0; run < sys->maxruns; run++)
|
||||||
|
roledefDestroy (runPointerGet (sys, run));
|
||||||
|
|
||||||
|
/* clear substructures */
|
||||||
|
termlistDestroy (sys->secrets);
|
||||||
|
|
||||||
|
/* clear main system */
|
||||||
|
systemDestroy (sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
statesApproximation (System sys)
|
||||||
|
{
|
||||||
|
if (sys->statesHigh == 0)
|
||||||
|
return (double) sys->statesLow;
|
||||||
|
else
|
||||||
|
return (double) (sys->statesLow + (sys->statesHigh * ULONG_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
statesPrintShort (System sys)
|
||||||
|
{
|
||||||
|
printf ("%.3e", statesApproximation (sys));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
statesPrint (System sys)
|
||||||
|
{
|
||||||
|
if (sys->statesHigh == 0)
|
||||||
|
{
|
||||||
|
printf ("%g", (double) sys->statesLow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double dstates;
|
||||||
|
|
||||||
|
dstates = sys->statesLow + (sys->statesHigh * ULONG_MAX);
|
||||||
|
printf ("%.3e (...)", dstates);
|
||||||
|
}
|
||||||
|
printf (" states traversed.\n");
|
||||||
|
if (globalLatex)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systemDestroy (System sys)
|
||||||
|
{
|
||||||
|
memFree (sys->runs, sys->maxruns * sizeof (struct run));
|
||||||
|
memFree (sys, sizeof (struct system));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensureValidRun
|
||||||
|
|
||||||
|
Makes sure memory is allocated for instantiating this run.
|
||||||
|
Note: This is meant to be used BEFORE using runPointerSet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
ensureValidRun (System sys, int run)
|
||||||
|
{
|
||||||
|
int i, oldsize;
|
||||||
|
|
||||||
|
if (run < sys->maxruns)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* this amount of memory was not allocated yet */
|
||||||
|
/* (re)allocate space */
|
||||||
|
/* Note, this is never explicitly freed, because it is never
|
||||||
|
copied */
|
||||||
|
|
||||||
|
sys->runs = (Run) memRealloc (sys->runs, sizeof (struct run) * (run + 1));
|
||||||
|
|
||||||
|
/* update size parameter */
|
||||||
|
oldsize = sys->maxruns;
|
||||||
|
sys->maxruns = run + 1;
|
||||||
|
|
||||||
|
/* create runs, set the new pointer(s) to NULL */
|
||||||
|
for (i = oldsize; i < sys->maxruns; i++)
|
||||||
|
{
|
||||||
|
/* init run */
|
||||||
|
struct run myrun = sys->runs[i];
|
||||||
|
myrun.role = NULL;
|
||||||
|
myrun.agents = NULL;
|
||||||
|
myrun.index = NULL;
|
||||||
|
myrun.start = NULL;
|
||||||
|
myrun.know = knowledgeDuplicate (sys->know);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runAdd (System sys, int run, int type, Term label, Term from, Term to,
|
||||||
|
Term msg)
|
||||||
|
{
|
||||||
|
Roledef newEvent;
|
||||||
|
Roledef scan;
|
||||||
|
|
||||||
|
newEvent = roledefInit (type, label, from, to, msg);
|
||||||
|
ensureValidRun (sys, run);
|
||||||
|
if (runPointerGet (sys, run) == NULL)
|
||||||
|
{
|
||||||
|
sys->runs[run].start = newEvent;
|
||||||
|
runPointerSet (sys, run, newEvent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scan = runPointerGet (sys, run);
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = newEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
roledefPrint (Roledef rd)
|
||||||
|
{
|
||||||
|
if (rd == NULL)
|
||||||
|
{
|
||||||
|
printf ("[Empty roledef]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rd->type == READ && rd->internal)
|
||||||
|
{
|
||||||
|
/* special case: internal read == choose ! */
|
||||||
|
printf ("CHOOSE(");
|
||||||
|
termPrint (rd->message);
|
||||||
|
printf (")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rd->type == READ)
|
||||||
|
printf ("READ");
|
||||||
|
if (rd->type == SEND)
|
||||||
|
printf ("SEND");
|
||||||
|
if (rd->type == CLAIM)
|
||||||
|
printf ("CLAIM");
|
||||||
|
if (rd->label != NULL)
|
||||||
|
{
|
||||||
|
if (globalLatex)
|
||||||
|
{
|
||||||
|
printf ("$_{");
|
||||||
|
termPrint (rd->label);
|
||||||
|
printf ("}$");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("_");
|
||||||
|
termPrint (rd->label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (globalLatex)
|
||||||
|
printf ("$");
|
||||||
|
printf ("\t(");
|
||||||
|
termPrint (rd->from);
|
||||||
|
printf (",");
|
||||||
|
if (rd->type == CLAIM)
|
||||||
|
printf (" ");
|
||||||
|
termPrint (rd->to);
|
||||||
|
printf (", ");
|
||||||
|
termPrint (rd->message);
|
||||||
|
printf (" )");
|
||||||
|
if (globalLatex)
|
||||||
|
printf ("$");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runPrint (Roledef rd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
indent ();
|
||||||
|
i = 0;
|
||||||
|
while (rd != NULL)
|
||||||
|
{
|
||||||
|
printf ("%i: ", i);
|
||||||
|
roledefPrint (rd);
|
||||||
|
printf ("\n");
|
||||||
|
i++;
|
||||||
|
rd = rd->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runsPrint (System sys)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
indent ();
|
||||||
|
printf ("[ Run definitions ]\n");
|
||||||
|
for (i = 0; i < (sys->maxruns); i++)
|
||||||
|
{
|
||||||
|
indent ();
|
||||||
|
printf ("Run definition %i:\n", i);
|
||||||
|
runPrint (runPointerGet (sys, i));
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns a pointer to the agent name term
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
agentOfRunRole (const System sys, const int run, const Term role)
|
||||||
|
{
|
||||||
|
Termlist roles = sys->runs[run].protocol->rolenames;
|
||||||
|
Termlist agents= sys->runs[run].agents;
|
||||||
|
|
||||||
|
/* TODO stupid reversed order, lose that soon */
|
||||||
|
agents = termlistForward(agents);
|
||||||
|
while (agents != NULL && roles != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual(roles->term, role))
|
||||||
|
{
|
||||||
|
return agents->term;
|
||||||
|
}
|
||||||
|
agents = agents->prev;
|
||||||
|
roles = roles->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns a pointer to the agent name term
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
agentOfRun (const System sys, const int run)
|
||||||
|
{
|
||||||
|
return agentOfRunRole(sys,run,sys->runs[run].role->nameterm);
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
roledefDuplicate1 (const Roledef rd)
|
||||||
|
{
|
||||||
|
if (rd == NULL)
|
||||||
|
return NULL;
|
||||||
|
Roledef newrd = makeRoledef ();
|
||||||
|
memcpy (newrd, rd, sizeof (struct roledef));
|
||||||
|
newrd->next = NULL;
|
||||||
|
return newrd;
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
roledefDuplicate (Roledef rd)
|
||||||
|
{
|
||||||
|
if (rd == NULL)
|
||||||
|
return NULL;
|
||||||
|
Roledef newrd = roledefDuplicate1 (rd);
|
||||||
|
newrd->next = roledefDuplicate (rd->next);
|
||||||
|
return newrd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
roledefDelete (Roledef rd)
|
||||||
|
{
|
||||||
|
if (rd == NULL)
|
||||||
|
return;
|
||||||
|
roledefDelete (rd->next);
|
||||||
|
memFree (rd, sizeof (struct roledef));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
roledefDestroy (Roledef rd)
|
||||||
|
{
|
||||||
|
if (rd == NULL)
|
||||||
|
return;
|
||||||
|
roledefDestroy (rd->next);
|
||||||
|
termDelete (rd->from);
|
||||||
|
termDelete (rd->to);
|
||||||
|
termDelete (rd->message);
|
||||||
|
memFree (rd, sizeof (struct roledef));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Instantiate a role by making a new run.
|
||||||
|
|
||||||
|
This involves creation of a new run(id).
|
||||||
|
Copy & subst of Roledef, Agent knowledge.
|
||||||
|
Tolist might contain type constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
roleInstance (const System sys, const Protocol protocol, const Role role,
|
||||||
|
const Termlist paramlist)
|
||||||
|
{
|
||||||
|
int rid;
|
||||||
|
Run runs;
|
||||||
|
Roledef rd;
|
||||||
|
Termlist scanfrom, scanto;
|
||||||
|
Termlist fromlist = NULL;
|
||||||
|
Termlist tolist = NULL;
|
||||||
|
Term extterm = NULL;
|
||||||
|
|
||||||
|
/* claim runid, allocate space */
|
||||||
|
rid = sys->maxruns;
|
||||||
|
ensureValidRun (sys, rid);
|
||||||
|
runs = sys->runs;
|
||||||
|
|
||||||
|
/* duplicate roledef in buffer rd */
|
||||||
|
rd = roledefDuplicate (role->roledef);
|
||||||
|
|
||||||
|
/* scan for types in agent list */
|
||||||
|
/* scanners */
|
||||||
|
scanfrom = protocol->rolenames;
|
||||||
|
scanto = paramlist;
|
||||||
|
while (scanfrom != NULL && scanto != NULL)
|
||||||
|
{
|
||||||
|
fromlist = termlistAdd (fromlist, scanfrom->term);
|
||||||
|
if (scanto->term->stype != NULL &&
|
||||||
|
inTermlist (scanto->term->stype, TERM_Type))
|
||||||
|
{
|
||||||
|
/* There is a TYPE constant in the parameter list.
|
||||||
|
* Generate a new local variable for this run, with this type */
|
||||||
|
Term newvar = makeTermType (VARIABLE, scanfrom->term->symb, rid);
|
||||||
|
sys->variables = termlistAdd (sys->variables, newvar);
|
||||||
|
newvar->stype = termlistAdd (NULL, scanto->term);
|
||||||
|
tolist = termlistAdd (tolist, newvar);
|
||||||
|
/* newvar is apparently new, but it might occur
|
||||||
|
* in the first event if it's a read, in which
|
||||||
|
* case we forget it */
|
||||||
|
if (!(rd->type == READ && termOccurs (rd->message, scanfrom->term)))
|
||||||
|
{
|
||||||
|
/* but this is already set in the first
|
||||||
|
* read... */
|
||||||
|
/* TODO scan might be more complex, but
|
||||||
|
* this will do for now. I.e. occurring
|
||||||
|
* first in a read will do */
|
||||||
|
extterm = makeTermTuple (newvar, extterm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* not a type constant, add to list */
|
||||||
|
tolist = termlistAdd (tolist, scanto->term);
|
||||||
|
}
|
||||||
|
scanfrom = scanfrom->next;
|
||||||
|
scanto = scanto->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prefix a read for such reads. TODO: this should also cover any external stuff */
|
||||||
|
if (extterm != NULL)
|
||||||
|
{
|
||||||
|
Roledef rdnew;
|
||||||
|
|
||||||
|
rdnew = roledefInit (READ, NULL, NULL, NULL, extterm);
|
||||||
|
/* this is an internal action! */
|
||||||
|
rdnew->internal = 1;
|
||||||
|
rdnew->next = rd;
|
||||||
|
rd = rdnew;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set parameters */
|
||||||
|
runs[rid].protocol = protocol;
|
||||||
|
runs[rid].role = role;
|
||||||
|
runs[rid].agents = termlistDuplicate (tolist);
|
||||||
|
runs[rid].start = rd;
|
||||||
|
runs[rid].index = rd;
|
||||||
|
|
||||||
|
/* duplicate all locals form this run */
|
||||||
|
scanto = role->locals;
|
||||||
|
while (scanto != NULL)
|
||||||
|
{
|
||||||
|
Term t = scanto->term;
|
||||||
|
if (!inTermlist (fromlist, t))
|
||||||
|
{
|
||||||
|
if (realTermLeaf (t))
|
||||||
|
{
|
||||||
|
Term newt = makeTermType (t->type, t->symb, rid);
|
||||||
|
if (realTermVariable (newt))
|
||||||
|
{
|
||||||
|
sys->variables = termlistAdd (sys->variables, newt);
|
||||||
|
}
|
||||||
|
newt->stype = t->stype;
|
||||||
|
fromlist = termlistAdd (fromlist, t);
|
||||||
|
tolist = termlistAdd (tolist, newt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scanto = scanto->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO this is not what we want yet, also local knowledge. The local
|
||||||
|
* knowledge (list?) also needs to be substituted on invocation. */
|
||||||
|
runs[rid].know = knowledgeDuplicate (sys->know);
|
||||||
|
|
||||||
|
/* now adjust the local run copy */
|
||||||
|
|
||||||
|
rd = runs[rid].start;
|
||||||
|
while (rd != NULL)
|
||||||
|
{
|
||||||
|
rd->from = termLocal (rd->from, fromlist, tolist, role->locals, rid);
|
||||||
|
rd->to = termLocal (rd->to, fromlist, tolist, role->locals, rid);
|
||||||
|
rd->message =
|
||||||
|
termLocal (rd->message, fromlist, tolist, role->locals, rid);
|
||||||
|
rd = rd->next;
|
||||||
|
}
|
||||||
|
termlistDelete (fromlist);
|
||||||
|
termlistDelete (tolist);
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
roledefInit (int type, Term label, Term from, Term to, Term msg)
|
||||||
|
{
|
||||||
|
Roledef newEvent;
|
||||||
|
|
||||||
|
newEvent = makeRoledef ();
|
||||||
|
newEvent->internal = 0;
|
||||||
|
newEvent->type = type;
|
||||||
|
newEvent->label = label;
|
||||||
|
newEvent->from = from;
|
||||||
|
newEvent->to = to;
|
||||||
|
newEvent->message = msg;
|
||||||
|
newEvent->forbidden = NULL; // no forbidden stuff
|
||||||
|
newEvent->knowPhase = -1; // we haven't explored any knowledge yet
|
||||||
|
newEvent->next = NULL;
|
||||||
|
return newEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
roledefAdd (Roledef rd, int type, Term label, Term from, Term to, Term msg)
|
||||||
|
{
|
||||||
|
Roledef scan;
|
||||||
|
|
||||||
|
if (rd == NULL)
|
||||||
|
return roledefInit (type, label, from, to, msg);
|
||||||
|
|
||||||
|
scan = rd;
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = roledefInit (type, label, from, to, msg);
|
||||||
|
return rd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* allocate memory for traces, runs have to be known for that */
|
||||||
|
|
||||||
|
void
|
||||||
|
systemStart (System sys)
|
||||||
|
{
|
||||||
|
int i, s;
|
||||||
|
Roledef rd;
|
||||||
|
|
||||||
|
s = 0;
|
||||||
|
for (i = 0; i < sys->maxruns; i++)
|
||||||
|
{
|
||||||
|
rd = runPointerGet (sys, i);
|
||||||
|
while (rd != NULL)
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
rd = rd->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is the maximum trace length */
|
||||||
|
if (sys->maxtracelength > s)
|
||||||
|
sys->maxtracelength = s;
|
||||||
|
|
||||||
|
/* trace gets one added entry for buffer */
|
||||||
|
s = sys->maxtracelength + 1;
|
||||||
|
|
||||||
|
/* freed in systemDone */
|
||||||
|
sys->traceEvent = memAlloc (s * sizeof (Roledef));
|
||||||
|
sys->traceRun = memAlloc (s * sizeof (int));
|
||||||
|
sys->traceKnow = memAlloc (s * sizeof (Knowledge));
|
||||||
|
|
||||||
|
/* clear, for niceties */
|
||||||
|
for (i = 0; i < s; i++)
|
||||||
|
{
|
||||||
|
sys->traceEvent[i] = NULL;
|
||||||
|
sys->traceRun[i] = 0;
|
||||||
|
sys->traceKnow[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
indentActivate ()
|
||||||
|
{
|
||||||
|
indentState = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
indentSet (int i)
|
||||||
|
{
|
||||||
|
if (indentState)
|
||||||
|
indentDepth = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
indent ()
|
||||||
|
{
|
||||||
|
int i = indentDepth;
|
||||||
|
int j = 0;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
printf ("%i ", j);
|
||||||
|
i--;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Protocol
|
||||||
|
protocolCreate (Term name)
|
||||||
|
{
|
||||||
|
Protocol p;
|
||||||
|
|
||||||
|
p = memAlloc (sizeof (struct protocol));
|
||||||
|
p->nameterm = name;
|
||||||
|
p->rolenames = NULL;
|
||||||
|
p->next = NULL;
|
||||||
|
p->roles = NULL;
|
||||||
|
p->locals = NULL;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Role
|
||||||
|
roleCreate (Term name)
|
||||||
|
{
|
||||||
|
Role r;
|
||||||
|
|
||||||
|
r = memAlloc (sizeof (struct role));
|
||||||
|
r->nameterm = name;
|
||||||
|
r->next = NULL;
|
||||||
|
r->locals = NULL;
|
||||||
|
r->roledef = NULL;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
locVarPrint (Termlist tl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
printf ("No local terms.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("Local terms: ");
|
||||||
|
printf ("[");
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
termPrint (tl->term);
|
||||||
|
if (tl->term->stype != NULL)
|
||||||
|
{
|
||||||
|
printf (":");
|
||||||
|
termlistPrint (tl->term->stype);
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
if (tl != NULL)
|
||||||
|
printf (",");
|
||||||
|
}
|
||||||
|
printf ("]");
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
protocolPrint (Protocol p)
|
||||||
|
{
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
indent ();
|
||||||
|
printf ("[[Protocol : ");
|
||||||
|
termPrint (p->nameterm);
|
||||||
|
printf (" (");
|
||||||
|
termlistPrint (p->rolenames);
|
||||||
|
printf (")]]\n");
|
||||||
|
locVarPrint (p->locals);
|
||||||
|
rolesPrint (p->roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
protocolsPrint (Protocol p)
|
||||||
|
{
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
protocolPrint (p);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rolePrint (Role r)
|
||||||
|
{
|
||||||
|
if (r == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
indent ();
|
||||||
|
printf ("[[Role : ");
|
||||||
|
termPrint (r->nameterm);
|
||||||
|
printf ("]]\n");
|
||||||
|
locVarPrint (r->locals);
|
||||||
|
|
||||||
|
Roledef rd = r->roledef;
|
||||||
|
while (rd != NULL)
|
||||||
|
{
|
||||||
|
roledefPrint (rd);
|
||||||
|
printf ("\n");
|
||||||
|
rd = rd->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rolesPrint (Role r)
|
||||||
|
{
|
||||||
|
if (r == NULL)
|
||||||
|
{
|
||||||
|
printf ("Empty role.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (r != NULL)
|
||||||
|
{
|
||||||
|
rolePrint (r);
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
untrustedAgent (System sys, Termlist agents)
|
||||||
|
{
|
||||||
|
while (agents != NULL)
|
||||||
|
{
|
||||||
|
if (isTermVariable (agents->term))
|
||||||
|
{
|
||||||
|
if (sys->clp)
|
||||||
|
{
|
||||||
|
/* clp: variables are difficult */
|
||||||
|
/* TODO Add as constraint that they're
|
||||||
|
* trusted */
|
||||||
|
/* However, that is a branch as well :(
|
||||||
|
*/
|
||||||
|
/* claim secret is _really_ a instant-multiple
|
||||||
|
* read. If it is succesful, we sound
|
||||||
|
* the alert */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inTermlist (sys->untrusted, agents->term))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
agents = agents->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getMaxTraceLength (const System sys)
|
||||||
|
{
|
||||||
|
Roledef rd;
|
||||||
|
int maxlen;
|
||||||
|
int run;
|
||||||
|
|
||||||
|
maxlen = 0;
|
||||||
|
for (run = 0; run < sys->maxruns; run++)
|
||||||
|
{
|
||||||
|
rd = runPointerGet (sys, run);
|
||||||
|
while (rd != NULL)
|
||||||
|
{
|
||||||
|
rd = rd->next;
|
||||||
|
maxlen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nicely format the role and agents we think we're talking to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
agentsOfRunPrint (const System sys, const int run)
|
||||||
|
{
|
||||||
|
Term role = sys->runs[run].role->nameterm;
|
||||||
|
Termlist roles = sys->runs[run].protocol->rolenames;
|
||||||
|
|
||||||
|
termPrint(role);
|
||||||
|
printf("(");
|
||||||
|
while (roles != NULL)
|
||||||
|
{
|
||||||
|
termPrint(agentOfRunRole(sys,run,roles->term));
|
||||||
|
roles = roles->next;
|
||||||
|
if (roles != NULL)
|
||||||
|
{
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* explain a violated claim at point i in the trace
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
violatedClaimPrint (const System sys, const int i)
|
||||||
|
{
|
||||||
|
printf("Claim stuk");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attackLength yields the real (user friendly) length of an attack by omitting
|
||||||
|
* the redundant events but also the choose events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int attackLength(struct tracebuf* tb)
|
||||||
|
{
|
||||||
|
int len,i;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
i = 0;
|
||||||
|
while (i < tb->length)
|
||||||
|
{
|
||||||
|
if (tb->status[i] != S_RED)
|
||||||
|
{
|
||||||
|
/* apparently not redundant */
|
||||||
|
if (!(tb->event[i]->type == READ && tb->event[i]->internal))
|
||||||
|
{
|
||||||
|
/* and no internal read, so it counts */
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
200
src/runs.h
Normal file
200
src/runs.h
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
#ifndef RUNS
|
||||||
|
#define RUNS
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "constraints.h"
|
||||||
|
|
||||||
|
#define READ 1
|
||||||
|
#define SEND 2
|
||||||
|
#define CLAIM 3
|
||||||
|
|
||||||
|
#define runPointerGet(sys,run) sys->runs[run].index
|
||||||
|
#define runPointerSet(sys,run,newp) sys->runs[run].index = newp
|
||||||
|
|
||||||
|
struct roledef
|
||||||
|
{
|
||||||
|
/* flag for internal actions (overriding normal type) */
|
||||||
|
int internal;
|
||||||
|
int type;
|
||||||
|
Term label;
|
||||||
|
Term from;
|
||||||
|
Term to;
|
||||||
|
Term message;
|
||||||
|
struct roledef *next;
|
||||||
|
|
||||||
|
/* illegal injections */
|
||||||
|
Knowledge forbidden;
|
||||||
|
/* knowledge transitions counter */
|
||||||
|
int knowPhase;
|
||||||
|
|
||||||
|
/* evt runid for synchronisation, but that is implied in the
|
||||||
|
base array */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct roledef *Roledef;
|
||||||
|
|
||||||
|
|
||||||
|
struct role
|
||||||
|
{
|
||||||
|
Term nameterm;
|
||||||
|
Roledef roledef;
|
||||||
|
Termlist locals;
|
||||||
|
struct role *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct role *Role;
|
||||||
|
|
||||||
|
struct protocol
|
||||||
|
{
|
||||||
|
Term nameterm;
|
||||||
|
Role roles;
|
||||||
|
Termlist rolenames;
|
||||||
|
Termlist locals;
|
||||||
|
struct protocol *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct protocol *Protocol;
|
||||||
|
|
||||||
|
struct run
|
||||||
|
{
|
||||||
|
Protocol protocol;
|
||||||
|
Role role;
|
||||||
|
Termlist agents;
|
||||||
|
Roledef index;
|
||||||
|
Roledef start;
|
||||||
|
Knowledge know;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct run *Run;
|
||||||
|
|
||||||
|
struct varbuf
|
||||||
|
{
|
||||||
|
Termlist from;
|
||||||
|
Termlist to;
|
||||||
|
Termlist empty;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct varbuf *Varbuf;
|
||||||
|
|
||||||
|
struct tracebuf
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
int reallength;
|
||||||
|
Roledef *event;
|
||||||
|
int *run;
|
||||||
|
int *status;
|
||||||
|
int *link;
|
||||||
|
int violatedclaim; // index of violated claim in trace
|
||||||
|
Knowledge *know;
|
||||||
|
Termlist requiredterms;
|
||||||
|
Varbuf variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct system
|
||||||
|
{
|
||||||
|
int step; // can be managed globally
|
||||||
|
Knowledge know;
|
||||||
|
struct parameters *parameters; // misc
|
||||||
|
/* static run info, maxruns */
|
||||||
|
Run runs;
|
||||||
|
|
||||||
|
/* global */
|
||||||
|
int maxruns;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
Termlist secrets; // integrate secrets list into system
|
||||||
|
int shortestattack; // length of shortest attack trace
|
||||||
|
|
||||||
|
/* switches */
|
||||||
|
int report;
|
||||||
|
int prune; // type of pruning
|
||||||
|
int switch_maxtracelength; // helps to remember the length of the last trace
|
||||||
|
int maxtracelength; // helps to remember the length of the last trace
|
||||||
|
int switchM; // memory
|
||||||
|
int switchT; // time
|
||||||
|
int switchS; // progress (traversed states)
|
||||||
|
int porparam; // a multi-purpose integer parameter, passed to the partial order reduction method selected
|
||||||
|
int latex; // latex output switch
|
||||||
|
|
||||||
|
/* traversal */
|
||||||
|
int traverse; // traversal method
|
||||||
|
int explore; // boolean: explore states after actions or not
|
||||||
|
|
||||||
|
/* counters */
|
||||||
|
unsigned long int statesLow;
|
||||||
|
unsigned long int statesHigh;
|
||||||
|
unsigned long int claims; // number of claims encountered
|
||||||
|
unsigned long int failed; // number of claims failed
|
||||||
|
|
||||||
|
/* matching */
|
||||||
|
int match; // matching type
|
||||||
|
int clp; // do we use clp?
|
||||||
|
|
||||||
|
/* protocol definition */
|
||||||
|
Protocol protocols;
|
||||||
|
Termlist locals;
|
||||||
|
Termlist variables;
|
||||||
|
Termlist untrusted;
|
||||||
|
|
||||||
|
/* constructed trace pointers, static */
|
||||||
|
Roledef *traceEvent; // MaxRuns * maxRoledef
|
||||||
|
int *traceRun; // MaxRuns * maxRoledef
|
||||||
|
Knowledge *traceKnow; // Maxruns * maxRoledef
|
||||||
|
|
||||||
|
/* POR reduction assistance */
|
||||||
|
int PORphase; // -1: init (all sends), 0...: recurse reads
|
||||||
|
int PORdone; // simple bit to denote something was done.
|
||||||
|
int knowPhase; // which knowPhase have we already explored?
|
||||||
|
Constraintlist constraints; // only needed for CLP match
|
||||||
|
|
||||||
|
/* relevant: storage of shortest attack */
|
||||||
|
struct tracebuf* attack;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct system *System;
|
||||||
|
|
||||||
|
System systemInit ();
|
||||||
|
void systemReset (const System sys);
|
||||||
|
System systemDuplicate (System fromsys);
|
||||||
|
void statesPrint (System sys);
|
||||||
|
void statesPrintShort (System sys);
|
||||||
|
void systemDestroy (System sys);
|
||||||
|
void systemDone (System sys);
|
||||||
|
void ensureValidRun (System sys, int run);
|
||||||
|
void runAdd (System sys, int run, int type, Term label, Term from, Term to,
|
||||||
|
Term msg);
|
||||||
|
void roledefPrint (Roledef rd);
|
||||||
|
void runPrint (Roledef rd);
|
||||||
|
void runsPrint (System sys);
|
||||||
|
Term agentOfRunRole (const System sys, const int run, const Term role);
|
||||||
|
Term agentOfRun (const System sys, const int run);
|
||||||
|
Roledef roledefDuplicate1 (const Roledef rd);
|
||||||
|
Roledef roledefDuplicate (Roledef rd);
|
||||||
|
void roledefDelete (Roledef rd);
|
||||||
|
void roledefDestroy (Roledef rd);
|
||||||
|
void roleInstance (const System sys, const Protocol protocol, const Role role,
|
||||||
|
const Termlist tolist);
|
||||||
|
Roledef roledefInit (int type, Term label, Term from, Term to, Term msg);
|
||||||
|
Roledef roledefAdd (Roledef rd, int type, Term label, Term from, Term to,
|
||||||
|
Term msg);
|
||||||
|
void systemStart (System sys);
|
||||||
|
void indentActivate ();
|
||||||
|
void indentSet (int i);
|
||||||
|
void indent ();
|
||||||
|
|
||||||
|
Protocol protocolCreate (Term nameterm);
|
||||||
|
Role roleCreate (Term nameterm);
|
||||||
|
void locVarPrint (Termlist tl);
|
||||||
|
void protocolPrint (Protocol p);
|
||||||
|
void protocolsPrint (Protocol p);
|
||||||
|
void rolePrint (Role r);
|
||||||
|
void rolesPrint (Role r);
|
||||||
|
int untrustedAgent (System sys, Termlist agents);
|
||||||
|
int getMaxTraceLength (const System sys);
|
||||||
|
void agentsOfRunPrint (const System sys, const int run);
|
||||||
|
void violatedClaimPrint (const System sys, int i);
|
||||||
|
int attackLength(struct tracebuf* tb);
|
||||||
|
|
||||||
|
#endif
|
160
src/scanner.lex
Normal file
160
src/scanner.lex
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
%option yylineno
|
||||||
|
|
||||||
|
%{
|
||||||
|
/* scanner for security protocols language */
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
#include "pheading.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "tac.h"
|
||||||
|
|
||||||
|
/* tokens for language */
|
||||||
|
#include "tok.h"
|
||||||
|
|
||||||
|
void mkname(char *name);
|
||||||
|
void mkval(void);
|
||||||
|
void mktext(void);
|
||||||
|
|
||||||
|
int yyerror(char *s);
|
||||||
|
|
||||||
|
Symbol mkstring(char *name);
|
||||||
|
|
||||||
|
struct stringlist {
|
||||||
|
char* string;
|
||||||
|
struct stringlist* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct stringlist* Stringlist;
|
||||||
|
|
||||||
|
static Stringlist allocatedStrings = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
int mylineno = 0;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
comment1 "//".*
|
||||||
|
comment2 "#".*
|
||||||
|
delimiter [ \t\n]
|
||||||
|
whitespace {delimiter}+
|
||||||
|
uc_letter [A-Z]
|
||||||
|
lc_letter [a-z]
|
||||||
|
letter {lc_letter}|{uc_letter}
|
||||||
|
digit [0-9]
|
||||||
|
ascii_char [^\"\n]
|
||||||
|
escaped_char \\n|\\\"
|
||||||
|
integer {digit}+
|
||||||
|
text \"({ascii_char}|{escaped_char})*\"
|
||||||
|
id ({letter}|{digit})+
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
"/*" {
|
||||||
|
register int c;
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
while ( (c = input()) != '*' && c != '\n' && c != EOF )
|
||||||
|
; /* eat up text of comment */
|
||||||
|
|
||||||
|
if ( c == '*' )
|
||||||
|
{
|
||||||
|
while ( (c = input()) == '*' )
|
||||||
|
;
|
||||||
|
if ( c == '/' )
|
||||||
|
break; /* found the end */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
mylineno++;
|
||||||
|
|
||||||
|
if ( c == EOF )
|
||||||
|
{
|
||||||
|
yyerror( "EOF in comment" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\n { mylineno++; }
|
||||||
|
{whitespace} { }
|
||||||
|
{comment1} { }
|
||||||
|
{comment2} { }
|
||||||
|
|
||||||
|
protocol { return PROTOCOL; }
|
||||||
|
role { return ROLE; }
|
||||||
|
read { return READT; }
|
||||||
|
send { return SENDT; }
|
||||||
|
var { return VAR; }
|
||||||
|
const { return CONST; }
|
||||||
|
claim { return CLAIMT; }
|
||||||
|
run { return RUN; }
|
||||||
|
secret { return SECRET; }
|
||||||
|
inversekeys { return INVERSEKEYS; }
|
||||||
|
untrusted { return UNTRUSTED; }
|
||||||
|
compromised { return COMPROMISED; }
|
||||||
|
usertype { return USERTYPE; }
|
||||||
|
{id} {
|
||||||
|
yylval.symb = mkstring(yytext);
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
. { return yytext[0]; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
Symbol mkstring(char *name)
|
||||||
|
{
|
||||||
|
Symbol t;
|
||||||
|
char* s;
|
||||||
|
Stringlist sl;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (( t = lookup(name)) != NULL)
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
// make new name
|
||||||
|
len = strlen(name);
|
||||||
|
s = (char *)memAlloc(len+1);
|
||||||
|
sl = (Stringlist) memAlloc(sizeof(struct stringlist));
|
||||||
|
strncpy(s,name,len);
|
||||||
|
sl->next = allocatedStrings;
|
||||||
|
allocatedStrings = sl;
|
||||||
|
sl->string = s;
|
||||||
|
s[len] = EOS;
|
||||||
|
|
||||||
|
t = get_symb();
|
||||||
|
t->lineno = yylineno;
|
||||||
|
t->type = T_UNDEF;
|
||||||
|
t->text = s;
|
||||||
|
|
||||||
|
insert(t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scanner_cleanup(void)
|
||||||
|
{
|
||||||
|
yy_delete_buffer (YY_CURRENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void strings_cleanup(void)
|
||||||
|
{
|
||||||
|
Stringlist sl;
|
||||||
|
while (allocatedStrings != NULL)
|
||||||
|
{
|
||||||
|
sl = allocatedStrings;
|
||||||
|
allocatedStrings = sl->next;
|
||||||
|
memFree(sl->string, strlen(sl->string)+1);
|
||||||
|
memFree(sl, sizeof(struct stringlist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void mkval(void);
|
||||||
|
void mktext(void);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// vim:ft=lex:
|
3
src/speedtest
Executable file
3
src/speedtest
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
./scyther -d -p0 -r 8 $* <spdl/speedtest.spdl
|
285
src/substitutions.c
Normal file
285
src/substitutions.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "substitutions.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/* substitutions in terms */
|
||||||
|
|
||||||
|
Substitution
|
||||||
|
makeSubstitution (Term from, Term to)
|
||||||
|
{
|
||||||
|
Substitution subs;
|
||||||
|
|
||||||
|
subs = memAlloc (sizeof (struct substitution));
|
||||||
|
subs->from = from;
|
||||||
|
subs->to = to;
|
||||||
|
return subs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionDelete (Substitution subs)
|
||||||
|
{
|
||||||
|
if (subs == NULL)
|
||||||
|
return;
|
||||||
|
memFree (subs, sizeof (struct substitution));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionDestroy (Substitution subs)
|
||||||
|
{
|
||||||
|
if (subs == NULL)
|
||||||
|
return;
|
||||||
|
termDelete (subs->from);
|
||||||
|
termDelete (subs->to);
|
||||||
|
memFree (subs, sizeof (struct substitution));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
termSubstitute
|
||||||
|
|
||||||
|
Yields a new (deep copy) term of a term, according to the
|
||||||
|
substitution.
|
||||||
|
|
||||||
|
To remove the old term, use termDelete.
|
||||||
|
Be sure to use termNormalize on it afterwards!!
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Term
|
||||||
|
termSubstitute (Term term, Substitution subs)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (isTermEqual (term, subs->from))
|
||||||
|
{
|
||||||
|
return termDuplicate (subs->to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isTermLeaf (term))
|
||||||
|
{
|
||||||
|
if (isTermEncrypt (term))
|
||||||
|
{
|
||||||
|
return makeTermEncrypt (termSubstitute (term->op, subs),
|
||||||
|
termSubstitute (term->key, subs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return
|
||||||
|
makeTermTuple (termSubstitute (term->op1, subs),
|
||||||
|
termSubstitute (term->op2, subs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return termDuplicate (term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistSubstitute.
|
||||||
|
|
||||||
|
Makes a new list, deep copies of the terms.
|
||||||
|
|
||||||
|
To remove the old termlist, use termlistDestroy
|
||||||
|
|
||||||
|
TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistSubstitute (Termlist tl, Substitution subs)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Termlist tls = termlistSubstitute (tl->next, subs);
|
||||||
|
//return termlistAdd(termlistSubstitute(tl->next, subs),
|
||||||
|
// termSubstitute(tl->term, subs));
|
||||||
|
return tls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionPrint (Term t, Substitution subs)
|
||||||
|
{
|
||||||
|
printf ("Substituting ");
|
||||||
|
termPrint (subs->from);
|
||||||
|
printf (" by ");
|
||||||
|
termPrint (subs->to);
|
||||||
|
printf (" in ");
|
||||||
|
termPrint (t);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* termSubstituteList
|
||||||
|
|
||||||
|
Not very efficient at the moment. Recursing through the term might be
|
||||||
|
a lot easier. However, this works.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termSubstituteList (Term term, Substitutionlist sl)
|
||||||
|
{
|
||||||
|
Term newt;
|
||||||
|
Term oldt;
|
||||||
|
|
||||||
|
if (sl == NULL)
|
||||||
|
return termDuplicate (term);
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
newt = termSubstitute (term, sl->subst);
|
||||||
|
sl = sl->next;
|
||||||
|
while (sl != NULL)
|
||||||
|
{
|
||||||
|
oldt = newt;
|
||||||
|
newt = termSubstitute (oldt, sl->subst);
|
||||||
|
termDelete (oldt);
|
||||||
|
sl = sl->next;
|
||||||
|
}
|
||||||
|
return newt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Substitutionlist
|
||||||
|
makeSubstitutionList (Substitution subs)
|
||||||
|
{
|
||||||
|
Substitutionlist sl;
|
||||||
|
|
||||||
|
sl = memAlloc (sizeof (struct substitutionlist));
|
||||||
|
sl->subst = subs;
|
||||||
|
sl->next = NULL;
|
||||||
|
return sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Substitutionlist
|
||||||
|
substitutionlistAdd (Substitutionlist sl, Term from, Term to)
|
||||||
|
{
|
||||||
|
return substitutionlistConcat (sl,
|
||||||
|
makeSubstitutionList (makeSubstitution
|
||||||
|
(from, to)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionlistDestroy (Substitutionlist sl)
|
||||||
|
{
|
||||||
|
if (sl != NULL)
|
||||||
|
{
|
||||||
|
substitutionDelete (sl->subst);
|
||||||
|
substitutionlistDestroy (sl->next);
|
||||||
|
memFree (sl, sizeof (struct substitutionlist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionlistAnnihilate (Substitutionlist sl)
|
||||||
|
{
|
||||||
|
if (sl != NULL)
|
||||||
|
{
|
||||||
|
substitutionDestroy (sl->subst);
|
||||||
|
substitutionlistDestroy (sl->next);
|
||||||
|
memFree (sl, sizeof (struct substitutionlist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Substitutionlist
|
||||||
|
substitutionlistConcat (Substitutionlist sl1, Substitutionlist sl2)
|
||||||
|
{
|
||||||
|
Substitutionlist scan;
|
||||||
|
|
||||||
|
if (sl1 == NULL)
|
||||||
|
return sl2;
|
||||||
|
scan = sl1;
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = sl2;
|
||||||
|
return sl1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* substitute over termlist */
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
substitutionBatch (Termlist tl, Substitutionlist sl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (sl == NULL)
|
||||||
|
return termlistDuplicate (tl);
|
||||||
|
Termlist newtl = NULL;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
newtl = termlistAdd (newtl, termSubstituteList (tl->term, sl));
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* substitute over roledef */
|
||||||
|
|
||||||
|
Roledef
|
||||||
|
substitutionRoledef (Roledef rdorig, Substitutionlist sl)
|
||||||
|
{
|
||||||
|
Roledef rd, rdscan;
|
||||||
|
|
||||||
|
rd = roledefDuplicate (rdorig);
|
||||||
|
rdscan = rd;
|
||||||
|
|
||||||
|
while (rdscan != NULL)
|
||||||
|
{
|
||||||
|
rdscan->from = termSubstituteList (rdscan->from, sl);
|
||||||
|
rdscan->to = termSubstituteList (rdscan->to, sl);
|
||||||
|
rdscan->message = termSubstituteList (rdscan->message, sl);
|
||||||
|
rdscan = rdscan->next;
|
||||||
|
}
|
||||||
|
return rd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* substitute over knowledge structure */
|
||||||
|
|
||||||
|
Knowledge
|
||||||
|
substitutionKnowledge (Knowledge know, Substitutionlist sl)
|
||||||
|
{
|
||||||
|
/* TODO this is wrong anyway, because it does not respect the knowledge invariants. We should remove the variables occurring on
|
||||||
|
the left, and add to the knowledge the new stuff */
|
||||||
|
|
||||||
|
Termlist repres, repres2;
|
||||||
|
|
||||||
|
Knowledge know2 = emptyKnowledge ();
|
||||||
|
knowledgeSetInverses (know2, knowledgeGetInverses (know));
|
||||||
|
repres = knowledgeSet (know);
|
||||||
|
repres2 = substitutionBatch (repres, sl);
|
||||||
|
knowledgeAddTermlist (know2, repres2);
|
||||||
|
termlistDelete (repres2);
|
||||||
|
termlistDelete (repres);
|
||||||
|
return know2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
substitutionlistPrint (Substitutionlist sl)
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
if (sl == NULL)
|
||||||
|
printf ("[empty substitutionlist]\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (sl != NULL)
|
||||||
|
{
|
||||||
|
printf ("%i: ", i);
|
||||||
|
termPrint (sl->subst->from);
|
||||||
|
printf (" -> ");
|
||||||
|
termPrint (sl->subst->to);
|
||||||
|
printf ("\n");
|
||||||
|
i++;
|
||||||
|
sl = sl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
src/substitutions.h
Normal file
44
src/substitutions.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef SUBSTITUTIONS
|
||||||
|
#define SUBSTITUTIONS
|
||||||
|
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
struct substitution
|
||||||
|
{
|
||||||
|
Term from;
|
||||||
|
Term to;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct substitution *Substitution;
|
||||||
|
|
||||||
|
struct substitutionlist
|
||||||
|
{
|
||||||
|
Substitution subst;
|
||||||
|
struct substitutionlist *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct substitutionlist *Substitutionlist;
|
||||||
|
|
||||||
|
|
||||||
|
Substitution makeSubstitution (Term from, Term to);
|
||||||
|
void substitutionDelete (Substitution subs);
|
||||||
|
void substitutionDestroy (Substitution subs);
|
||||||
|
Term termSubstitute (Term term, Substitution subs);
|
||||||
|
Termlist termlistSubstitute (Termlist tl, Substitution subs);
|
||||||
|
void substitutionPrint (Term t, Substitution subs);
|
||||||
|
Term termSubstituteList (Term term, Substitutionlist sl);
|
||||||
|
Substitutionlist makeSubstitutionList (Substitution subs);
|
||||||
|
Substitutionlist substitutionlistAdd (Substitutionlist sl, Term from,
|
||||||
|
Term to);
|
||||||
|
void substitutionlistDestroy (Substitutionlist sl);
|
||||||
|
void substitutionlistAnnihilate (Substitutionlist sl);
|
||||||
|
Substitutionlist substitutionlistConcat (Substitutionlist sl1,
|
||||||
|
Substitutionlist sl2);
|
||||||
|
Termlist substitutionBatch (Termlist tl, Substitutionlist sl);
|
||||||
|
Roledef substitutionRoledef (Roledef rd, Substitutionlist sl);
|
||||||
|
Knowledge substitutionKnowledge (Knowledge know, Substitutionlist sl);
|
||||||
|
void substitutionlistPrint (Substitutionlist sl);
|
||||||
|
|
||||||
|
#endif
|
145
src/symbols.c
Normal file
145
src/symbols.c
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Symbol processor.
|
||||||
|
|
||||||
|
Stores symbols for the lexical scanner. Can later print them.
|
||||||
|
Implementation uses a hashtable, the size of which is defined in
|
||||||
|
symbols.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int yylineno;
|
||||||
|
|
||||||
|
/* global declarations */
|
||||||
|
|
||||||
|
Symbol symbtab[HASHSIZE];
|
||||||
|
Symbol symb_list;
|
||||||
|
Symbol symb_alloc;
|
||||||
|
|
||||||
|
/* main code */
|
||||||
|
|
||||||
|
void
|
||||||
|
symbolsInit (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < HASHSIZE; i++)
|
||||||
|
symbtab[i] = NULL;
|
||||||
|
symb_list = NULL;
|
||||||
|
symb_alloc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
symbolsDone (void)
|
||||||
|
{
|
||||||
|
Symbol s;
|
||||||
|
|
||||||
|
while (symb_alloc != NULL)
|
||||||
|
{
|
||||||
|
s = symb_alloc;
|
||||||
|
symb_alloc = s->allocnext;
|
||||||
|
memFree (s, sizeof (struct symbol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol
|
||||||
|
get_symb (void)
|
||||||
|
{
|
||||||
|
Symbol t;
|
||||||
|
if (symb_list != NULL)
|
||||||
|
{
|
||||||
|
t = symb_list;
|
||||||
|
symb_list = symb_list->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = (Symbol) memAlloc (sizeof (struct symbol));
|
||||||
|
t->allocnext = symb_alloc;
|
||||||
|
symb_alloc = t;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_symb (Symbol s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
s->next = symb_list;
|
||||||
|
symb_list = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hash (char *s)
|
||||||
|
{
|
||||||
|
int hv = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; s[i] != EOS; i++)
|
||||||
|
{
|
||||||
|
int v = (hv >> 28) ^ (s[i] & 0xf);
|
||||||
|
hv = (hv << 4) | v;
|
||||||
|
}
|
||||||
|
hv = hv & 0x7fffffff;
|
||||||
|
return hv % HASHSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
insert (Symbol s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return; /* illegal insertion of empty stuff */
|
||||||
|
|
||||||
|
int hv = hash (s->text);
|
||||||
|
s->next = symbtab[hv];
|
||||||
|
symbtab[hv] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol
|
||||||
|
lookup (char *s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int hv = hash (s);
|
||||||
|
Symbol t = symbtab[hv];
|
||||||
|
|
||||||
|
while (t != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp (t->text, s) == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
symbolPrint (Symbol s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO maybe action depending on type? */
|
||||||
|
printf ("%s", s->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol
|
||||||
|
symbolSysConst (char *str)
|
||||||
|
{
|
||||||
|
Symbol symb;
|
||||||
|
|
||||||
|
symb = lookup (str);
|
||||||
|
if (symb == NULL)
|
||||||
|
{
|
||||||
|
symb = get_symb ();
|
||||||
|
symb->lineno = yylineno;
|
||||||
|
symb->type = T_SYSCONST;
|
||||||
|
symb->text = str;
|
||||||
|
}
|
||||||
|
return symb;
|
||||||
|
}
|
37
src/symbols.h
Normal file
37
src/symbols.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef SYMBOLS
|
||||||
|
#define SYMBOLS
|
||||||
|
|
||||||
|
/* Size of hashtable: optimistically large. */
|
||||||
|
#define HASHSIZE 997
|
||||||
|
|
||||||
|
#define T_UNDEF -1
|
||||||
|
#define T_PROTOCOL 0
|
||||||
|
#define T_CONST 1
|
||||||
|
#define T_VAR 2
|
||||||
|
#define T_SYSCONST 3
|
||||||
|
|
||||||
|
#define EOS 0
|
||||||
|
|
||||||
|
struct symbol
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
int lineno;
|
||||||
|
char *text;
|
||||||
|
struct symbol *next;
|
||||||
|
struct symbol *allocnext;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct symbol *Symbol;
|
||||||
|
|
||||||
|
void symbolsInit (void);
|
||||||
|
void symbolsDone (void);
|
||||||
|
|
||||||
|
Symbol get_symb (void);
|
||||||
|
void free_symb (Symbol s);
|
||||||
|
|
||||||
|
void insert (Symbol s);
|
||||||
|
Symbol lookup (char *s);
|
||||||
|
void symbolPrint (Symbol s);
|
||||||
|
Symbol symbolSysConst (char *str);
|
||||||
|
|
||||||
|
#endif
|
269
src/tac.c
Normal file
269
src/tac.c
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "tac.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
extern int yylineno;
|
||||||
|
|
||||||
|
static Tac allocatedTacs;
|
||||||
|
|
||||||
|
void
|
||||||
|
tacInit (void)
|
||||||
|
{
|
||||||
|
allocatedTacs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tacDone (void)
|
||||||
|
{
|
||||||
|
Tac ts, tf;
|
||||||
|
|
||||||
|
ts = allocatedTacs;
|
||||||
|
while (ts != NULL)
|
||||||
|
{
|
||||||
|
tf = ts;
|
||||||
|
ts = ts->allnext;
|
||||||
|
memFree (tf, sizeof (struct tacnode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tac
|
||||||
|
tacCreate (int op)
|
||||||
|
{
|
||||||
|
/* maybe even store in scrapping list, so we could delete them
|
||||||
|
* all later */
|
||||||
|
Tac t = memAlloc (sizeof (struct tacnode));
|
||||||
|
t->allnext = allocatedTacs;
|
||||||
|
allocatedTacs = t;
|
||||||
|
t->lineno = yylineno;
|
||||||
|
t->op = op;
|
||||||
|
t->next = NULL;
|
||||||
|
t->prev = NULL;
|
||||||
|
t->tac1 = NULL;
|
||||||
|
t->tac2 = NULL;
|
||||||
|
t->tac3 = NULL;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tac
|
||||||
|
tacString (char *s)
|
||||||
|
{
|
||||||
|
Tac t;
|
||||||
|
t = tacCreate (TAC_STRING);
|
||||||
|
t->str1 = s;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tac
|
||||||
|
tacJoin (int op, Tac t1, Tac t2, Tac t3)
|
||||||
|
{
|
||||||
|
Tac t;
|
||||||
|
t = tacCreate (op);
|
||||||
|
t->tac1 = t1;
|
||||||
|
t->tac2 = t2;
|
||||||
|
t->tac3 = t3;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tac
|
||||||
|
tacCat (Tac t1, Tac t2)
|
||||||
|
{
|
||||||
|
Tac t1e;
|
||||||
|
|
||||||
|
if (t1 == NULL)
|
||||||
|
{
|
||||||
|
if (t2 == NULL)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t1e = t1;
|
||||||
|
while (t1e->next != NULL)
|
||||||
|
t1e = t1e->next;
|
||||||
|
t1e->next = t2;
|
||||||
|
if (t2 != NULL)
|
||||||
|
{
|
||||||
|
t2->prev = t1e;
|
||||||
|
}
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in: a list. out: a tuple (for e.g. associativity)
|
||||||
|
* Effectively, this defines how we interpret tuples with
|
||||||
|
* more than two components.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Tac
|
||||||
|
tacTuple (Tac taclist)
|
||||||
|
{
|
||||||
|
Tac tc;
|
||||||
|
|
||||||
|
/* check for single node */
|
||||||
|
if (taclist->next == NULL)
|
||||||
|
{
|
||||||
|
/* just return */
|
||||||
|
tc = taclist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* otherwise, write as (x,(y,(z,..))) */
|
||||||
|
tc = tacCreate (TAC_TUPLE);
|
||||||
|
tc->tac1 = taclist;
|
||||||
|
tc->tac2 = tacTuple (taclist->next);
|
||||||
|
|
||||||
|
/* unlink list */
|
||||||
|
tc->tac1->next = NULL;
|
||||||
|
tc->tac2->prev = NULL;
|
||||||
|
}
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tacPrint
|
||||||
|
* Print the tac. Only for debugging purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
tacPrint (Tac t)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
return;
|
||||||
|
switch (t->op)
|
||||||
|
{
|
||||||
|
case TAC_PROTOCOL:
|
||||||
|
printf ("protocol %s (", t->sym1->text);
|
||||||
|
tacPrint (t->tac3);
|
||||||
|
printf (")\n{\n");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf ("};\n");
|
||||||
|
break;
|
||||||
|
case TAC_ROLE:
|
||||||
|
printf ("role %s\n{\n", t->sym1->text);
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf ("};\n");
|
||||||
|
break;
|
||||||
|
case TAC_READ:
|
||||||
|
printf ("read");
|
||||||
|
if (t->sym1 != NULL)
|
||||||
|
{
|
||||||
|
printf ("_%s", t->sym1->text);
|
||||||
|
}
|
||||||
|
printf ("(");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (");\n");
|
||||||
|
break;
|
||||||
|
case TAC_SEND:
|
||||||
|
printf ("send");
|
||||||
|
if (t->sym1 != NULL)
|
||||||
|
{
|
||||||
|
printf ("_%s", t->sym1->text);
|
||||||
|
}
|
||||||
|
printf ("(");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (");\n");
|
||||||
|
break;
|
||||||
|
case TAC_CLAIM:
|
||||||
|
printf ("claim");
|
||||||
|
if (t->sym1 != NULL)
|
||||||
|
{
|
||||||
|
printf ("_%s", t->sym1->text);
|
||||||
|
}
|
||||||
|
printf ("(");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (");\n");
|
||||||
|
break;
|
||||||
|
case TAC_CONST:
|
||||||
|
printf ("const ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
if (t->tac2 != NULL)
|
||||||
|
{
|
||||||
|
printf (" : ");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
}
|
||||||
|
printf (";\n");
|
||||||
|
break;
|
||||||
|
case TAC_VAR:
|
||||||
|
printf ("var ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
if (t->tac2 != NULL)
|
||||||
|
{
|
||||||
|
printf (" : ");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
}
|
||||||
|
printf (";\n");
|
||||||
|
break;
|
||||||
|
case TAC_UNDEF:
|
||||||
|
printf ("undefined");
|
||||||
|
if (t->next != NULL)
|
||||||
|
printf (",");
|
||||||
|
break;
|
||||||
|
case TAC_STRING:
|
||||||
|
printf ("%s", t->sym1->text);
|
||||||
|
if (t->next != NULL)
|
||||||
|
printf (",");
|
||||||
|
break;
|
||||||
|
case TAC_TUPLE:
|
||||||
|
printf ("(");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf (",");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (")");
|
||||||
|
break;
|
||||||
|
case TAC_ENCRYPT:
|
||||||
|
printf ("{");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf ("}");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
if (t->next != NULL)
|
||||||
|
{
|
||||||
|
printf (",");
|
||||||
|
t = t->next;
|
||||||
|
tacPrint (t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TAC_RUN:
|
||||||
|
printf ("run ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf ("(");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (");\n");
|
||||||
|
break;
|
||||||
|
case TAC_ROLEREF:
|
||||||
|
symbolPrint (t->sym1);
|
||||||
|
printf (".");
|
||||||
|
symbolPrint (t->sym2);
|
||||||
|
break;
|
||||||
|
case TAC_COMPROMISED:
|
||||||
|
printf ("compromised ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf (";\n");
|
||||||
|
break;
|
||||||
|
case TAC_SECRET:
|
||||||
|
printf ("secret ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf (";\n");
|
||||||
|
break;
|
||||||
|
case TAC_INVERSEKEYS:
|
||||||
|
printf ("inversekeys (");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf (",");
|
||||||
|
tacPrint (t->tac2);
|
||||||
|
printf (");\n");
|
||||||
|
break;
|
||||||
|
case TAC_UNTRUSTED:
|
||||||
|
printf ("untrusted ");
|
||||||
|
tacPrint (t->tac1);
|
||||||
|
printf (";\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("[??]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and any other stuff */
|
||||||
|
if (t->next != NULL)
|
||||||
|
{
|
||||||
|
tacPrint (t->next);
|
||||||
|
}
|
||||||
|
}
|
69
src/tac.h
Normal file
69
src/tac.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef TAC_H
|
||||||
|
#define TAC_H
|
||||||
|
|
||||||
|
#include "symbols.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TAC instructions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TAC_UNDEF 0
|
||||||
|
#define TAC_SYM 1
|
||||||
|
#define TAC_TUPLE 3
|
||||||
|
#define TAC_ENCRYPT 4
|
||||||
|
#define TAC_VAR 7
|
||||||
|
#define TAC_CONST 8
|
||||||
|
#define TAC_READ 9
|
||||||
|
#define TAC_SEND 10
|
||||||
|
#define TAC_CLAIM 11
|
||||||
|
#define TAC_FUNC 12
|
||||||
|
#define TAC_STRING 13
|
||||||
|
#define TAC_ROLE 14
|
||||||
|
#define TAC_PROTOCOL 15
|
||||||
|
#define TAC_RUN 16
|
||||||
|
#define TAC_ROLEREF 17
|
||||||
|
#define TAC_SECRET 18
|
||||||
|
#define TAC_INVERSEKEYS 19
|
||||||
|
#define TAC_UNTRUSTED 20
|
||||||
|
#define TAC_COMPROMISED 21
|
||||||
|
#define TAC_USERTYPE 22
|
||||||
|
|
||||||
|
struct tacnode
|
||||||
|
{
|
||||||
|
struct tacnode *next;
|
||||||
|
struct tacnode *prev;
|
||||||
|
struct tacnode *allnext;
|
||||||
|
int op;
|
||||||
|
int lineno;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Symbol sym1;
|
||||||
|
struct tacnode *tac1;
|
||||||
|
char *str1;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Symbol sym2;
|
||||||
|
struct tacnode *tac2;
|
||||||
|
char *str2;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Symbol sym3;
|
||||||
|
struct tacnode *tac3;
|
||||||
|
char *str3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct tacnode *Tac;
|
||||||
|
|
||||||
|
void tacInit (void);
|
||||||
|
void tacDone (void);
|
||||||
|
Tac tacCreate (int op);
|
||||||
|
Tac tacSymb (char *s);
|
||||||
|
Tac tacJoin (int op, Tac t1, Tac t2, Tac t3);
|
||||||
|
Tac tacTuple (Tac taclist);
|
||||||
|
Tac tacCat (Tac t1, Tac t2);
|
||||||
|
void tacPrint (Tac t);
|
||||||
|
|
||||||
|
#endif
|
702
src/termlists.c
Normal file
702
src/termlists.c
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/* system constants.
|
||||||
|
* declared in compiler.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern Term TERM_Function;
|
||||||
|
extern Term TERM_Hidden;
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistsInit (void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistsDone (void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inline candidate */
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
makeTermlist ()
|
||||||
|
{
|
||||||
|
return (Termlist) memAlloc (sizeof (struct termlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistDuplicate
|
||||||
|
|
||||||
|
A deep copy.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistDuplicate (Termlist tl)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
|
||||||
|
if (tl == NULL)
|
||||||
|
return NULL;
|
||||||
|
newtl = makeTermlist ();
|
||||||
|
newtl->term = termDuplicate (tl->term);
|
||||||
|
newtl->prev = NULL;
|
||||||
|
newtl->next = termlistDuplicate (tl->next);
|
||||||
|
if (newtl->next != NULL)
|
||||||
|
(newtl->next)->prev = newtl;
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistShallow
|
||||||
|
|
||||||
|
A shallow copy, because I gather we won't be modifying any terms, only
|
||||||
|
termlists. Oh, and it reverses the order :) Don't forget!
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistShallow (Termlist tl)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
|
||||||
|
newtl = NULL;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
newtl = termlistAdd (newtl, tl->term);
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistDelete
|
||||||
|
|
||||||
|
(shallow)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistDelete (Termlist tl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
return;
|
||||||
|
termlistDelete (tl->next);
|
||||||
|
memFree (tl, sizeof (struct termlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistDestroy
|
||||||
|
|
||||||
|
(deep)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistDestroy (Termlist tl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
return;
|
||||||
|
termlistDestroy (tl->next);
|
||||||
|
termDelete (tl->term);
|
||||||
|
memFree (tl, sizeof (struct termlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
inTermlist
|
||||||
|
|
||||||
|
check whether a term occurs in a termlist
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
inTermlist (Termlist tl, Term term)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isTermEqual (tl->term, term))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return inTermlist (tl->next, term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* are all elements of list 1 in list 2, and vice versa?
|
||||||
|
Note that we assume unique elements !
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
isTermlistEqual (Termlist tl1, Termlist tl2)
|
||||||
|
{
|
||||||
|
if (termlistLength (tl1) != termlistLength (tl2))
|
||||||
|
return 0;
|
||||||
|
while (tl2 != NULL)
|
||||||
|
{
|
||||||
|
if (!inTermlist (tl1, tl2->term))
|
||||||
|
return 0;
|
||||||
|
tl2 = tl2->next;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistAdd
|
||||||
|
|
||||||
|
Adds a term. Duplicates are allowed.
|
||||||
|
A new list pointer is returned.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAdd (Termlist tl, Term term)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
|
||||||
|
newtl = makeTermlist ();
|
||||||
|
newtl->term = term;
|
||||||
|
newtl->next = tl;
|
||||||
|
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
newtl->prev = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newtl->prev = tl->prev;
|
||||||
|
if (newtl->prev != NULL)
|
||||||
|
(newtl->prev)->next = newtl;
|
||||||
|
tl->prev = newtl;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistAppend
|
||||||
|
|
||||||
|
Appends a term to the end of the list. Duplicates are allowed.
|
||||||
|
A new list pointer is returned.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAppend (const Termlist tl, const Term term)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
Termlist scantl;
|
||||||
|
|
||||||
|
newtl = makeTermlist ();
|
||||||
|
newtl->term = term;
|
||||||
|
newtl->next = NULL;
|
||||||
|
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
newtl->prev = NULL;
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scantl = tl;
|
||||||
|
while (scantl->next != NULL)
|
||||||
|
scantl = scantl->next;
|
||||||
|
scantl->next = newtl;
|
||||||
|
newtl->prev = scantl;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistConcat (Termlist tl1, Termlist tl2)
|
||||||
|
{
|
||||||
|
if (tl1 == NULL)
|
||||||
|
return tl2;
|
||||||
|
if (tl2 == NULL)
|
||||||
|
return tl1;
|
||||||
|
|
||||||
|
Termlist scan = tl1;
|
||||||
|
while (scan->next != NULL)
|
||||||
|
scan = scan->next;
|
||||||
|
scan->next = tl2;
|
||||||
|
return tl1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termlistDelTerm
|
||||||
|
|
||||||
|
remove the current element from the termlist. Easier because of the
|
||||||
|
double linked list.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Termlist
|
||||||
|
termlistDelTerm (Termlist tl)
|
||||||
|
{
|
||||||
|
Termlist newhead;
|
||||||
|
|
||||||
|
if (tl == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (tl->prev != NULL)
|
||||||
|
{
|
||||||
|
(tl->prev)->next = tl->next;
|
||||||
|
newhead = tl->prev;
|
||||||
|
while (newhead->prev != NULL)
|
||||||
|
newhead = newhead->prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newhead = tl->next;
|
||||||
|
}
|
||||||
|
if (tl->next != NULL)
|
||||||
|
(tl->next)->prev = tl->prev;
|
||||||
|
memFree (tl, sizeof (struct termlist));
|
||||||
|
return newhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistConjunct (Termlist tl1, Termlist tl2)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
Termlist scan;
|
||||||
|
|
||||||
|
scan = tl1;
|
||||||
|
newtl = NULL;
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
if (inTermlist (tl2, scan->term))
|
||||||
|
newtl = termlistAdd (newtl, scan->term);
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistConjunctType (Termlist tl1, Termlist tl2, int termtype)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
Termlist scan;
|
||||||
|
|
||||||
|
scan = tl1;
|
||||||
|
newtl = NULL;
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
if (((scan->term)->type == termtype) && (inTermlist (tl2, scan->term)))
|
||||||
|
newtl = termlistAdd (newtl, scan->term);
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistType (Termlist tl, int termtype)
|
||||||
|
{
|
||||||
|
Termlist newtl;
|
||||||
|
Termlist scan;
|
||||||
|
|
||||||
|
scan = tl;
|
||||||
|
newtl = NULL;
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
if ((scan->term)->type == termtype)
|
||||||
|
newtl = termlistAdd (newtl, scan->term);
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
termlistPrint (Termlist tl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
printf ("[Empty]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf ("[");
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
termPrint (tl->term);
|
||||||
|
tl = tl->next;
|
||||||
|
if (tl != NULL)
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
printf ("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAddVariables (Termlist tl, Term t)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
return tl;
|
||||||
|
|
||||||
|
t = deVar (t);
|
||||||
|
if (isTermLeaf (t))
|
||||||
|
{
|
||||||
|
if (isTermVariable (t) && !inTermlist (tl, t))
|
||||||
|
return termlistAdd (tl, t);
|
||||||
|
else
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isTermEncrypt (t))
|
||||||
|
return termlistAddVariables (termlistAddVariables (tl, t->op),
|
||||||
|
t->key);
|
||||||
|
else
|
||||||
|
return
|
||||||
|
termlistAddVariables (termlistAddVariables (tl, t->op1), t->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAddRealVariables (Termlist tl, Term t)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
return tl;
|
||||||
|
|
||||||
|
if (realTermLeaf (t))
|
||||||
|
{
|
||||||
|
if (realTermVariable (t))
|
||||||
|
{
|
||||||
|
Term tbuf = t->subst;
|
||||||
|
t->subst = NULL;
|
||||||
|
if (!inTermlist (tl,t))
|
||||||
|
{
|
||||||
|
tl = termlistAdd (tl,t);
|
||||||
|
}
|
||||||
|
t->subst = tbuf;
|
||||||
|
return termlistAddRealVariables (tl,t->subst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (realTermEncrypt (t))
|
||||||
|
return termlistAddVariables (termlistAddVariables (tl, t->op),
|
||||||
|
t->key);
|
||||||
|
else
|
||||||
|
return
|
||||||
|
termlistAddVariables (termlistAddVariables (tl, t->op1), t->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAddBasic (Termlist tl, Term t)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
return tl;
|
||||||
|
if (!isTermLeaf (t))
|
||||||
|
{
|
||||||
|
if (isTermEncrypt (t))
|
||||||
|
return termlistAddBasic (termlistAddBasic (tl, t->op), t->key);
|
||||||
|
else
|
||||||
|
return termlistAddBasic (termlistAddBasic (tl, t->op1), t->op2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!inTermlist (tl, t))
|
||||||
|
{
|
||||||
|
return termlistAdd (tl, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistAddBasics (Termlist tl, Termlist scan)
|
||||||
|
{
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
tl = termlistAddBasic (tl, scan->term);
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* termlistMinusTerm
|
||||||
|
*
|
||||||
|
* Remove a term from a termlist, and yield a new termlist pointer.
|
||||||
|
* Semantics: remove the first occurrence of the term.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistMinusTerm (Termlist tl, Term t)
|
||||||
|
{
|
||||||
|
Termlist scan;
|
||||||
|
|
||||||
|
scan = tl;
|
||||||
|
while (scan != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual (scan->term, t))
|
||||||
|
return termlistDelTerm (scan);
|
||||||
|
else
|
||||||
|
scan = scan->next;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
termlistLength (Termlist tl)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
tl = tl->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
inverseKey
|
||||||
|
|
||||||
|
Gives the inverse Key of some term (which is used to encrypt something), as is defined
|
||||||
|
by the termlist, which is a list of key1,key1inv, key2, key2inv, etc...
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Term
|
||||||
|
inverseKey (Termlist inverses, Term key)
|
||||||
|
{
|
||||||
|
key = deVar (key);
|
||||||
|
|
||||||
|
/* is this a function application? i.e. hash? */
|
||||||
|
if (isTermLeaf (key) && inTermlist (key->stype, TERM_Function))
|
||||||
|
{
|
||||||
|
/* functions cannot be inverted by default */
|
||||||
|
return termDuplicate (TERM_Hidden);
|
||||||
|
}
|
||||||
|
/* check for the special case first: when it is effectively a function application */
|
||||||
|
if (isTermEncrypt (key) && isTermLeaf (key->key)
|
||||||
|
&& inTermlist (deVar (key->key)->stype, TERM_Function))
|
||||||
|
{
|
||||||
|
/* we are scanning for functions */
|
||||||
|
/* scan the list */
|
||||||
|
/* key is function application kk(op), or {op}kk */
|
||||||
|
Term funKey (Term orig, Term newk)
|
||||||
|
{
|
||||||
|
/* in: {op}kk, nk
|
||||||
|
* out: {op'}nk */
|
||||||
|
return makeTermEncrypt (termDuplicate (orig->op),
|
||||||
|
termDuplicate (newk));
|
||||||
|
}
|
||||||
|
while (inverses != NULL && inverses->next != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (isTermEqual (key->key, inverses->term))
|
||||||
|
return funKey (key, inverses->next->term);
|
||||||
|
if (isTermEqual (key->key, inverses->next->term))
|
||||||
|
return funKey (key, inverses->term);
|
||||||
|
inverses = inverses->next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* scanning for a direct inverse */
|
||||||
|
|
||||||
|
/* scan the list */
|
||||||
|
while (inverses != NULL && inverses->next != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual (key, inverses->term))
|
||||||
|
return termDuplicate (inverses->next->term);
|
||||||
|
if (isTermEqual (key, inverses->next->term))
|
||||||
|
return termDuplicate (inverses->term);
|
||||||
|
inverses = inverses->next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return termDuplicate (key); /* defaults to symmetrical */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* localTerm
|
||||||
|
*
|
||||||
|
* Creates a term local to a run.
|
||||||
|
* We assume that at this point, no variables have been instantiated yet that occur in this term.
|
||||||
|
* We also assume that fromlist, tolist and locals only hold real leaves.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termLocal (const Term t, Termlist fromlist, Termlist tolist,
|
||||||
|
const Termlist locals, const int runid)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (realTermLeaf (t))
|
||||||
|
{
|
||||||
|
while (fromlist != NULL && tolist != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual (fromlist->term, t))
|
||||||
|
{
|
||||||
|
// matches!
|
||||||
|
return tolist->term;
|
||||||
|
}
|
||||||
|
fromlist = fromlist->next;
|
||||||
|
tolist = tolist->next;
|
||||||
|
}
|
||||||
|
if (inTermlist (locals, t))
|
||||||
|
{
|
||||||
|
// return termRunid(t,runid);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Term newt = termDuplicate (t);
|
||||||
|
if (realTermTuple (t))
|
||||||
|
{
|
||||||
|
newt->op1 = termLocal (t->op1, fromlist, tolist, locals, runid);
|
||||||
|
newt->op2 = termLocal (t->op2, fromlist, tolist, locals, runid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newt->op = termLocal (t->op, fromlist, tolist, locals, runid);
|
||||||
|
newt->key = termLocal (t->key, fromlist, tolist, locals, runid);
|
||||||
|
}
|
||||||
|
return newt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* termlistLocal
|
||||||
|
*
|
||||||
|
* We expand the previous concept to termlists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistLocal (Termlist tl, const Termlist fromlist, const Termlist tolist,
|
||||||
|
const Termlist locals, int runid)
|
||||||
|
{
|
||||||
|
Termlist newtl = NULL;
|
||||||
|
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
newtl =
|
||||||
|
termlistAdd (newtl,
|
||||||
|
termLocal (tl->term, fromlist, tolist, locals, runid));
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return newtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether tl2 is contained in tl1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
termlistContained (const Termlist tlbig, Termlist tlsmall)
|
||||||
|
{
|
||||||
|
while (tlsmall != NULL)
|
||||||
|
{
|
||||||
|
if (!inTermlist (tlbig, tlsmall->term))
|
||||||
|
return 0;
|
||||||
|
tlsmall = tlsmall->next;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine whether a variable has been substituted with something with
|
||||||
|
* the right type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
validSubst (const int matchmode, const Term term)
|
||||||
|
{
|
||||||
|
if (!realTermVariable (term) || term->subst == NULL)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (matchmode)
|
||||||
|
{
|
||||||
|
case 0: /* real type match */
|
||||||
|
return realTermLeaf (term->subst)
|
||||||
|
&& termlistContained (term->stype, term->subst->stype);
|
||||||
|
case 1: /* basic type match */
|
||||||
|
/* subst must be a leaf */
|
||||||
|
/* TODO: what about functions? */
|
||||||
|
return realTermLeaf (term->subst);
|
||||||
|
case 2: /* no type match */
|
||||||
|
/* anything goes */
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* termFunction
|
||||||
|
*
|
||||||
|
* An assist function that helps to simulate Term->Term functions, using
|
||||||
|
* termlists. One termlist functions as the domain, and the other as the
|
||||||
|
* range.
|
||||||
|
*
|
||||||
|
* Extending a function with a value y = f(x) amounts to extending the
|
||||||
|
* domain with x, and the range with y.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termFunction (Termlist fromlist, Termlist tolist, Term tx)
|
||||||
|
{
|
||||||
|
while (fromlist != NULL && tolist != NULL)
|
||||||
|
{
|
||||||
|
if (isTermEqual (fromlist->term, tx))
|
||||||
|
{
|
||||||
|
return tolist->term;
|
||||||
|
}
|
||||||
|
fromlist = fromlist->next;
|
||||||
|
tolist = tolist->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward the termlist pointer to the last item
|
||||||
|
*/
|
||||||
|
|
||||||
|
Termlist
|
||||||
|
termlistForward (Termlist tl)
|
||||||
|
{
|
||||||
|
if (tl == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (tl->next != NULL)
|
||||||
|
{
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
48
src/termlists.h
Normal file
48
src/termlists.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef TERMLISTS
|
||||||
|
#define TERMLISTS
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
|
||||||
|
struct termlist
|
||||||
|
{
|
||||||
|
Term term;
|
||||||
|
struct termlist *next;
|
||||||
|
struct termlist *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct termlist *Termlist;
|
||||||
|
|
||||||
|
void termlistsInit (void);
|
||||||
|
void termlistsDone (void);
|
||||||
|
Termlist termlistDuplicate (Termlist tl);
|
||||||
|
Termlist termlistShallow (Termlist tl);
|
||||||
|
void termlistDelete (Termlist tl);
|
||||||
|
void termlistDestroy (Termlist tl);
|
||||||
|
void termlistPrint (Termlist tl);
|
||||||
|
int inTermlist (Termlist tl, Term term);
|
||||||
|
int isTermlistEqual (Termlist tl1, Termlist tl2);
|
||||||
|
Termlist termlistAdd (Termlist tl, Term term);
|
||||||
|
Termlist termlistAppend (const Termlist tl, const Term term);
|
||||||
|
Termlist termlistConcat (Termlist tl1, Termlist tl2);
|
||||||
|
Termlist termlistDelTerm (Termlist tl);
|
||||||
|
Termlist termlistConjunct (Termlist tl1, Termlist tl2);
|
||||||
|
Termlist termlistConjunctType (Termlist tl1, Termlist tl2, int termtype);
|
||||||
|
Termlist termlistType (Termlist tl, int termtype);
|
||||||
|
Termlist termlistAddVariables (Termlist tl, Term t);
|
||||||
|
Termlist termlistAddRealVariables (Termlist tl, Term t);
|
||||||
|
Termlist termlistAddBasic (Termlist tl, Term t);
|
||||||
|
Termlist termlistAddBasics (Termlist tl, Termlist scan);
|
||||||
|
Termlist termlistMinusTerm (Termlist tl, Term t);
|
||||||
|
int termlistLength (Termlist tl);
|
||||||
|
Term inverseKey (Termlist inverses, Term key);
|
||||||
|
Term termLocal (const Term t, Termlist fromlist, Termlist tolist,
|
||||||
|
const Termlist locals, const int runid);
|
||||||
|
Termlist termlistLocal (Termlist tl, const Termlist fromlist,
|
||||||
|
const Termlist tolist, const Termlist locals,
|
||||||
|
const int runid);
|
||||||
|
int termlistContained (const Termlist tlbig, Termlist tlsmall);
|
||||||
|
int validSubst (const int matchmode, const Term term);
|
||||||
|
Term termFunction (Termlist fromlist, Termlist tolist, Term tx);
|
||||||
|
Termlist termlistForward (Termlist tl);
|
||||||
|
|
||||||
|
#endif
|
680
src/terms.c
Normal file
680
src/terms.c
Normal file
@ -0,0 +1,680 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "terms.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "ctype.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* external definitions */
|
||||||
|
|
||||||
|
extern Term TERM_Function;
|
||||||
|
extern int inTermlist (); // suppresses a warning, but at what cost?
|
||||||
|
extern int globalLatex;
|
||||||
|
|
||||||
|
/* forward declarations */
|
||||||
|
|
||||||
|
void indent (void);
|
||||||
|
|
||||||
|
/* useful macros */
|
||||||
|
|
||||||
|
#define RID_UNDEF MIN_INT
|
||||||
|
/* main code */
|
||||||
|
|
||||||
|
/* Two types of terms: general, and normalized. Normalized rewrites all
|
||||||
|
tuples to (x,(y,z))..NULL form, making list traversal easy. */
|
||||||
|
|
||||||
|
void
|
||||||
|
termsInit (void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
termsDone (void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
makeTerm ()
|
||||||
|
{
|
||||||
|
return (Term) memAlloc (sizeof (struct term));
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
makeTermEncrypt (Term t1, Term t2)
|
||||||
|
{
|
||||||
|
Term term = makeTerm ();
|
||||||
|
term->type = ENCRYPT;
|
||||||
|
term->stype = NULL;
|
||||||
|
term->op = t1;
|
||||||
|
term->key = t2;
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
makeTermTuple (Term t1, Term t2)
|
||||||
|
{
|
||||||
|
if (t1 == NULL)
|
||||||
|
{
|
||||||
|
if (t2 == NULL)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug (5, "Trying to make a tuple node with an empty term.");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
if (t2 == NULL)
|
||||||
|
{
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term tt = makeTerm ();
|
||||||
|
tt->type = TUPLE;
|
||||||
|
tt->stype = NULL;
|
||||||
|
tt->op1 = t1;
|
||||||
|
tt->op2 = t2;
|
||||||
|
return tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Term
|
||||||
|
makeTermType (const int type, const Symbol symb, const int runid)
|
||||||
|
{
|
||||||
|
Term term = makeTerm ();
|
||||||
|
term->type = type;
|
||||||
|
term->stype = NULL;
|
||||||
|
term->subst = NULL;
|
||||||
|
term->symb = symb;
|
||||||
|
term->runid = runid;
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* deVar unwraps any substitutions.
|
||||||
|
*
|
||||||
|
* For speed, it is a macro. Sometimes it will call
|
||||||
|
* deVarScan to do the actual unwinding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
deVarScan (Term t)
|
||||||
|
{
|
||||||
|
while (realTermVariable (t) && t->subst != NULL)
|
||||||
|
t = t->subst;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hasTermVariable (Term term)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
return 0;
|
||||||
|
term = deVar (term);
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
return realTermVariable (term);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (realTermTuple (term))
|
||||||
|
return (hasTermVariable (term->op1) || hasTermVariable (term->op2));
|
||||||
|
else
|
||||||
|
return (hasTermVariable (term->op) || hasTermVariable (term->key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
isTermEqualFn(term,term)
|
||||||
|
|
||||||
|
Tests whether two terms are completely identical. This also includes
|
||||||
|
variables. This is the recursive function.
|
||||||
|
|
||||||
|
We assume the term is normalized, e.g. no tupling has direct
|
||||||
|
subtupling.
|
||||||
|
|
||||||
|
Out: 0 unequal, 1 equal
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
isTermEqualFn (Term term1, Term term2)
|
||||||
|
{
|
||||||
|
term1 = deVar (term1);
|
||||||
|
term2 = deVar (term2);
|
||||||
|
|
||||||
|
if (term1 == term2)
|
||||||
|
return 1;
|
||||||
|
if ((term1 == NULL) || (term2 == NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (term1->type != term2->type)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (realTermLeaf (term1))
|
||||||
|
{
|
||||||
|
return (term1->symb == term2->symb && term1->runid == term2->runid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* ENCRYPT or TUPLE */
|
||||||
|
|
||||||
|
if (realTermEncrypt (term1))
|
||||||
|
{
|
||||||
|
/* for optimization of encryption equality, we compare
|
||||||
|
operator 2 first (we expect it to be a smaller term)
|
||||||
|
*/
|
||||||
|
return (isTermEqualFn (term1->key, term2->key) &&
|
||||||
|
isTermEqualFn (term1->op, term2->op));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* tuple */
|
||||||
|
|
||||||
|
return (isTermEqualFn (term1->op1, term2->op1) &&
|
||||||
|
isTermEqualFn (term1->op2, term2->op2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
termOccurs (Term t, Term tsub)
|
||||||
|
{
|
||||||
|
t = deVar (t);
|
||||||
|
tsub = deVar (tsub);
|
||||||
|
|
||||||
|
if (isTermEqual (t, tsub))
|
||||||
|
return 1;
|
||||||
|
if (realTermLeaf (t))
|
||||||
|
return 0;
|
||||||
|
if (realTermTuple (t))
|
||||||
|
return (termOccurs (t->op1, tsub) || termOccurs (t->op2, tsub));
|
||||||
|
else
|
||||||
|
return (termOccurs (t->op, tsub) || termOccurs (t->key, tsub));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
termPrint (Term term)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
{
|
||||||
|
printf ("Empty term");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!DEBUGL (1))
|
||||||
|
{
|
||||||
|
term = deVar (term);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
term = deVar (term);
|
||||||
|
#endif
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
{
|
||||||
|
symbolPrint (term->symb);
|
||||||
|
if (realTermVariable (term))
|
||||||
|
printf ("V");
|
||||||
|
if (term->runid >= 0)
|
||||||
|
{
|
||||||
|
if (globalLatex)
|
||||||
|
printf ("\\sharp%i", term->runid);
|
||||||
|
else
|
||||||
|
printf ("#%i", term->runid);
|
||||||
|
}
|
||||||
|
if (term->subst != NULL)
|
||||||
|
{
|
||||||
|
if (globalLatex)
|
||||||
|
printf ("\\rightarrow");
|
||||||
|
else
|
||||||
|
printf ("->");
|
||||||
|
termPrint (term->subst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (realTermTuple (term))
|
||||||
|
{
|
||||||
|
printf ("(");
|
||||||
|
while (realTermTuple (term))
|
||||||
|
{
|
||||||
|
termPrint (term->op1);
|
||||||
|
printf (",");
|
||||||
|
term = term->op2;
|
||||||
|
if (!realTermTuple (term))
|
||||||
|
termPrint (term);
|
||||||
|
|
||||||
|
}
|
||||||
|
printf (")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
if (isTermLeaf (term->key)
|
||||||
|
&& inTermlist (term->key->stype, TERM_Function))
|
||||||
|
{
|
||||||
|
/* function application */
|
||||||
|
termPrint (term->key);
|
||||||
|
printf ("(");
|
||||||
|
termPrint (term->op);
|
||||||
|
printf (")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* normal encryption */
|
||||||
|
if (globalLatex)
|
||||||
|
{
|
||||||
|
printf ("\\{");
|
||||||
|
termPrint (term->op);
|
||||||
|
printf ("\\}_{");
|
||||||
|
termPrint (term->key);
|
||||||
|
printf ("}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("{");
|
||||||
|
termPrint (term->op);
|
||||||
|
printf ("}");
|
||||||
|
termPrint (term->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Duplicate
|
||||||
|
|
||||||
|
make a deep copy of a term, but not of leaves.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termDuplicate (const Term term)
|
||||||
|
{
|
||||||
|
Term newterm;
|
||||||
|
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
return term;
|
||||||
|
|
||||||
|
newterm = (Term) memAlloc (sizeof (struct term));
|
||||||
|
newterm->type = term->type;
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
newterm->op = termDuplicate (term->op);
|
||||||
|
newterm->key = termDuplicate (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->op1 = termDuplicate (term->op1);
|
||||||
|
newterm->op2 = termDuplicate (term->op2);
|
||||||
|
}
|
||||||
|
return newterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
DuplicateDeep
|
||||||
|
|
||||||
|
make a deep copy of a term, and also of leaves.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termDuplicateDeep (const Term term)
|
||||||
|
{
|
||||||
|
Term newterm;
|
||||||
|
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
newterm = (Term) memAlloc (sizeof (struct term));
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
{
|
||||||
|
memcpy (newterm, term, sizeof (struct term));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->type = term->type;
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
newterm->op = termDuplicateDeep (term->op);
|
||||||
|
newterm->key = termDuplicateDeep (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->op1 = termDuplicateDeep (term->op1);
|
||||||
|
newterm->op2 = termDuplicateDeep (term->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DuplicateUV
|
||||||
|
*
|
||||||
|
* Remove all instantiated variables on the way down.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
termDuplicateUV (Term term)
|
||||||
|
{
|
||||||
|
Term newterm;
|
||||||
|
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
term = deVar (term);
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
return term;
|
||||||
|
|
||||||
|
newterm = (Term) memAlloc (sizeof (struct term));
|
||||||
|
newterm->type = term->type;
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
newterm->op = termDuplicateUV (term->op);
|
||||||
|
newterm->key = termDuplicateUV (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->op1 = termDuplicateUV (term->op1);
|
||||||
|
newterm->op2 = termDuplicateUV (term->op2);
|
||||||
|
}
|
||||||
|
return newterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
realTermDuplicate
|
||||||
|
|
||||||
|
make a deep copy of a term, also of leaves.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Term
|
||||||
|
realTermDuplicate (const Term term)
|
||||||
|
{
|
||||||
|
Term newterm;
|
||||||
|
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
newterm = (Term) memAlloc (sizeof (struct term));
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
{
|
||||||
|
memcpy (newterm, term, sizeof (struct term));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->type = term->type;
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
newterm->op = realTermDuplicate (term->op);
|
||||||
|
newterm->key = realTermDuplicate (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newterm->op1 = realTermDuplicate (term->op1);
|
||||||
|
newterm->op2 = realTermDuplicate (term->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newterm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
termDelete
|
||||||
|
|
||||||
|
Removes a term and deallocates memory
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
termDelete (const Term term)
|
||||||
|
{
|
||||||
|
if (term != NULL && !realTermLeaf (term))
|
||||||
|
{
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
termDelete (term->op);
|
||||||
|
termDelete (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
termDelete (term->op1);
|
||||||
|
termDelete (term->op2);
|
||||||
|
}
|
||||||
|
memFree (term, sizeof (struct term));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
termNormalize
|
||||||
|
|
||||||
|
avoids problems with associativity by rewriting every ((x,y),z) to
|
||||||
|
(x,y,z)), i.e. a normal form for terms, after which equality is
|
||||||
|
okay.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
termNormalize (Term term)
|
||||||
|
{
|
||||||
|
term = deVar (term);
|
||||||
|
if (term == NULL || realTermLeaf (term))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
termNormalize (term->op);
|
||||||
|
termNormalize (term->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* normalize left hand first,both for tupling and for
|
||||||
|
encryption */
|
||||||
|
termNormalize (term->op1);
|
||||||
|
/* check for ((x,y),z) construct */
|
||||||
|
if (realTermTuple (term->op1))
|
||||||
|
{
|
||||||
|
/* temporarily store the old terms */
|
||||||
|
Term tx = (term->op1)->op1;
|
||||||
|
Term ty = (term->op1)->op2;
|
||||||
|
Term tz = term->op2;
|
||||||
|
/* move node */
|
||||||
|
term->op2 = term->op1;
|
||||||
|
/* construct (x,(y,z)) version */
|
||||||
|
term->op1 = tx;
|
||||||
|
(term->op2)->op1 = ty;
|
||||||
|
(term->op2)->op2 = tz;
|
||||||
|
}
|
||||||
|
termNormalize (term->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Term
|
||||||
|
termRunid (Term term, int runid)
|
||||||
|
{
|
||||||
|
if (term == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (realTermLeaf (term))
|
||||||
|
{
|
||||||
|
/* leaf */
|
||||||
|
if (term->runid == runid)
|
||||||
|
return term;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Term newt = termDuplicate (term);
|
||||||
|
newt->runid = runid;
|
||||||
|
return newt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* anything else, recurse */
|
||||||
|
if (realTermEncrypt (term))
|
||||||
|
{
|
||||||
|
return makeTermEncrypt (termRunid (term->op, runid),
|
||||||
|
termRunid (term->key, runid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return makeTermTuple (termRunid (term->op1, runid),
|
||||||
|
termRunid (term->op2, runid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tupleCount yields the size of the top tuple in the term */
|
||||||
|
|
||||||
|
int
|
||||||
|
tupleCount (Term tt)
|
||||||
|
{
|
||||||
|
if (tt == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deVar (tt);
|
||||||
|
if (!realTermTuple (tt))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (tupleCount (tt->op1) + tupleCount (tt->op2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tupleProject yields the projection pi (0 .. n-1) on a top tuple. Returns
|
||||||
|
* NULL if the range is incorrect. */
|
||||||
|
|
||||||
|
Term
|
||||||
|
tupleProject (Term tt, int n)
|
||||||
|
{
|
||||||
|
if (tt == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
deVar (tt);
|
||||||
|
if (!realTermTuple (tt))
|
||||||
|
{
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
/* no tuple, adressing error */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no tuple */
|
||||||
|
return tt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* there is a tuple to traverse */
|
||||||
|
int left = tupleCount (tt->op1);
|
||||||
|
if (n >= left)
|
||||||
|
{
|
||||||
|
/* it's in the right hand side */
|
||||||
|
return tupleProject (tt->op2, n - left);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* left hand side */
|
||||||
|
return tupleProject (tt->op1, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* number of elements in a term.
|
||||||
|
*
|
||||||
|
* Currently, the encryption operator is weighed as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
termSize(Term t)
|
||||||
|
{
|
||||||
|
if (t == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = deVar(t);
|
||||||
|
if (realTermLeaf(t))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (realTermEncrypt(t))
|
||||||
|
{
|
||||||
|
return 1 + termSize(t->op) + termSize(t->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return termSize(t->op1) + termSize(t->op2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yield some sort of distance between two terms, as a float between 0 and 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
float
|
||||||
|
termDistance(Term t1, Term t2)
|
||||||
|
{
|
||||||
|
/* First the special cases: no equal subterms, completely equal */
|
||||||
|
if (isTermEqual(t1,t2))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
t1 = deVar(t1);
|
||||||
|
t2 = deVar(t2);
|
||||||
|
|
||||||
|
int t1s = termSize(t1);
|
||||||
|
int t2s = termSize(t2);
|
||||||
|
|
||||||
|
if (t1 == NULL || t2 == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (t1->type != t2->type)
|
||||||
|
{
|
||||||
|
/* unequal type, maybe one is a subterm of the other? */
|
||||||
|
if (t1s > t2s && termOccurs(t1,t2))
|
||||||
|
{
|
||||||
|
return (float) t2s / t1s;
|
||||||
|
}
|
||||||
|
if (t2s > t1s && termOccurs(t2,t1))
|
||||||
|
{
|
||||||
|
return (float) t1s / t2s;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* equal types */
|
||||||
|
if (isTermLeaf(t1))
|
||||||
|
{
|
||||||
|
/* we had established before that they are not equal */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* non-leaf recurse */
|
||||||
|
if (isTermEncrypt(t1))
|
||||||
|
{
|
||||||
|
/* encryption */
|
||||||
|
return (termDistance(t1->op, t2->op) + termDistance(t1->key, t2->key)) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (termDistance(t1->op1, t2->op1) + termDistance(t1->op2, t2->op2)) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
src/terms.h
Normal file
93
src/terms.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#ifndef TERMS
|
||||||
|
#define TERMS
|
||||||
|
|
||||||
|
#include "symbols.h"
|
||||||
|
|
||||||
|
#define GLOBAL 1
|
||||||
|
#define VARIABLE 2
|
||||||
|
#define LEAF 3 // type <= LEAF means it's a leaf, nkay?
|
||||||
|
#define ENCRYPT 4
|
||||||
|
#define TUPLE 5
|
||||||
|
|
||||||
|
struct term
|
||||||
|
{
|
||||||
|
/* basic : name,runid
|
||||||
|
encrypt: op,key
|
||||||
|
tuple : op,next
|
||||||
|
*/
|
||||||
|
int type;
|
||||||
|
void *stype; // only for leaf, termlist pointer
|
||||||
|
struct term *subst; // only for variable/leaf, substitution term
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Symbol symb;
|
||||||
|
struct term *op;
|
||||||
|
struct term *op1;
|
||||||
|
struct term *next; // for alternative memory management
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int runid;
|
||||||
|
struct term *key;
|
||||||
|
struct term *op2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct term *Term;
|
||||||
|
|
||||||
|
void termsInit (void);
|
||||||
|
void termsDone (void);
|
||||||
|
Term makeTermEncrypt (Term t1, Term t2);
|
||||||
|
Term makeTermTuple (Term t1, Term t2);
|
||||||
|
Term makeTermType (const int type, const Symbol symb, const int runid);
|
||||||
|
Term deVarScan (Term t);
|
||||||
|
#define substVar(t) ((t != NULL && t->type == VARIABLE && t->subst != NULL) ? 1 : 0)
|
||||||
|
#define deVar(t) ( substVar(t) ? deVarScan(t->subst) : t)
|
||||||
|
#define realTermLeaf(t) (t != NULL && t->type <= LEAF)
|
||||||
|
#define realTermTuple(t) (t != NULL && t->type == TUPLE)
|
||||||
|
#define realTermEncrypt(t) (t != NULL && t->type == ENCRYPT)
|
||||||
|
#define realTermVariable(t) (t != NULL && t->type == VARIABLE)
|
||||||
|
#define isTermLeaf(t) realTermLeaf(deVar(t))
|
||||||
|
#define isTermTuple(t) realTermTuple(deVar(t))
|
||||||
|
#define isTermEncrypt(t) realTermEncrypt(deVar(t))
|
||||||
|
#define isTermVariable(t) realTermVariable(deVar(t))
|
||||||
|
#define isTermEqual(t1,t2) ((substVar(t1) || substVar(t2)) \
|
||||||
|
? isTermEqualFn(t1,t2) \
|
||||||
|
: ( \
|
||||||
|
(t1 == t2) \
|
||||||
|
? 1 \
|
||||||
|
: ( \
|
||||||
|
(t1 == NULL || t2 == NULL || t1->type != t2->type) \
|
||||||
|
? 0 \
|
||||||
|
: ( \
|
||||||
|
realTermLeaf(t1) \
|
||||||
|
? (t1->symb == t2->symb && t1->runid == t2->runid) \
|
||||||
|
: ( \
|
||||||
|
realTermEncrypt(t2) \
|
||||||
|
? (isTermEqualFn(t1->key, t2->key) && \
|
||||||
|
isTermEqualFn(t1->op, t2->op)) \
|
||||||
|
: (isTermEqualFn(t1->op1, t2->op1) && \
|
||||||
|
isTermEqualFn(t1->op2, t2->op2)) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
int hasTermVariable (Term term);
|
||||||
|
int isTermEqualFn (Term term1, Term term2);
|
||||||
|
int termOccurs (Term t, Term tsub);
|
||||||
|
void termPrint (Term term);
|
||||||
|
Term termDuplicate (const Term term);
|
||||||
|
Term termDuplicateDeep (const Term term);
|
||||||
|
Term termDuplicateUV (Term term);
|
||||||
|
void termDelete (const Term term);
|
||||||
|
void termNormalize (Term term);
|
||||||
|
Term termRunid (Term term, int runid);
|
||||||
|
int tupleCount (Term tt);
|
||||||
|
Term tupleProject (Term tt, int n);
|
||||||
|
int termSize(Term t);
|
||||||
|
float termDistance(Term t1, Term t2);
|
||||||
|
|
||||||
|
#endif
|
22
src/testl
Executable file
22
src/testl
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Shell script to display the latex output relatively quickly. For
|
||||||
|
# internal testing only, as it depends on the spdl subdirectory.
|
||||||
|
#
|
||||||
|
# Usage example:
|
||||||
|
#
|
||||||
|
# ./testl ns3
|
||||||
|
#
|
||||||
|
|
||||||
|
file=spdl/$1.spdl outfile=tempattack
|
||||||
|
|
||||||
|
if [ -f $file ]
|
||||||
|
then
|
||||||
|
./scyther --latex <$file >$outfile.tex
|
||||||
|
latex $outfile.tex
|
||||||
|
xdvi $outfile.dvi
|
||||||
|
else
|
||||||
|
echo "No file $file found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
80
src/todo.txt
Normal file
80
src/todo.txt
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
- Remove stupid preamble postamble stuff, or maybe integrate this behaviour
|
||||||
|
into some switch, where default would be a standalone latex file, and
|
||||||
|
another option would generate a file that can be included.
|
||||||
|
- Variables have to be 'saved' and 'stored' into some structure. However, for
|
||||||
|
this we need a global list of all variables, which is not available at the
|
||||||
|
moment. The compiler and run instantiator should maintain such a list, and
|
||||||
|
then we could save it into a struct with three lists. (from,to,empty)
|
||||||
|
This will need a sys allVariables list.
|
||||||
|
- Timer output is broken for values e.g. above an hour. Fix or remove
|
||||||
|
altogether.
|
||||||
|
- ns3 doesn't even reach a claim in --cl and -t8. Check.
|
||||||
|
- in Runs.c, revise 'untrustedAgent' to cope with some weird exceptions.
|
||||||
|
- CLP: variables in keys must be branched: maybe even in three situations
|
||||||
|
(have key and contents, have inverse key and content, nothing)
|
||||||
|
- Implement delayed protocol compiler (on run demand only).
|
||||||
|
- Implement run knowledge, and use this in protocol compiler.
|
||||||
|
- Remove any remaining global variables, if any.
|
||||||
|
- When choosing agents for runs (with an initial read), it does not make
|
||||||
|
sense to choose untrusted agents.
|
||||||
|
- Introduce 'Ticket' default type in the compiler, along with some
|
||||||
|
handling for that.
|
||||||
|
- Make a shell script 'test $filename $commandline'
|
||||||
|
Generates a $test-$date.out and $test-$date.err. Useful for storing
|
||||||
|
test data.
|
||||||
|
- How should claims behave (trusted/untrusted) wrt uninstantiated
|
||||||
|
agents? Branch again? That's what is causing the nsl3-var problem.
|
||||||
|
- The 'choose' operator must always be typed, I think.
|
||||||
|
- Synchronisation test can be expensive, because a good protocol will
|
||||||
|
yield few such tests, and a bad protocol will prune most traces after
|
||||||
|
failure. The performance loss will only be 'felt' when the whole state
|
||||||
|
space is explored (-p0), which is only used for theoretical tests.
|
||||||
|
- The woolam-ce is incorrect because it is illegal to have a variable
|
||||||
|
term in a key that is read, by CMV semantics. I don't know what it
|
||||||
|
means for CE semantics (yet).
|
||||||
|
- Idea: run bla.bla(params) [compromised <localterm> [,<localterm>] ];
|
||||||
|
1. These local terms are given to the intruder. Technically this
|
||||||
|
should only happen _after_ they are first sent in the run. Maybe add
|
||||||
|
this to send semantics: if termOccurs(sendterm, compromisedterm) then
|
||||||
|
add compromisedterm to M, remove compromisedterm from list of terms to
|
||||||
|
compromise.
|
||||||
|
2. All claims in the run are ignored (add untrusted flag to run)
|
||||||
|
Alternative: run x.x(x) untrusted; or just compromised, to give up
|
||||||
|
all constants.
|
||||||
|
Note this is not sufficient yet, because it does not consider any
|
||||||
|
partner runs. Maybe declare a 'compromised' section first; other runs
|
||||||
|
will only activate after these have completed. Note this is much more
|
||||||
|
expensive.
|
||||||
|
- Issue: how do untrusted claims work in the context of an intruder?
|
||||||
|
Claim must be checked if it can be solved such that at least one of
|
||||||
|
the agents is trusted.
|
||||||
|
- Fix the first environment read with a special (hidden) label.
|
||||||
|
1. Hide it or print differently in output.
|
||||||
|
2. Ensure typed matching for it, even when using -m1 switch.
|
||||||
|
- Woolam-ce gives nothing. But then again, it's a wrong impl.
|
||||||
|
- consider option -finline-functions for gcc, test.
|
||||||
|
- Currently, match_basic unrolls substitutions to compare message with
|
||||||
|
the forbidden list, but I don't think that it is required. Test.
|
||||||
|
- -m2 is much better with a lot of variables. Compare this to unfolding
|
||||||
|
of the runs with -t4 -m0/1.
|
||||||
|
- Global/protocol variables should not exist in the current system.
|
||||||
|
- File freopen stuff, instead of this sdtin stuff.
|
||||||
|
- Solve the 'version' issue. How is it defined?
|
||||||
|
- run nsl.initiator(alice, all Agent) constructs?
|
||||||
|
- 'all' would generate the roles with the corresponding type.
|
||||||
|
- or maybe for clarity/complexity control: use 'runs' for constructs
|
||||||
|
with 'all' in it.
|
||||||
|
- Constraints might be a part of a knowledge thing, because with we
|
||||||
|
might now have a number of local knowledge sets, each with their own
|
||||||
|
constraint sets. That doesn't make it easier though :( and will cause
|
||||||
|
some performance loss I suppose. Each local set has to remain
|
||||||
|
solveable as well.
|
||||||
|
- Maybe function application ought to be a different basic term type.
|
||||||
|
- After role construction, msc consistency can be checked.
|
||||||
|
- Make sure module knowledge has an interface instead of reference to
|
||||||
|
internals (i.e. no ref to basic/encr)
|
||||||
|
- Reduce knowledge to a simple term list? That would simplify a number
|
||||||
|
of things, and also allow for easier addition of stuff.
|
||||||
|
- How is % notation handled in Casper?
|
||||||
|
- Vernam encryption?
|
||||||
|
- Count number of illegal injections rejected for statistics.
|
200
src/tracebuf.c
Normal file
200
src/tracebuf.c
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* tracebuf.c
|
||||||
|
*
|
||||||
|
* trace buffer operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "runs.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "tracebuf.h"
|
||||||
|
#include "varbuf.h"
|
||||||
|
|
||||||
|
/* reconstruct the knowledge sequence, -1 if it can be done, event nr of last depending read otherwise.
|
||||||
|
* There is one exception: if it returns tb->length, the required terms are not in the last knowledge
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
tracebufRebuildKnow(struct tracebuf *tb)
|
||||||
|
{
|
||||||
|
Knowledge k;
|
||||||
|
Roledef rd;
|
||||||
|
int i;
|
||||||
|
int flag;
|
||||||
|
Termlist tl;
|
||||||
|
|
||||||
|
if (tb == NULL || tb->length == 0)
|
||||||
|
{
|
||||||
|
/* stupid, but true */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = -1;
|
||||||
|
k = knowledgeDuplicate(tb->know[0]);
|
||||||
|
i = 0;
|
||||||
|
while (i < tb->length)
|
||||||
|
{
|
||||||
|
rd = tb->event[i];
|
||||||
|
if (tb->status[i] != S_RED)
|
||||||
|
{
|
||||||
|
/* simulate execution of the event */
|
||||||
|
switch (rd->type)
|
||||||
|
{
|
||||||
|
case READ:
|
||||||
|
if (!inKnowledge (k, rd->message))
|
||||||
|
{
|
||||||
|
flag = i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEND:
|
||||||
|
knowledgeAddTerm (k, rd->message);
|
||||||
|
break;
|
||||||
|
case CLAIM:
|
||||||
|
/* TODO parse term requirements ? */
|
||||||
|
/* Probably not needed */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Anything else */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* write the new knowledge, overwriting old stuff */
|
||||||
|
knowledgeDelete (tb->know[i+1]);
|
||||||
|
tb->know[i+1] = knowledgeDuplicate (k);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
tl = tb->requiredterms;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (!inKnowledge (k, tl->term))
|
||||||
|
{
|
||||||
|
flag = tb->length;
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
knowledgeDelete(k);
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* traceBufInit
|
||||||
|
*
|
||||||
|
* initializes the trace buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct tracebuf*
|
||||||
|
tracebufInit (void)
|
||||||
|
{
|
||||||
|
struct tracebuf *tb = (struct tracebuf *) memAlloc(sizeof(struct tracebuf));
|
||||||
|
tb->length = 0;
|
||||||
|
tb->reallength = 0;
|
||||||
|
tb->event = NULL;
|
||||||
|
tb->know = NULL;
|
||||||
|
tb->run = NULL;
|
||||||
|
tb->status = NULL;
|
||||||
|
tb->link = NULL;
|
||||||
|
tb->requiredterms = NULL;
|
||||||
|
tb->violatedclaim = 0;
|
||||||
|
tb->variables = NULL;
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tracebufDone (struct tracebuf *tb)
|
||||||
|
{
|
||||||
|
if (tb == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Roledef rd;
|
||||||
|
|
||||||
|
varbufDone (tb->variables);
|
||||||
|
if (tb->length > 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
/* note: knowledge domain is length+1 */
|
||||||
|
knowledgeDelete(tb->know[0]);
|
||||||
|
while (i < tb->length)
|
||||||
|
{
|
||||||
|
rd = tb->event[i];
|
||||||
|
termDelete (rd->from);
|
||||||
|
termDelete (rd->to);
|
||||||
|
termDelete (rd->message);
|
||||||
|
roledefDelete(rd);
|
||||||
|
knowledgeDelete(tb->know[i+1]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memFree(tb->know, (i+1) * sizeof (struct knowledge*));
|
||||||
|
memFree(tb->event, i * sizeof (struct roledef*));
|
||||||
|
memFree(tb->run, i * sizeof(int));
|
||||||
|
memFree(tb->status, i * sizeof(int));
|
||||||
|
memFree(tb->link, i * sizeof(int));
|
||||||
|
}
|
||||||
|
memFree(tb, sizeof(tracebuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tracebuf*
|
||||||
|
tracebufSet (const System sys, int length, int claimev)
|
||||||
|
{
|
||||||
|
struct tracebuf *tb;
|
||||||
|
int i;
|
||||||
|
Roledef rd;
|
||||||
|
|
||||||
|
/* TODO For the constraint logic approach, we would simply insert
|
||||||
|
* any constant from the constraint for a variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tb = tracebufInit();
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
tb->length = length;
|
||||||
|
tb->reallength = length;
|
||||||
|
tb->variables = (Varbuf) varbufInit (sys);
|
||||||
|
tb->event = (Roledef *) memAlloc(length * sizeof(struct roledef*));
|
||||||
|
tb->status = (int *) memAlloc(length * sizeof(int));
|
||||||
|
tb->link = (int *) memAlloc(length * sizeof(int));
|
||||||
|
tb->run = (int *) memAlloc(length * sizeof(int));
|
||||||
|
tb->know = (Knowledge *) memAlloc((length + 1) * sizeof (struct knowledge*));
|
||||||
|
|
||||||
|
/* when duplicating the knowledge, we want to instantiate the variables as well
|
||||||
|
*/
|
||||||
|
|
||||||
|
tb->know[0] = knowledgeSubstDo (sys->traceKnow[0]);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < length)
|
||||||
|
{
|
||||||
|
rd = roledefDuplicate1 (sys->traceEvent[i]);
|
||||||
|
if (rd == NULL)
|
||||||
|
{
|
||||||
|
printf("Empty event in trace at %i of %i?\n",i,length);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make a copy without variables */
|
||||||
|
rd->to = termDuplicateUV (rd->to);
|
||||||
|
rd->from = termDuplicateUV (rd->from);
|
||||||
|
rd->message = termDuplicateUV (rd->message);
|
||||||
|
|
||||||
|
tb->event[i] = rd;
|
||||||
|
tb->link[i] = -1;
|
||||||
|
tb->status[i] = S_UNK;
|
||||||
|
tb->run[i] = sys->traceRun[i];
|
||||||
|
tb->know[i+1] = NULL;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark claim */
|
||||||
|
tb->violatedclaim = claimev;
|
||||||
|
tb->status[claimev] = S_OKE;
|
||||||
|
tracebufRebuildKnow (tb);
|
||||||
|
return tb;
|
||||||
|
}
|
27
src/tracebuf.h
Normal file
27
src/tracebuf.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef TRACEBUF
|
||||||
|
#define TRACEBUF
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
#include "termlists.h"
|
||||||
|
#include "knowledge.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
/* STATUS symbols */
|
||||||
|
#define S_UNK 0 // UNKnown : unprocessed.
|
||||||
|
#define S_OKE 1 // OKE : done, but required for the attack.
|
||||||
|
#define S_RED 2 // REDundant : is not needed for attack, we're sure.
|
||||||
|
#define S_TOD 3 // TODo : The previous suggestion REQ was too similar to RED.
|
||||||
|
// This is reserved for reads.
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tracebuf struct is defined in runs.h to avoid loops.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int tracebufRebuildKnow(struct tracebuf *tb);
|
||||||
|
struct tracebuf* tracebufInit (void);
|
||||||
|
void tracebufDone (struct tracebuf *tb);
|
||||||
|
struct tracebuf* tracebufSet (const System sys, int length, int claimev);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
94
src/varbuf.c
Normal file
94
src/varbuf.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* varbuf.c
|
||||||
|
*
|
||||||
|
* Operations on a variable substitutions buffer.
|
||||||
|
* The type is actually defined in runs.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create a new varbuffer from the current state of the system
|
||||||
|
*/
|
||||||
|
|
||||||
|
Varbuf
|
||||||
|
varbufInit (System sys)
|
||||||
|
{
|
||||||
|
Varbuf vb;
|
||||||
|
Termlist tl;
|
||||||
|
Term termfrom, termto;
|
||||||
|
|
||||||
|
vb = (Varbuf) memAlloc(sizeof(struct varbuf));
|
||||||
|
vb->from = NULL;
|
||||||
|
vb->to = NULL;
|
||||||
|
vb->empty = NULL;
|
||||||
|
tl = sys->variables;
|
||||||
|
while (tl != NULL)
|
||||||
|
{
|
||||||
|
if (realTermVariable(tl->term))
|
||||||
|
{
|
||||||
|
/* this is actually a variable */
|
||||||
|
if (tl->term->subst == NULL)
|
||||||
|
{
|
||||||
|
/* non-instantiated */
|
||||||
|
vb->empty = termlistAdd (vb->empty, tl->term);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* store instantiation */
|
||||||
|
termfrom = tl->term;
|
||||||
|
termto = termfrom->subst;
|
||||||
|
termfrom->subst = NULL; // temp disable
|
||||||
|
vb->from = termlistAdd (vb->from, termfrom);
|
||||||
|
vb->to = termlistAdd (vb->to, termto);
|
||||||
|
termfrom->subst = termto; // restore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tl = tl->next;
|
||||||
|
}
|
||||||
|
return vb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* copy the variable state back into the system
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
varbufSet (System sys, Varbuf vb)
|
||||||
|
{
|
||||||
|
Termlist tl1, tl2;
|
||||||
|
|
||||||
|
tl1 = vb->from;
|
||||||
|
tl2 = vb->to;
|
||||||
|
while (tl1 != NULL && tl2 != NULL)
|
||||||
|
{
|
||||||
|
tl1->term->subst = tl2->term;
|
||||||
|
tl1 = tl1->next;
|
||||||
|
tl2 = tl2->next;
|
||||||
|
}
|
||||||
|
tl1 = vb->empty;
|
||||||
|
while (tl1 != NULL)
|
||||||
|
{
|
||||||
|
tl1->term->subst = NULL;
|
||||||
|
tl1 = tl1->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
varbufDone (Varbuf vb)
|
||||||
|
{
|
||||||
|
if (vb != NULL)
|
||||||
|
{
|
||||||
|
termlistDelete (vb->from);
|
||||||
|
termlistDelete (vb->to);
|
||||||
|
termlistDelete (vb->empty);
|
||||||
|
memFree(vb, sizeof(struct varbuf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
10
src/varbuf.h
Normal file
10
src/varbuf.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef VARBUF
|
||||||
|
#define VARBUF
|
||||||
|
|
||||||
|
#include "runs.h"
|
||||||
|
|
||||||
|
Varbuf varbufInit (System sys);
|
||||||
|
void varbufSet (System sys, Varbuf vb);
|
||||||
|
void varbufDone (Varbuf vb);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user