- Got rid of a lot of garbage.
This commit is contained in:
parent
f837d1b000
commit
76f0db6f13
@ -1,8 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildMacIntel-MacPPC.cmake
|
||||
# Purpose: Build MacPPC binary on MacIntel
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
include (BuildMacPPC.cmake)
|
||||
|
@ -1,11 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildMacIntel.cmake
|
||||
# Purpose: Build MacIntel binary
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
message (STATUS "Building Apple Mac Intel version")
|
||||
set (scythername "scyther-macintel")
|
||||
add_executable (${scythername} ${Scyther_sources})
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fnested-functions -arch i386")
|
||||
|
@ -1,8 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildMacPPC-MacIntel.cmake
|
||||
# Purpose: Build MacIntel binary on MacPPC
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
include (BuildMacIntel.cmake)
|
||||
|
@ -1,11 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildMacPPC.cmake
|
||||
# Purpose: Build MacPPC binary
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
message (STATUS "Building Apple Mac PPC version")
|
||||
set (scythername "scyther-macppc")
|
||||
add_executable (${scythername} ${Scyther_sources})
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fnested-functions -arch ppc")
|
||||
|
@ -1,36 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildPlatform.cmake
|
||||
# Purpose: Make platform-dependant decisions
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# Add target for Universal Binary when needed
|
||||
if (APPLE)
|
||||
include (UniversalBinary.cmake)
|
||||
endif (APPLE)
|
||||
|
||||
# Retrieve Source_OS, Destination_OS (from -DTARGET)
|
||||
include (GetOS.cmake)
|
||||
|
||||
# From source_os and destination_os make a new name for the build script
|
||||
if (Source_OS STREQUAL Destination_OS)
|
||||
set (BuildScriptName "Build${Source_OS}.cmake")
|
||||
else (Source_OS STREQUAL Destination_OS)
|
||||
set (BuildScriptName "Build${Source_OS}-${Destination_OS}.cmake")
|
||||
endif (Source_OS STREQUAL Destination_OS)
|
||||
message (STATUS "Locating platform specific file ${BuildScriptName}")
|
||||
|
||||
# Locate the file. If it exists, start it
|
||||
if (EXISTS ${BuildScriptName})
|
||||
# Execute the build script
|
||||
include (${BuildScriptName})
|
||||
else (EXISTS ${BuildScriptName})
|
||||
# Could not find it!
|
||||
message (STATUS "Could not find ${BuildScriptName}")
|
||||
if (Source_OS STREQUAL Destination_OS)
|
||||
message (FATAL_ERROR "Don't know how to build on ${Source_OS}")
|
||||
else (Source_OS STREQUAL Destination_OS)
|
||||
message (FATAL_ERROR "Don't know how to build for ${Destination_OS} on ${Source_OS}")
|
||||
endif (Source_OS STREQUAL Destination_OS)
|
||||
endif (EXISTS ${BuildScriptName})
|
||||
|
@ -1,15 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildUnix-Win32.cmake
|
||||
# Purpose: Build Win32 binary on Unix
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
message (STATUS "Building W32 version")
|
||||
# This should work on win32 platform, but also when the compiler
|
||||
# is available anyway under linux
|
||||
set (CMAKE_C_COMPILER "i586-mingw32msvc-gcc")
|
||||
set (CMAKE_CXX_COMPILER "i586-mingw32msvc-g++")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) # to get rid of -rdynamic
|
||||
set (scythername "scyther-w32.exe")
|
||||
add_executable (${scythername} ${Scyther_sources})
|
||||
|
@ -1,12 +0,0 @@
|
||||
################################################################
|
||||
# Name: BuildUnix.cmake
|
||||
# Purpose: Build Unix binary on self
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# We call it linux, because that is what de-facto is the case.
|
||||
|
||||
message (STATUS "Building Linux version")
|
||||
set (scythername "scyther-linux")
|
||||
add_executable (${scythername} ${Scyther_sources})
|
||||
|
@ -1,37 +0,0 @@
|
||||
################################################################
|
||||
# Name: CMakeLists.txt
|
||||
# Purpose: Input file for CMake for the Scyther tool
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# Scyther project
|
||||
project (Scyther)
|
||||
# I need 2.4 for flex/etc although it does not run yet
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
||||
|
||||
# List all the source files
|
||||
set (Scyther_sources
|
||||
arachne.c binding.c claim.c color.c compiler.c cost.c
|
||||
debug.c depend.c dotout.c error.c heuristic.c hidelevel.c
|
||||
intruderknowledge.c knowledge.c label.c list.c main.c mgu.c
|
||||
prune_bounds.c prune_theorems.c role.c
|
||||
specialterm.c states.c switches.c symbol.c system.c tac.c
|
||||
termlist.c termmap.c term.c timer.c type.c warshall.c xmlout.c
|
||||
parser.c scanner.c
|
||||
)
|
||||
|
||||
# If we are in a debug mode we want to be strict
|
||||
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -DDEBUG")
|
||||
|
||||
# Usual static
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static")
|
||||
|
||||
# Determine version number
|
||||
include (SVNVersion.cmake)
|
||||
|
||||
# Make scanner and parser
|
||||
include (ScannerParser.cmake)
|
||||
|
||||
# Set build target settings according to platform
|
||||
include (BuildPlatform.cmake)
|
||||
|
@ -1,33 +0,0 @@
|
||||
# - Try to find Bison
|
||||
# Once done this will define
|
||||
#
|
||||
# BISON_FOUND - system has Bison
|
||||
# BISON_EXECUTABLE - path of the bison executable
|
||||
# BISON_VERSION - the version string, like "2.5.31"
|
||||
#
|
||||
|
||||
|
||||
FIND_PROGRAM(BISON_EXECUTABLE NAMES bison)
|
||||
mark_as_advanced(BISON_DIR Bison_DIR)
|
||||
|
||||
#INCLUDE(MacroEnsureVersion)
|
||||
|
||||
IF(BISON_EXECUTABLE)
|
||||
SET(BISON_FOUND TRUE)
|
||||
|
||||
EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE _BISON_VERSION
|
||||
)
|
||||
string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" BISON_VERSION "${_bison_VERSION}")
|
||||
ENDIF(BISON_EXECUTABLE)
|
||||
|
||||
IF(BISON_FOUND)
|
||||
IF(NOT Bison_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Bison: ${BISON_EXECUTABLE}")
|
||||
ENDIF(NOT Bison_FIND_QUIETLY)
|
||||
ELSE(BISON_FOUND)
|
||||
IF(Bison_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Bison")
|
||||
ENDIF(Bison_FIND_REQUIRED)
|
||||
ENDIF(BISON_FOUND)
|
||||
|
@ -1,33 +0,0 @@
|
||||
# - Try to find Flex
|
||||
# Once done this will define
|
||||
#
|
||||
# FLEX_FOUND - system has Flex
|
||||
# FLEX_EXECUTABLE - path of the flex executable
|
||||
# FLEX_VERSION - the version string, like "2.5.31"
|
||||
#
|
||||
|
||||
|
||||
FIND_PROGRAM(FLEX_EXECUTABLE NAMES flex)
|
||||
mark_as_advanced(FLEX_DIR Flex_DIR)
|
||||
|
||||
#INCLUDE(MacroEnsureVersion)
|
||||
|
||||
IF(FLEX_EXECUTABLE)
|
||||
SET(FLEX_FOUND TRUE)
|
||||
|
||||
EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE _FLEX_VERSION
|
||||
)
|
||||
string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" FLEX_VERSION "${_FLEX_VERSION}")
|
||||
ENDIF(FLEX_EXECUTABLE)
|
||||
|
||||
IF(FLEX_FOUND)
|
||||
IF(NOT Flex_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Flex: ${FLEX_EXECUTABLE}")
|
||||
ENDIF(NOT Flex_FIND_QUIETLY)
|
||||
ELSE(FLEX_FOUND)
|
||||
IF(Flex_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Flex")
|
||||
ENDIF(Flex_FIND_REQUIRED)
|
||||
ENDIF(FLEX_FOUND)
|
||||
|
@ -1,43 +0,0 @@
|
||||
################################################################
|
||||
# Name: GetOS.cmake
|
||||
# Purpose: Determine Source_OS and Destination_OS (-DTARGETOS)
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# Supported types:
|
||||
#
|
||||
# Win32
|
||||
# Unix
|
||||
# MacPPC
|
||||
# MacIntel
|
||||
|
||||
# First we find out the current operating system
|
||||
set (Source_OS)
|
||||
if (WIN32)
|
||||
# Windows
|
||||
set (Source_OS "Win32")
|
||||
else (WIN32)
|
||||
# Not windows, is it a mac?
|
||||
if (APPLE)
|
||||
# TODO: A mac, but what architecture?
|
||||
# For now we assume intel (Christoph Sprenger's machine)
|
||||
set (Source_OS "MacIntel")
|
||||
else (APPLE)
|
||||
# Not a mac, not windows
|
||||
if (UNIX)
|
||||
set (Source_OS "Unix")
|
||||
else (UNIX)
|
||||
message (FATAL "Unrecognized source platform.")
|
||||
endif (UNIX)
|
||||
endif (APPLE)
|
||||
endif (WIN32)
|
||||
#message (STATUS "Source platform: ${Source_OS}")
|
||||
|
||||
# Destination? If target is unset, we just take the source
|
||||
if (TARGETOS)
|
||||
set (Destination_OS "${TARGETOS}")
|
||||
else (TARGETOS)
|
||||
set (Destination_OS "${Source_OS}")
|
||||
endif (TARGETOS)
|
||||
#message (STATUS "Destination platform: ${Destination_OS}")
|
||||
|
@ -1,86 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# Make doxygen reference manuals. (in ../refman)
|
||||
#
|
||||
refman: doxyconfig
|
||||
doxygen doxyconfig
|
||||
|
@ -1,58 +0,0 @@
|
||||
################################################################
|
||||
# Name: SVNVersion.cmake
|
||||
# Purpose: Determine subversion revision id for Scyther
|
||||
# and write it into a macro in version.h
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# Technically, this only needs to be redone each time a file
|
||||
# changes, so this is a target with dependencies on all files.
|
||||
|
||||
# Checkout version info
|
||||
find_program (SVNVERSION_EXECUTABLE NAMES svnversion)
|
||||
mark_as_advanced (SVNVERSION_EXECUTABLE)
|
||||
mark_as_advanced (SVNVERSION_DYNAMIC)
|
||||
set (SVNVERSION_DYNAMIC false)
|
||||
if (SVNVERSION_EXECUTABLE)
|
||||
# test whether svnversion gives useful info
|
||||
execute_process (
|
||||
COMMAND ${SVNVERSION_EXECUTABLE} --no-newline
|
||||
OUTPUT_VARIABLE SVN_Result
|
||||
)
|
||||
mark_as_advanced (SVN_Result)
|
||||
if (NOT ${SVN_Result} STREQUAL "exported")
|
||||
# svnversion gives useful stuff
|
||||
## write to file
|
||||
#file (WRITE version.h "#define SVNVERSION \"${SVN_Result}\"\n")
|
||||
set (SVNVERSION_DYNAMIC true)
|
||||
endif (NOT ${SVN_Result} STREQUAL "exported")
|
||||
mark_as_advanced (SVNDIR)
|
||||
endif (SVNVERSION_EXECUTABLE)
|
||||
|
||||
# If dynamic generation is required, this means another target in the
|
||||
# makefile
|
||||
if (SVNVERSION_DYNAMIC)
|
||||
# add a command to generate version.h
|
||||
message (STATUS "Generating version.h dynamically using svnversion command")
|
||||
add_custom_command (
|
||||
OUTPUT version.h
|
||||
# The version number depends on all the files; if they
|
||||
# don't change, neither should the version number
|
||||
# (although this might be incorrect when updating the
|
||||
# current directory)
|
||||
DEPENDS ${Scyther_sources}
|
||||
DEPENDS .svn
|
||||
COMMAND ./subbuild-version-information.sh
|
||||
COMMENT "Generating subversion and tag version information in version.h using svnversion command"
|
||||
)
|
||||
else (SVNVERSION_DYNAMIC)
|
||||
# Don't dynamically generate, simply empty every time
|
||||
file (WRITE version.h "#define SVNVERSION \"Unknown\"\n#define TAGVERSION \"Unknown\"")
|
||||
endif (SVNVERSION_DYNAMIC)
|
||||
|
||||
# add the version number to the sources
|
||||
set_source_files_properties(version.h
|
||||
PROPERTIES
|
||||
GENERATED true)
|
||||
set (Scyther_sources ${Scyther_sources} version.h)
|
||||
|
@ -1,41 +0,0 @@
|
||||
################################################################
|
||||
# Name: ScannerParser.cmake
|
||||
# Purpose: If flex/bison are available, generate parser and scanner
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
# Make the scanner using flex, if it can be found
|
||||
include(FindFLEX.cmake)
|
||||
if (FLEX_FOUND)
|
||||
set_source_files_properties(scanner.c PROPERTIES GENERATED true)
|
||||
ADD_CUSTOM_COMMAND (
|
||||
OUTPUT scanner.c
|
||||
DEPENDS scanner.l
|
||||
COMMAND ${FLEX_EXECUTABLE}
|
||||
# TODO: I should look up from which version the -o
|
||||
# switch works, might not be portable.
|
||||
ARGS -oscanner.c scanner.l
|
||||
COMMENT "Building scanner.c from scanner.l using flex"
|
||||
)
|
||||
else (FLEX_FOUND)
|
||||
message (STATUS "Because flex is not found, we will use the existing scanner.c")
|
||||
endif (FLEX_FOUND)
|
||||
|
||||
# Make the parser using bison, if it can be found
|
||||
include(FindBISON.cmake)
|
||||
if (BISON_FOUND)
|
||||
set_source_files_properties(parser.c PROPERTIES GENERATED true)
|
||||
ADD_CUSTOM_COMMAND (
|
||||
OUTPUT parser.c
|
||||
DEPENDS parser.y
|
||||
COMMAND ${BISON_EXECUTABLE}
|
||||
# TODO: I should look up from which version the -o
|
||||
# switch works, might not be portable.
|
||||
ARGS -d -oparser.c parser.y
|
||||
COMMENT "Building parser.c from parser.y using bison"
|
||||
)
|
||||
else (BISON_FOUND)
|
||||
message (STATUS "Because bison is not found, we will use the existing parser.c")
|
||||
endif (BISON_FOUND)
|
||||
|
||||
|
@ -1,789 +0,0 @@
|
||||
[Project]
|
||||
FileName=Scyther.dev
|
||||
Name=Scyther
|
||||
UnitCount=72
|
||||
Type=1
|
||||
Ver=1
|
||||
ObjFiles=
|
||||
Includes=
|
||||
Libs=
|
||||
PrivateResource=
|
||||
ResourceIncludes=
|
||||
MakeIncludes=
|
||||
Compiler=
|
||||
CppCompiler=
|
||||
Linker=
|
||||
IsCpp=0
|
||||
Icon=
|
||||
ExeOutput=..\gui\Scyther
|
||||
ObjectOutput=
|
||||
OverrideOutput=0
|
||||
OverrideOutputName=Scyther.exe
|
||||
HostApplication=
|
||||
Folders=
|
||||
CommandLine=
|
||||
UseCustomMakefile=0
|
||||
CustomMakefile=
|
||||
IncludeVersionInfo=0
|
||||
SupportXPThemes=0
|
||||
CompilerSet=0
|
||||
CompilerSettings=0000000000000000000000
|
||||
|
||||
[Unit1]
|
||||
FileName=xmlout.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit2]
|
||||
FileName=arachne.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit3]
|
||||
FileName=arachne.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit4]
|
||||
FileName=binding.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit5]
|
||||
FileName=binding.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit6]
|
||||
FileName=claim.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit7]
|
||||
FileName=claim.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit8]
|
||||
FileName=color.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit9]
|
||||
FileName=color.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit10]
|
||||
FileName=compiler.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit11]
|
||||
FileName=compiler.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit12]
|
||||
FileName=cost.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit13]
|
||||
FileName=cost.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit14]
|
||||
FileName=debug.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit15]
|
||||
FileName=debug.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit16]
|
||||
FileName=depend.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit17]
|
||||
FileName=depend.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit18]
|
||||
FileName=dotout.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit19]
|
||||
FileName=dotout.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit20]
|
||||
FileName=error.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit21]
|
||||
FileName=error.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit22]
|
||||
FileName=heuristic.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit23]
|
||||
FileName=heuristic.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit24]
|
||||
FileName=hidelevel.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit25]
|
||||
FileName=hidelevel.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit26]
|
||||
FileName=intruderknowledge.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit27]
|
||||
FileName=intruderknowledge.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit28]
|
||||
FileName=knowledge.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit29]
|
||||
FileName=knowledge.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit30]
|
||||
FileName=label.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit31]
|
||||
FileName=label.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit32]
|
||||
FileName=list.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit33]
|
||||
FileName=list.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit35]
|
||||
FileName=mgu.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit36]
|
||||
FileName=pheading.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit37]
|
||||
FileName=prune_bounds.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit38]
|
||||
FileName=prune_bounds.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit39]
|
||||
FileName=prune_theorems.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit40]
|
||||
FileName=prune_theorems.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit41]
|
||||
FileName=role.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit42]
|
||||
FileName=role.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit43]
|
||||
FileName=specialterm.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit44]
|
||||
FileName=specialterm.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit45]
|
||||
FileName=states.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit46]
|
||||
FileName=states.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit48]
|
||||
FileName=switches.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit49]
|
||||
FileName=symbol.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit50]
|
||||
FileName=symbol.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit51]
|
||||
FileName=system.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit52]
|
||||
FileName=system.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit53]
|
||||
FileName=tac.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit54]
|
||||
FileName=tac.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit55]
|
||||
FileName=term.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit56]
|
||||
FileName=term.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit57]
|
||||
FileName=termlist.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit58]
|
||||
FileName=termlist.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit59]
|
||||
FileName=termmap.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit60]
|
||||
FileName=termmap.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit61]
|
||||
FileName=timer.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit62]
|
||||
FileName=timer.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit63]
|
||||
FileName=type.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit64]
|
||||
FileName=type.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit65]
|
||||
FileName=warshall.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit66]
|
||||
FileName=warshall.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit67]
|
||||
FileName=xmlout.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit68]
|
||||
FileName=main.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit69]
|
||||
FileName=version.h
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit70]
|
||||
FileName=parser.h
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit71]
|
||||
FileName=scanner.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[VersionInfo]
|
||||
Major=0
|
||||
Minor=1
|
||||
Release=1
|
||||
Build=1
|
||||
LanguageID=1033
|
||||
CharsetID=1252
|
||||
CompanyName=
|
||||
FileVersion=
|
||||
FileDescription=Developed using the Dev-C++ IDE
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=
|
||||
AutoIncBuildNr=0
|
||||
|
||||
[Unit34]
|
||||
FileName=mgu.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit72]
|
||||
FileName=parser.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit73]
|
||||
FileName=scanner.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit74]
|
||||
FileName=parser.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit47]
|
||||
FileName=switches.c
|
||||
CompileCpp=0
|
||||
Folder=Scyther
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
@ -1,42 +0,0 @@
|
||||
################################################################
|
||||
# Name: UniversalBinary.cmake
|
||||
# Purpose: Add target to make a Mac universal binary
|
||||
# Needs pre-build mac versions first!
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
find_program(lipoexecutable lipo)
|
||||
if (lipoexecutable)
|
||||
# Check whether we already have the binaries
|
||||
set (UBrequiredfiles FALSE)
|
||||
set (ppcfile "scyther-macppc")
|
||||
set (intelfile "scyther-macintel")
|
||||
if (EXISTS "${ppcfile}")
|
||||
if (EXISTS "${intelfile}")
|
||||
set (UBrequiredfiles TRUE)
|
||||
else (EXISTS "${intelfile}")
|
||||
message (STATUS "Could not find scyther-macintel.")
|
||||
endif (EXISTS "${intelfile}")
|
||||
else (EXISTS "${ppcfile}")
|
||||
message (STATUS "Could not find scyther-macppc.")
|
||||
endif (EXISTS "${ppcfile}")
|
||||
|
||||
# Use information to proceed
|
||||
if (UBrequiredfiles)
|
||||
message (STATUS "Adding target for Mac universal binary")
|
||||
add_custom_target (scyther-mac
|
||||
COMMAND lipo -create "${ppcfile}" "${intelfile}" -output scyther-mac
|
||||
COMMENT "Generating Mac universal binary"
|
||||
DEPENDS scyther-macintel
|
||||
DEPENDS scyther-macppc
|
||||
)
|
||||
else (UBrequiredfiles)
|
||||
message (STATUS "No universal binary possible yet. Please do the following:")
|
||||
message (STATUS " cmake -DTARGETOS=MacPPC . && make")
|
||||
message (STATUS " cmake -DTARGETOS=MacIntel . && make")
|
||||
message (STATUS " cmake . && make scyther-mac")
|
||||
endif (UBrequiredfiles)
|
||||
else (lipoexecutable)
|
||||
message (FATAL_ERROR "Cannot find the 'lipo' program that is required for creating universal binaries")
|
||||
endif (lipoexecutable)
|
||||
|
2582
gui/src/arachne.c
2582
gui/src/arachne.c
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
||||
#ifndef ARACHNE
|
||||
#define ARACHNE
|
||||
|
||||
#include "system.h"
|
||||
|
||||
void arachneInit (const System sys);
|
||||
void arachneDone ();
|
||||
int arachne ();
|
||||
int get_semitrace_length ();
|
||||
void indentPrint ();
|
||||
int isTriviallyKnownAtArachne (const System sys, const Term t, const int run,
|
||||
const int index);
|
||||
int isTriviallyKnownAfterArachne (const System sys, const Term t,
|
||||
const int run, const int index);
|
||||
void arachneOutputAttack ();
|
||||
void printSemiState ();
|
||||
int countIntruderActions ();
|
||||
void role_name_print (const int run);
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
\documentclass{article}
|
||||
\usepackage{a4wide}
|
||||
\usepackage{msc}
|
||||
\usepackage{ifthen}
|
||||
|
||||
%\setlength{\instwidth}{3.0cm}
|
||||
%\setlength{\instdist}{4cm}
|
||||
%\setlength{\actionwidth}{3.6cm}
|
||||
%\setlength{\conditionoverlap}{1.9cm}
|
||||
|
||||
% Action macro from MSC documentation
|
||||
|
||||
\newsavebox{\labelbox}
|
||||
\newlength{\oldwd}
|
||||
\newlength{\oldht}
|
||||
\newcommand{\Action}[2]{%
|
||||
\setlength{\oldwd}{\actionwidth}%
|
||||
\setlength{\oldht}{\actionheight}%
|
||||
\savebox{\labelbox}{#1}%
|
||||
\setlength{\actionwidth}{\wd\labelbox + 2\labeldist}%
|
||||
\setlength{\actionheight}{\ht\labelbox + \dp\labelbox + 2\labeldist}%
|
||||
\action{\usebox{\labelbox}}{#2}%
|
||||
\setlength{\actionwidth}{\oldwd}%
|
||||
\setlength{\actionheight}{\oldht}%
|
||||
}
|
||||
|
||||
\newlength{\mscspacer}
|
||||
\setlength{\mscspacer}{1ex}
|
||||
|
||||
\newcommand{\ActionBox}[2]{%
|
||||
\Action{\parbox{\maxmscaction - 2\mscspacer}{\centering #1}}{#2}
|
||||
}
|
||||
|
||||
\newlength{\maxtemp}
|
||||
|
||||
\newcommand{\maxlength}[2]{
|
||||
\settowidth{\maxtemp}{#2}
|
||||
\ifthenelse{\lengthtest{#1 < \maxtemp}}{\setlength{#1}{\maxtemp}}{}
|
||||
\ifthenelse{\lengthtest{\maxmscall < \maxtemp}}{\setlength{\maxmscall}{\maxtemp}}{}
|
||||
}
|
||||
|
||||
|
||||
|
||||
\newlength{\maxmscall}
|
||||
\newlength{\maxmscinst}
|
||||
\newlength{\maxmscaction}
|
||||
\newlength{\maxmsccondition}
|
||||
|
||||
\setlength{\maxmscall}{\mscspacer}
|
||||
\setlength{\maxmscinst}{\mscspacer}
|
||||
\setlength{\maxmscaction}{\mscspacer}
|
||||
\setlength{\maxmsccondition}{\mscspacer}
|
||||
|
||||
% pagestyle without numbering
|
||||
\pagestyle{empty}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\input{attack}
|
||||
|
||||
\end{document}
|
@ -1,617 +0,0 @@
|
||||
/**
|
||||
* Handle bindings for Arache engine.
|
||||
*/
|
||||
|
||||
#include "list.h"
|
||||
#include "role.h"
|
||||
#include "label.h"
|
||||
#include "system.h"
|
||||
#include "binding.h"
|
||||
#include "warshall.h"
|
||||
#include "debug.h"
|
||||
#include "term.h"
|
||||
#include "termmap.h"
|
||||
#include "arachne.h"
|
||||
#include "switches.h"
|
||||
#include "depend.h"
|
||||
#include "error.h"
|
||||
#if !defined(__APPLE__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
static System sys; //!< local storage of system pointer
|
||||
|
||||
extern Protocol INTRUDER; //!< The intruder protocol
|
||||
extern Role I_M; //!< special role; precedes all other events always
|
||||
|
||||
/*
|
||||
*
|
||||
* Assist stuff
|
||||
*
|
||||
*/
|
||||
|
||||
//! Create mem for binding
|
||||
Binding
|
||||
binding_create (Term term, int run_to, int ev_to)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = malloc (sizeof (struct binding));
|
||||
b->done = false;
|
||||
b->blocked = false;
|
||||
b->run_from = -1;
|
||||
b->ev_from = -1;
|
||||
b->run_to = run_to;
|
||||
b->ev_to = ev_to;
|
||||
b->term = term;
|
||||
b->level = 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
//! Remove mem for binding
|
||||
void
|
||||
binding_destroy (Binding b)
|
||||
{
|
||||
if (b->done)
|
||||
{
|
||||
goal_unbind (b);
|
||||
}
|
||||
free (b);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Main
|
||||
*
|
||||
*/
|
||||
|
||||
//! Init module
|
||||
void
|
||||
bindingInit (const System mysys)
|
||||
{
|
||||
sys = mysys;
|
||||
sys->bindings = NULL;
|
||||
|
||||
dependInit (sys);
|
||||
}
|
||||
|
||||
//! Close up
|
||||
void
|
||||
bindingDone ()
|
||||
{
|
||||
int delete (Binding b)
|
||||
{
|
||||
binding_destroy (b);
|
||||
return true;
|
||||
}
|
||||
list_iterate (sys->bindings, delete);
|
||||
list_destroy (sys->bindings);
|
||||
|
||||
dependDone (sys);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Externally available functions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//! Print a binding (given a binding list pointer)
|
||||
int
|
||||
binding_print (const Binding b)
|
||||
{
|
||||
if (b->done)
|
||||
eprintf ("Binding (%i,%i) --( ", b->run_from, b->ev_from);
|
||||
else
|
||||
eprintf ("Unbound --( ");
|
||||
termPrint (b->term);
|
||||
eprintf (" )->> (%i,%i)", b->run_to, b->ev_to);
|
||||
if (b->blocked)
|
||||
eprintf ("[blocked]");
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Bind a goal (true if success, false if it must be pruned)
|
||||
int
|
||||
goal_bind (const Binding b, const int run, const int ev)
|
||||
{
|
||||
if (b->blocked)
|
||||
{
|
||||
error ("Trying to bind a blocked goal.");
|
||||
}
|
||||
if (!b->done)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (run >= sys->maxruns || sys->runs[run].step <= ev)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("For term: ");
|
||||
termPrint (b->term);
|
||||
eprintf (" needed for r%ii%i.\n", b->run_to, b->ev_to);
|
||||
eprintf ("Current limits: %i runs, %i events for this run.\n",
|
||||
sys->maxruns, sys->runs[run].step);
|
||||
globalError--;
|
||||
error
|
||||
("trying to bind to something not yet in the semistate: r%ii%i.",
|
||||
run, ev);
|
||||
}
|
||||
#endif
|
||||
b->run_from = run;
|
||||
b->ev_from = ev;
|
||||
if (dependPushEvent (run, ev, b->run_to, b->ev_to))
|
||||
{
|
||||
b->done = true;
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
binding_print (b);
|
||||
eprintf ("\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalError++;
|
||||
binding_print (b);
|
||||
error ("Trying to bind a bound goal again.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Unbind a goal
|
||||
void
|
||||
goal_unbind (const Binding b)
|
||||
{
|
||||
if (b->done)
|
||||
{
|
||||
dependPopEvent ();
|
||||
b->done = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("Trying to unbind an unbound goal again.");
|
||||
}
|
||||
}
|
||||
|
||||
//! Bind a goal as a dummy (block)
|
||||
/**
|
||||
* Especially made for tuple expansion
|
||||
*
|
||||
* @TODO Weird that this returns a value (always true, otherwise error)
|
||||
*/
|
||||
int
|
||||
binding_block (Binding b)
|
||||
{
|
||||
if (!b->blocked)
|
||||
{
|
||||
b->blocked = true;
|
||||
return true;
|
||||
}
|
||||
error ("Trying to block a goal again.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Unblock a binding
|
||||
/*
|
||||
* @TODO Weird that this returns a value (always true, otherwise error)
|
||||
*/
|
||||
int
|
||||
binding_unblock (Binding b)
|
||||
{
|
||||
if (b->blocked)
|
||||
{
|
||||
b->blocked = false;
|
||||
return true;
|
||||
}
|
||||
error ("Trying to unblock a non-blocked goal.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! Add a goal
|
||||
/**
|
||||
* The int parameter 'level' is just to store additional info. Here, it stores priorities for a goal.
|
||||
* Higher level goals will be selected first. Typically, a normal goal is level 0, a key is 1.
|
||||
*
|
||||
* Returns the number of added goals (sometimes unfolding tuples)
|
||||
*/
|
||||
int
|
||||
goal_add (Term term, const int run, const int ev, const int level)
|
||||
{
|
||||
term = deVar (term);
|
||||
#ifdef DEBUG
|
||||
if (term == NULL)
|
||||
{
|
||||
globalError++;
|
||||
roledefPrint (eventRoledef (sys, run, ev));
|
||||
eprintf ("\n");
|
||||
globalError--;
|
||||
error ("Trying to add an emtpy goal term to r%ii%i, with level %i.",
|
||||
run, ev, level);
|
||||
}
|
||||
if (run >= sys->maxruns)
|
||||
error ("Trying to add a goal for a run that does not exist.");
|
||||
if (ev >= sys->runs[run].step)
|
||||
error
|
||||
("Trying to add a goal for an event that is not in the semistate yet.");
|
||||
#endif
|
||||
if (switches.intruder && realTermTuple (term))
|
||||
{
|
||||
// Only split if there is an intruder
|
||||
return goal_add (TermOp1 (term), run, ev, level) +
|
||||
goal_add (TermOp2 (term), run, ev, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine whether we already had it
|
||||
int createnew;
|
||||
|
||||
int testSame (void *data)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) data;
|
||||
if (isTermEqual (b->term, term))
|
||||
{
|
||||
// binding of same term
|
||||
if (run == b->run_to && ev == b->ev_to)
|
||||
{
|
||||
// identical binding
|
||||
createnew = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
createnew = true;
|
||||
list_iterate (sys->bindings, testSame);
|
||||
if (createnew)
|
||||
{
|
||||
// Add a new binding
|
||||
Binding b;
|
||||
b = binding_create (term, run, ev);
|
||||
b->level = level;
|
||||
sys->bindings = list_insert (sys->bindings, b);
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (3))
|
||||
{
|
||||
eprintf ("Adding new binding for ");
|
||||
termPrint (term);
|
||||
eprintf (" to run %i, ev %i.\n", run, ev);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Remove a goal
|
||||
void
|
||||
goal_remove_last (int n)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
if (sys->bindings != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) sys->bindings->data;
|
||||
binding_destroy (b);
|
||||
sys->bindings = list_delete (sys->bindings);
|
||||
n--;
|
||||
}
|
||||
else
|
||||
{
|
||||
error
|
||||
("goal_remove_last error: trying to remove %i too many bindings.",
|
||||
n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Determine whether some label set is ordered w.r.t. send/read order.
|
||||
/**
|
||||
* Assumes all these labels exist in the system, within length etc, and that the run mappings are valid.
|
||||
*/
|
||||
int
|
||||
labels_ordered (Termmap runs, Termlist labels)
|
||||
{
|
||||
while (labels != NULL)
|
||||
{
|
||||
// Given this label, and the mapping of runs, we want to know if the order is okay. Thus, we need to know sendrole and readrole
|
||||
Labelinfo linfo;
|
||||
int send_run, send_ev, read_run, read_ev;
|
||||
|
||||
int get_index (const int run)
|
||||
{
|
||||
Roledef rd;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
rd = sys->runs[run].start;
|
||||
while (rd != NULL && !isTermEqual (rd->label, labels->term))
|
||||
{
|
||||
rd = rd->next;
|
||||
i++;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (rd == NULL)
|
||||
error
|
||||
("Could not locate send or read for label, after niagree holds, to test for order.");
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
linfo = label_find (sys->labellist, labels->term);
|
||||
if (!linfo->ignore)
|
||||
{
|
||||
send_run = termmapGet (runs, linfo->sendrole);
|
||||
read_run = termmapGet (runs, linfo->readrole);
|
||||
send_ev = get_index (send_run);
|
||||
read_ev = get_index (read_run);
|
||||
if (!isDependEvent (send_run, send_ev, read_run, read_ev))
|
||||
{
|
||||
// Not ordered; false
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
// Proceed
|
||||
labels = labels->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Check whether the binding denotes a sensible thing such that we can use run_from and ev_from
|
||||
int
|
||||
valid_binding (Binding b)
|
||||
{
|
||||
if (b->done && (!b->blocked))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Iterate over all bindings
|
||||
/**
|
||||
* Iterator should return true to proceed
|
||||
*/
|
||||
int
|
||||
iterate_bindings (int (*func) (Binding b))
|
||||
{
|
||||
List bl;
|
||||
|
||||
for (bl = sys->bindings; bl != NULL; bl = bl->next)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
if (!func (b))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Iterate over preceding bindings (this does not include stuff bound to the same destination)
|
||||
/**
|
||||
* Iterator should return true to proceed
|
||||
*/
|
||||
int
|
||||
iterate_preceding_bindings (const int run, const int ev,
|
||||
int (*func) (Binding b))
|
||||
{
|
||||
int precs (Binding b)
|
||||
{
|
||||
if (isDependEvent (b->run_to, b->ev_to, run, ev))
|
||||
{
|
||||
return func (b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return iterate_bindings (precs);
|
||||
}
|
||||
|
||||
|
||||
//! Check for unique origination
|
||||
/*
|
||||
* Contrary to a previous version, we simply check for unique origination.
|
||||
* This immediately takes care of any 'occurs before' things. Complexity is N
|
||||
* log N.
|
||||
*
|
||||
* Each term should originate only at one point (thus in one binding)
|
||||
*
|
||||
*@returns True, if it's okay. If false, it needs to be pruned.
|
||||
*/
|
||||
int
|
||||
unique_origination ()
|
||||
{
|
||||
List bl;
|
||||
|
||||
bl = sys->bindings;
|
||||
|
||||
while (bl != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
// Check for a valid binding; it has to be 'done' and sensibly bound (not as in tuple expanded stuff)
|
||||
if (valid_binding (b))
|
||||
{
|
||||
Termlist terms;
|
||||
|
||||
terms = tuple_to_termlist (b->term);
|
||||
if (terms != NULL)
|
||||
{
|
||||
/* Apparently this is a good term.
|
||||
* Now we check whether it occurs in any previous bindings as well.
|
||||
*/
|
||||
|
||||
List bl2;
|
||||
|
||||
bl2 = sys->bindings;
|
||||
while (bl2 != bl)
|
||||
{
|
||||
Binding b2;
|
||||
|
||||
b2 = (Binding) bl2->data;
|
||||
if (valid_binding (b2))
|
||||
{
|
||||
Termlist terms2, sharedterms;
|
||||
|
||||
if (switches.intruder)
|
||||
{
|
||||
// For intruder we work with sets here
|
||||
terms2 = tuple_to_termlist (b2->term);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For regular agents we use terms
|
||||
terms2 = termlistAdd (NULL, b2->term);
|
||||
}
|
||||
sharedterms = termlistConjunct (terms, terms2);
|
||||
|
||||
// Compare terms
|
||||
if (sharedterms != NULL)
|
||||
{
|
||||
// Apparently, this binding shares a term.
|
||||
// Equal terms should originate at the same point
|
||||
if (b->run_from != b2->run_from ||
|
||||
b->ev_from != b2->ev_from)
|
||||
{
|
||||
// Not equal: thus no unique origination.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
termlistDelete (terms2);
|
||||
termlistDelete (sharedterms);
|
||||
}
|
||||
bl2 = bl2->next;
|
||||
}
|
||||
}
|
||||
termlistDelete (terms);
|
||||
}
|
||||
bl = bl->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Prune invalid state w.r.t. <=C minimal requirement
|
||||
/**
|
||||
* Intuition says this can be done a lot more efficient. Luckily this is the prototype.
|
||||
*
|
||||
*@returns True, if it's okay. If false, it needs to be pruned.
|
||||
*/
|
||||
int
|
||||
bindings_c_minimal ()
|
||||
{
|
||||
if (!unique_origination ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
List bl;
|
||||
|
||||
// For all goals
|
||||
bl = sys->bindings;
|
||||
while (bl != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
// Check for a valid binding; it has to be 'done' and sensibly bound (not as in tuple expanded stuff)
|
||||
if (valid_binding (b))
|
||||
{
|
||||
int run;
|
||||
|
||||
// Find all preceding events
|
||||
for (run = 0; run < sys->maxruns; run++)
|
||||
{
|
||||
int ev;
|
||||
|
||||
//!@todo hardcoded reference to step, should be length
|
||||
for (ev = 0; ev < sys->runs[run].step; ev++)
|
||||
{
|
||||
if (isDependEvent (run, ev, b->run_from, b->ev_from))
|
||||
{
|
||||
// this node is *before* the from node
|
||||
Roledef rd;
|
||||
int occursthere;
|
||||
|
||||
rd = roledef_shift (sys->runs[run].start, ev);
|
||||
if (switches.intruder)
|
||||
{
|
||||
// intruder: interm bindings should cater for the first occurrence
|
||||
occursthere = termInTerm (rd->message, b->term);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no intruder, then simple test
|
||||
occursthere = isTermEqual (rd->message, b->term);
|
||||
}
|
||||
if (occursthere)
|
||||
{
|
||||
// This term already occurs in a previous node!
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (4))
|
||||
{
|
||||
// Report this
|
||||
indentPrint ();
|
||||
eprintf ("Binding for ");
|
||||
termPrint (b->term);
|
||||
eprintf
|
||||
(" at r%i i%i is not c-minimal because it occurred before at r%i i%i in ",
|
||||
b->run_from, b->ev_from, run, ev);
|
||||
termPrint (rd->message);
|
||||
eprintf ("\n");
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this event is not before the target, then the
|
||||
// next in the run certainly is not either (because
|
||||
// that would imply that this one is before it)
|
||||
// Thus, we effectively exit the loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bl = bl->next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Count the number of bindings that are done.
|
||||
int
|
||||
countBindingsDone ()
|
||||
{
|
||||
int count;
|
||||
|
||||
int countDone (Binding b)
|
||||
{
|
||||
if ((!b->blocked) && b->done)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
iterate_bindings (countDone);
|
||||
return count;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#ifndef BINDINGS
|
||||
#define BINDINGS
|
||||
|
||||
#include "term.h"
|
||||
#include "termmap.h"
|
||||
#include "system.h"
|
||||
|
||||
//! Binding structure
|
||||
/*
|
||||
* Idea is the ev_from *has to* precede the ev_to
|
||||
*/
|
||||
struct binding
|
||||
{
|
||||
int done; //!< Iff true, it is bound
|
||||
int blocked; //!< Iff true, ignore it
|
||||
|
||||
int run_from; //!< origination run
|
||||
int ev_from; //!< step in origination run
|
||||
|
||||
int run_to; //!< destination run
|
||||
int ev_to; //!< step in destination run
|
||||
|
||||
Term term; //!< Binding term
|
||||
int level; //!< ???
|
||||
};
|
||||
|
||||
typedef struct binding *Binding; //!< pointer to binding structure
|
||||
|
||||
|
||||
void bindingInit (const System mysys);
|
||||
void bindingDone ();
|
||||
|
||||
int binding_print (Binding b);
|
||||
int valid_binding (Binding b);
|
||||
|
||||
int goal_add (Term term, const int run, const int ev, const int level);
|
||||
int goal_add_fixed (Term term, const int run, const int ev, const int fromrun,
|
||||
const int fromev);
|
||||
void goal_remove_last (int n);
|
||||
int goal_bind (const Binding b, const int run, const int ev);
|
||||
void goal_unbind (const Binding b);
|
||||
int binding_block (Binding b);
|
||||
int binding_unblock (Binding b);
|
||||
int labels_ordered (Termmap runs, Termlist labels);
|
||||
|
||||
int iterate_bindings (int (*func) (Binding b));
|
||||
int iterate_preceding_bindings (const int run, const int ev,
|
||||
int (*func) (Binding b));
|
||||
|
||||
int bindings_c_minimal ();
|
||||
int countBindingsDone ();
|
||||
|
||||
#endif
|
119
gui/src/bugs.txt
119
gui/src/bugs.txt
@ -1,119 +0,0 @@
|
||||
--+++ Crititcal Bugs
|
||||
|
||||
* soph segfaults at no switch or -r4 (-r3 is okay??) using non-debug version.
|
||||
* './scyther -a ../spdl/nsl3.spdl --increment-runs' segfaults. The main reason is that the Archne engine uses runs in a different way.
|
||||
Maybe it is best to disable --increment rules for non-ModelChecker verification.
|
||||
|
||||
---+++ Bugs
|
||||
|
||||
* Problem with goal bindings: instantiation of variable with a tuple might
|
||||
introduce a tuple goal, which is forbidden. We must find a way to deal with this. This typically occurs in type flaw searches.
|
||||
* Arachne seems to trip over claims with empty prec sets. Maybe we
|
||||
simply should not test these.
|
||||
* Splice/AS does not work well because priority key search stumbles over the
|
||||
public key search stuff. That is a flaw in the heuristic: we should not look
|
||||
for anything that is in the intruder knowledge already. In fact, it is a
|
||||
problem with branching. We should not look for PK(X), even if X is a
|
||||
variable. Priority should go to keys of which the constructor is not in M_0,
|
||||
maybe that heuristic works.
|
||||
However, there seems to be an infinite loop for this in the algorithm, which
|
||||
I did not anticipate. Investigate!
|
||||
<br>
|
||||
Maybe self-loops are the problem. This has to do with tuple alternation
|
||||
decoding. Consider re-introducing explicit intruder strands OR self-loop
|
||||
pruning.
|
||||
|
||||
---+++ Would like to have
|
||||
|
||||
---++++ ArachneEngine
|
||||
|
||||
* There is no good test on the correct workings of
|
||||
add_goals/destruction of these. We can test this if after
|
||||
termination, we have 0 goals; for this we need to store the
|
||||
initially added goals as well. Furthermore, we can generate an
|
||||
error when <0 goals occur.
|
||||
* Consider where in Arachne dependency graph is used. If this is only for
|
||||
pruning states, we can construct it there only. However, the base 'role
|
||||
defs/bindings' graph might be re-used.
|
||||
* Add switch for arachne to prune encryption levels when using -m2.
|
||||
* To store attacks for arachne, maybe the following is needed:
|
||||
* The roles for each run
|
||||
* The variable bindings for all (local) variables
|
||||
* The goal bindings
|
||||
* Agent terms must have keylevel 0; enforce this!
|
||||
* Select_goal should consider, for singular variables, whether their
|
||||
type can be found in M_0. If so, the goal can be ignored.
|
||||
* Fix 'never sent secrets' list, that are e.g. secret keys of regular agents
|
||||
and such. The intruder can never learn these, we need this for pruning.
|
||||
If a goal is such a term, we prune. Investigate how this can be incorporated.
|
||||
Investigate also whether this actually makes a difference.
|
||||
* Make 'generate_trace_bindings' to create the bindings for a given trace.
|
||||
Note that there can be multiple solutions; for now, simply try to take the
|
||||
shortest one.
|
||||
|
||||
---++++ ModelChecker
|
||||
|
||||
* For secrecy, one trusted agent and one untrusted agent suffices.
|
||||
Implement this in the modelchecker.
|
||||
* Implement delayed protocol compiler (on run demand only) for the modelchecker?
|
||||
|
||||
---++++ Misc
|
||||
|
||||
* Make different error codes for compilation error/ other error. This can be
|
||||
useful for scripts. However, it might shift some constants for the Elegast
|
||||
scripts.
|
||||
* Rewrite termMguTerm such that it iterates and adapt all functions
|
||||
using it. This is to allow for associative tupling later.
|
||||
* Fix constants in intruder knowledge. Auto add single one of each type,
|
||||
when typed expl. Add single constant when untyped. Fix this also in
|
||||
semantics, and add proof to establish sufficiency.
|
||||
* Fix function handling (signatures).
|
||||
* Move initial intruder knowledge maybe into the title of the MSC.
|
||||
* Implement run knowledge, and use this in protocol compiler.
|
||||
* Introduce 'Ticket' default type in the compiler, along with some
|
||||
handling for that.
|
||||
* The 'choose' operator must always be typed, I think. Yes.
|
||||
* 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.
|
||||
1. 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.
|
||||
* Woolam-ce gives nothing. But then again, it's a wrong impl.
|
||||
* Global/protocol variables should not exist in the current system.
|
||||
* 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.
|
||||
* Maybe function application ought to be a different basic term type.
|
||||
* After role construction, msc consistency can be checked.
|
||||
* 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?
|
||||
|
||||
---++++ ConstraintLogic (and thus obsolete)
|
||||
|
||||
* CLP: variables in keys must be branched: maybe even in three situations
|
||||
(have key and contents, have inverse key and content, nothing)
|
||||
* How should claims behave (trusted/untrusted) wrt uninstantiated
|
||||
agents? Branch again? That's what is causing the nsl3-var problem.
|
||||
* 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.
|
||||
* 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.
|
||||
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
PLATFORM=`uname`
|
||||
echo $PLATFORM
|
||||
if [ "$PLATFORM" = "Darwin" ]
|
||||
then
|
||||
./subbuild-mac-universal.sh
|
||||
else
|
||||
if [ "$PLATFORM" = "Linux" ]
|
||||
then
|
||||
./subbuild-unix-both.sh
|
||||
else
|
||||
echo "I don't know platform $PLATFORM, so I won't do anything"
|
||||
fi
|
||||
fi
|
||||
|
1136
gui/src/claim.c
1136
gui/src/claim.c
File diff suppressed because it is too large
Load Diff
@ -1,18 +0,0 @@
|
||||
#ifndef CLAIMS
|
||||
#define CLAIMS
|
||||
|
||||
int check_claim_nisynch (const System sys, const int i);
|
||||
int check_claim_niagree (const System sys, const int i);
|
||||
int arachne_claim_niagree (const System sys, const int claim_run,
|
||||
const int claim_index);
|
||||
int arachne_claim_nisynch (const System sys, const int claim_run,
|
||||
const int claim_index);
|
||||
|
||||
int prune_claim_specifics (const System sys);
|
||||
int add_claim_specifics (const System sys, const Claimlist cl, const
|
||||
Roledef rd, int (*callback) (void));
|
||||
void count_false_claim (const System sys);
|
||||
int property_check (const System sys);
|
||||
int claimStatusReport (const System sys, Claimlist cl);
|
||||
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
/** @file color.c \brief Color output for terminals.
|
||||
*
|
||||
* Depends on the switches (to disable them with a --plain switch)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "switches.h"
|
||||
|
||||
//! Substitution string for --plain output
|
||||
char *empty = "";
|
||||
//! Reset colors
|
||||
char *COLOR_Reset = "[0m";
|
||||
//! Red
|
||||
char *COLOR_Red = "[31m";
|
||||
//! Green
|
||||
char *COLOR_Green = "[32m";
|
||||
//! Bold
|
||||
char *COLOR_Bold = "[1m";
|
||||
|
||||
//! Init colors
|
||||
void
|
||||
colorInit (void)
|
||||
{
|
||||
if (switches.plain)
|
||||
{
|
||||
COLOR_Reset = empty;
|
||||
COLOR_Red = empty;
|
||||
COLOR_Green = empty;
|
||||
COLOR_Bold = empty;
|
||||
}
|
||||
}
|
||||
|
||||
//! Exit colors
|
||||
void
|
||||
colorDone (void)
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#ifndef COLOROUTPUT
|
||||
#define COLOROUTPUT
|
||||
|
||||
extern char *COLOR_Reset;
|
||||
extern char *COLOR_Red;
|
||||
extern char *COLOR_Green;
|
||||
extern char *COLOR_Bold;
|
||||
|
||||
void colorInit (void);
|
||||
void colorDone (void);
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
How to compile Scyther
|
||||
|
||||
Requirements expressed as Ubuntu packages where [name][location]
|
||||
|
||||
Needed:
|
||||
|
||||
gcc
|
||||
If you don't know what this is, please stop reading.
|
||||
scons
|
||||
A Python script set to replace the make etc. toolchain.
|
||||
|
||||
For cross-compilation (Windows):
|
||||
|
||||
[mingw32][universe]
|
||||
GCC variant to compile for windows + w32 binutils.
|
||||
|
||||
Use 'scons arch=windows' to generate the binary.
|
||||
|
2164
gui/src/compiler.c
2164
gui/src/compiler.c
File diff suppressed because it is too large
Load Diff
@ -1,26 +0,0 @@
|
||||
#ifndef COMPILER
|
||||
#define COMPILER
|
||||
|
||||
#include "tac.h"
|
||||
#include "role.h"
|
||||
#include "system.h"
|
||||
|
||||
void compilerInit (const System sys);
|
||||
void compilerDone (void);
|
||||
|
||||
void compile (Tac tc, int maxruns);
|
||||
void preprocess (const System sys);
|
||||
Term findGlobalConstant (const char *s);
|
||||
Term makeGlobalConstant (const char *s);
|
||||
Term makeGlobalVariable (const char *s);
|
||||
void compute_role_variables (const System sys, Protocol p, Role r);
|
||||
|
||||
Term symbolDeclare (Symbol s, int isVar);
|
||||
void levelTacDeclaration (Tac tc, int isVar);
|
||||
|
||||
#define levelDeclareVar(s) levelTacDeclaration(s,1)
|
||||
#define levelDeclareConst(s) levelTacDeclaration(s,0)
|
||||
#define levelVar(s) symbolDeclare(s,1)
|
||||
#define levelConst(s) symbolDeclare(s,0)
|
||||
|
||||
#endif
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
cp scyther-linux ../gui/Scyther/Bin
|
||||
cp scyther-w32.exe ../gui/Scyther/Bin
|
||||
cp scyther-mac ../gui/Scyther/Bin
|
||||
|
||||
# bonus...
|
||||
cp scyther-linux ~/bin
|
||||
|
||||
echo Copied the files to their respective locations and ~/bin
|
||||
|
@ -1,74 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*@file cost.c
|
||||
*
|
||||
* Determine cost of a given semitrace in sys
|
||||
* Constructed for Arachne results, unreliable otherwise.
|
||||
*
|
||||
*/
|
||||
#include "switches.h"
|
||||
#include "system.h"
|
||||
#include "binding.h"
|
||||
#include "error.h"
|
||||
#include <limits.h>
|
||||
|
||||
//************************************************************************
|
||||
// Private methods
|
||||
//************************************************************************
|
||||
|
||||
//************************************************************************
|
||||
// Public methods
|
||||
//************************************************************************
|
||||
|
||||
//! Determine cost of an attack
|
||||
/*
|
||||
* This should also work on uncompleted semitraces, and should be monotonous
|
||||
* (i.e. further iterations should increase the cost only) so that it can be
|
||||
* used for branch and bound.
|
||||
*
|
||||
* A lower value (closer to 0) is a more feasible attack.
|
||||
*/
|
||||
int
|
||||
attackCost (const System sys)
|
||||
{
|
||||
if (switches.prune == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (switches.prune == 1)
|
||||
{
|
||||
// Select the first attack.
|
||||
// Implied by having the cost of traces after finding an attack to be always higher.
|
||||
//
|
||||
if (sys->current_claim->failed > 0)
|
||||
{
|
||||
// we already have an attack
|
||||
return INT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
// return some value relating to the cost (anything less than int_max will do)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (switches.prune == 2)
|
||||
{
|
||||
// Use nice heuristic cf. work of Gijs Hollestelle. Hand-picked parameters.
|
||||
int cost;
|
||||
|
||||
cost = 0;
|
||||
|
||||
//cost += get_semitrace_length ();
|
||||
|
||||
cost += 10 * selfInitiators (sys);
|
||||
cost += 7 * selfResponders (sys);
|
||||
cost += 10 * sys->num_regular_runs;
|
||||
cost += 3 * countInitiators (sys);
|
||||
cost += 2 * countBindingsDone ();
|
||||
cost += 1 * sys->num_intruder_runs;
|
||||
|
||||
return cost;
|
||||
}
|
||||
error ("Unknown pruning method (cost function not found)");
|
||||
return 0;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#ifndef COST
|
||||
#define COST
|
||||
|
||||
int attackCost (const System sys);
|
||||
|
||||
#endif
|
@ -1,52 +0,0 @@
|
||||
/**
|
||||
*@file debug.c
|
||||
*\brief Debugging code.
|
||||
*
|
||||
* It is hoped that this code will become redundant over time.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "debug.h"
|
||||
#include "system.h"
|
||||
#include "error.h"
|
||||
|
||||
static int debuglevel;
|
||||
|
||||
//! Set the debuglevel from the main code.
|
||||
void
|
||||
debugSet (int level)
|
||||
{
|
||||
debuglevel = level;
|
||||
}
|
||||
|
||||
//! Test whether some debuglevel is meant to be printed.
|
||||
/**
|
||||
*@param level The debuglevel
|
||||
*@return True iff level is smaller than, or equal to, the last set debuglevel.
|
||||
*\sa debugSet()
|
||||
*/
|
||||
int
|
||||
debugCond (int level)
|
||||
{
|
||||
return (level <= debuglevel);
|
||||
}
|
||||
|
||||
//! Print some debug string for some level, if desired.
|
||||
/**
|
||||
*@param level The debuglevel
|
||||
*@param string The string to be displayed for this level.
|
||||
*@return If the debuglevel is higher than the level, the string is ignored.
|
||||
* Otherwise it will be printed.
|
||||
*\sa debugCond()
|
||||
*/
|
||||
void
|
||||
debug (int level, char *string)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (debugCond (level))
|
||||
{
|
||||
indent ();
|
||||
printfstderr ("DEBUG [%i]: %s\n", level, string);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#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
|
569
gui/src/depend.c
569
gui/src/depend.c
@ -1,569 +0,0 @@
|
||||
/**
|
||||
* @file depend.c
|
||||
* \brief interface for graph code from the viewpoint of events.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "depend.h"
|
||||
#include "term.h"
|
||||
#include "system.h"
|
||||
#include "binding.h"
|
||||
#include "warshall.h"
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* Generic structures
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
//! Event dependency structure
|
||||
struct depeventgraph
|
||||
{
|
||||
//! Flag denoting what it was made for (newrun|newbinding)
|
||||
int fornewrun;
|
||||
//! Number of runs;
|
||||
int runs;
|
||||
//! System where it derives from
|
||||
System sys;
|
||||
//! Number of nodes
|
||||
int n;
|
||||
//! Rowsize
|
||||
int rowsize;
|
||||
//! Graph structure
|
||||
unsigned int *G;
|
||||
//! Zombie dummy push
|
||||
int zombie;
|
||||
//! Previous graph
|
||||
struct depeventgraph *prev;
|
||||
};
|
||||
|
||||
//! Pointer shorthard
|
||||
typedef struct depeventgraph *Depeventgraph;
|
||||
|
||||
/*
|
||||
* External
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
extern Protocol INTRUDER; //!< The intruder protocol
|
||||
extern Role I_M; //!< special role; precedes all other events always
|
||||
|
||||
/*
|
||||
* Globals
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Depeventgraph currentdepgraph;
|
||||
|
||||
/*
|
||||
* Default code
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//! Default init
|
||||
void
|
||||
dependInit (const System sys)
|
||||
{
|
||||
currentdepgraph = NULL;
|
||||
}
|
||||
|
||||
//! Pring
|
||||
void
|
||||
dependPrint ()
|
||||
{
|
||||
Depeventgraph dg;
|
||||
|
||||
eprintf ("Printing DependEvent stack, top first.\n\n");
|
||||
for (dg = currentdepgraph; dg != NULL; dg = dg->prev)
|
||||
{
|
||||
eprintf ("%i nodes, %i rowsize, %i zombies, %i runs: created for new ",
|
||||
dg->n, dg->rowsize, dg->zombie, dg->runs);
|
||||
if (dg->fornewrun)
|
||||
{
|
||||
eprintf ("run");
|
||||
}
|
||||
else
|
||||
{
|
||||
eprintf ("binding");
|
||||
}
|
||||
eprintf ("\n");
|
||||
}
|
||||
eprintf ("\n");
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int n1;
|
||||
int r1;
|
||||
int o1;
|
||||
|
||||
r1 = 0;
|
||||
o1 = 0;
|
||||
eprintf ("Printing dependency graph.\n");
|
||||
eprintf ("Y axis nodes comes before X axis node.\n");
|
||||
for (n1 = 0; n1 < nodeCount (); n1++)
|
||||
{
|
||||
int n2;
|
||||
int r2;
|
||||
int o2;
|
||||
|
||||
if ((n1 - o1) >= currentdepgraph->sys->runs[r1].rolelength)
|
||||
{
|
||||
o1 += currentdepgraph->sys->runs[r1].rolelength;
|
||||
r1++;
|
||||
eprintf ("\n");
|
||||
}
|
||||
r2 = 0;
|
||||
o2 = 0;
|
||||
eprintf ("%5i : ", n1);
|
||||
for (n2 = 0; n2 < nodeCount (); n2++)
|
||||
{
|
||||
if ((n2 - o2) >= currentdepgraph->sys->runs[r2].rolelength)
|
||||
{
|
||||
o2 += currentdepgraph->sys->runs[r2].rolelength;
|
||||
r2++;
|
||||
eprintf (" ");
|
||||
}
|
||||
eprintf ("%i", getNode (n1, n2));
|
||||
}
|
||||
eprintf ("\n");
|
||||
|
||||
}
|
||||
eprintf ("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Default cleanup
|
||||
void
|
||||
dependDone (const System sys)
|
||||
{
|
||||
if (currentdepgraph != NULL)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("\n\n");
|
||||
dependPrint ();
|
||||
globalError--;
|
||||
error
|
||||
("depgraph stack (depend.c) not empty at dependDone, bad iteration?");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Libs
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//! Convert from event to node in a graph (given that sys is set)
|
||||
int
|
||||
eventtonode (const Depeventgraph dgx, const int r, const int e)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < dgx->sys->maxruns; i++)
|
||||
{
|
||||
if (i == r)
|
||||
{
|
||||
// this run
|
||||
#ifdef DEBUG
|
||||
if (dgx->sys->runs[i].rolelength <= e)
|
||||
{
|
||||
error ("Bad offset for eventtonode");
|
||||
}
|
||||
#endif
|
||||
return (n + e);
|
||||
}
|
||||
else
|
||||
{
|
||||
// not this run, add offset
|
||||
n += dgx->sys->runs[i].rolelength;
|
||||
}
|
||||
}
|
||||
error ("Bad offset (run number too high?) for eventtonode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Return the number of nodes in a graph
|
||||
int
|
||||
countnodes (const Depeventgraph dgx)
|
||||
{
|
||||
int i;
|
||||
int nodes;
|
||||
|
||||
nodes = 0;
|
||||
for (i = 0; i < dgx->sys->maxruns; i++)
|
||||
{
|
||||
nodes += dgx->sys->runs[i].rolelength;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
//! Graph size given the number of nodes
|
||||
unsigned int
|
||||
getGraphSize (const Depeventgraph dgx)
|
||||
{
|
||||
return (dgx->n * dgx->rowsize);
|
||||
}
|
||||
|
||||
//! Create graph from sys
|
||||
Depeventgraph
|
||||
dependCreate (const System sys)
|
||||
{
|
||||
Depeventgraph dgnew;
|
||||
|
||||
dgnew = (Depeventgraph) MALLOC (sizeof (struct depeventgraph));
|
||||
dgnew->sys = sys;
|
||||
dgnew->fornewrun = true;
|
||||
dgnew->runs = sys->maxruns;
|
||||
dgnew->zombie = 0;
|
||||
dgnew->prev = NULL;
|
||||
dgnew->n = countnodes (dgnew); // count nodes works on ->sys
|
||||
dgnew->rowsize = WORDSIZE (dgnew->n);
|
||||
dgnew->G = (unsigned int *) CALLOC (1, getGraphSize (dgnew) * sizeof (unsigned int)); // works on ->n and ->rowsize
|
||||
|
||||
return dgnew;
|
||||
}
|
||||
|
||||
//! Copy graph from current one
|
||||
Depeventgraph
|
||||
dependCopy (const Depeventgraph dgold)
|
||||
{
|
||||
Depeventgraph dgnew;
|
||||
|
||||
// Copy old to new
|
||||
dgnew = (Depeventgraph) MALLOC (sizeof (struct depeventgraph));
|
||||
memcpy ((void *) dgnew, (void *) dgold,
|
||||
(size_t) sizeof (struct depeventgraph));
|
||||
|
||||
// New copy
|
||||
dgnew->fornewrun = false;
|
||||
dgnew->zombie = 0;
|
||||
|
||||
// copy inner graph
|
||||
dgnew->G =
|
||||
(unsigned int *) MALLOC (getGraphSize (dgold) * sizeof (unsigned int));
|
||||
memcpy ((void *) dgnew->G, (void *) dgold->G,
|
||||
getGraphSize (dgold) * sizeof (unsigned int));
|
||||
|
||||
return dgnew;
|
||||
}
|
||||
|
||||
//! Destroy graph
|
||||
void
|
||||
dependDestroy (const Depeventgraph dgold)
|
||||
{
|
||||
FREE (dgold->G);
|
||||
FREE (dgold);
|
||||
}
|
||||
|
||||
//! push graph to stack (generic)
|
||||
void
|
||||
dependPushGeneric (Depeventgraph dgnew)
|
||||
{
|
||||
dgnew->prev = currentdepgraph;
|
||||
currentdepgraph = dgnew;
|
||||
}
|
||||
|
||||
//! restore graph from stack (generic)
|
||||
void
|
||||
dependPopGeneric (void)
|
||||
{
|
||||
Depeventgraph dgprev;
|
||||
|
||||
dgprev = currentdepgraph->prev;
|
||||
dependDestroy (currentdepgraph);
|
||||
currentdepgraph = dgprev;
|
||||
}
|
||||
|
||||
// Dependencies from role order
|
||||
void
|
||||
dependDefaultRoleOrder (void)
|
||||
{
|
||||
int r;
|
||||
|
||||
for (r = 0; r < currentdepgraph->sys->maxruns; r++)
|
||||
{
|
||||
int e;
|
||||
|
||||
for (e = 1; e < currentdepgraph->sys->runs[r].rolelength; e++)
|
||||
{
|
||||
setDependEvent (r, e - 1, r, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dependencies fro bindings order
|
||||
void
|
||||
dependDefaultBindingOrder (void)
|
||||
{
|
||||
List bl;
|
||||
|
||||
for (bl = currentdepgraph->sys->bindings; bl != NULL; bl = bl->next)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
if (valid_binding (b))
|
||||
{
|
||||
int r1, e1, r2, e2;
|
||||
|
||||
r1 = b->run_from;
|
||||
e1 = b->ev_from;
|
||||
r2 = b->run_to;
|
||||
e2 = b->ev_to;
|
||||
if (!((r1 == r2) && (e1 == e2)))
|
||||
{
|
||||
// Not a self-binding
|
||||
setDependEvent (r1, e1, r2, e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Construct graph dependencies from sys
|
||||
/**
|
||||
* uses currentdepgraph->sys
|
||||
*/
|
||||
void
|
||||
dependFromSys (void)
|
||||
{
|
||||
dependDefaultRoleOrder ();
|
||||
dependDefaultBindingOrder ();
|
||||
}
|
||||
|
||||
//! Detect whether the graph has a cycle. If so, a node can get to itself (through the cycle)
|
||||
int
|
||||
hasCycle ()
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < currentdepgraph->n; n++)
|
||||
{
|
||||
if (getNode (n, n))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public Code
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//! get node
|
||||
int
|
||||
getNode (const int n1, const int n2)
|
||||
{
|
||||
return BIT (currentdepgraph->G + currentdepgraph->rowsize * n1, n2);
|
||||
}
|
||||
|
||||
//! set node
|
||||
void
|
||||
setNode (const int n1, const int n2)
|
||||
{
|
||||
SETBIT (currentdepgraph->G + currentdepgraph->rowsize * n1, n2);
|
||||
}
|
||||
|
||||
//! Count nodes
|
||||
int
|
||||
nodeCount (void)
|
||||
{
|
||||
return countnodes (currentdepgraph);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple setting
|
||||
*/
|
||||
void
|
||||
setDependEvent (const int r1, const int e1, const int r2, const int e2)
|
||||
{
|
||||
int n1, n2;
|
||||
|
||||
n1 = eventtonode (currentdepgraph, r1, e1);
|
||||
n2 = eventtonode (currentdepgraph, r2, e2);
|
||||
setNode (n1, n2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple testing
|
||||
*/
|
||||
int
|
||||
isDependEvent (const int r1, const int e1, const int r2, const int e2)
|
||||
{
|
||||
int n1, n2;
|
||||
|
||||
n1 = eventtonode (currentdepgraph, r1, e1);
|
||||
n2 = eventtonode (currentdepgraph, r2, e2);
|
||||
return getNode (n1, n2);
|
||||
}
|
||||
|
||||
//! create new graph after adding runs or events (new number of nodes)
|
||||
void
|
||||
dependPushRun (const System sys)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug (5, "Push dependGraph for new run\n");
|
||||
#endif
|
||||
dependPushGeneric (dependCreate (sys));
|
||||
dependFromSys ();
|
||||
}
|
||||
|
||||
//! restore graph to state after previous run add
|
||||
void
|
||||
dependPopRun (void)
|
||||
{
|
||||
if (!currentdepgraph->fornewrun)
|
||||
{
|
||||
globalError++;
|
||||
dependPrint ();
|
||||
globalError--;
|
||||
error ("Trying to pop graph created for new binding.");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
debug (5, "Pop dependGraph for new run\n");
|
||||
#endif
|
||||
dependPopGeneric ();
|
||||
}
|
||||
|
||||
//! create new graph by adding event bindings
|
||||
/*
|
||||
* The push code returns true or false: if false, the operation fails because
|
||||
* it there is now a cycle in the graph, and there is no need to pop the
|
||||
* result.
|
||||
*/
|
||||
int
|
||||
dependPushEvent (const int r1, const int e1, const int r2, const int e2)
|
||||
{
|
||||
if (isDependEvent (r2, e2, r1, e1))
|
||||
{
|
||||
// Adding would imply a cycle, so we won't do that.
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (3))
|
||||
{
|
||||
eprintf ("Cycle detected for binding %i,%i -> %i,%i.\n", r1, e1, r2,
|
||||
e2);
|
||||
}
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
dependPrint ();
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No immediate cycle: new graph, return true TODO disabled
|
||||
if ((1 == 1) && (((r1 == r2) && (e1 == e2))
|
||||
|| isDependEvent (r1, e1, r2, e2)))
|
||||
{
|
||||
// if n->n or the binding already existed, no changes
|
||||
// no change: add zombie
|
||||
currentdepgraph->zombie += 1;
|
||||
#ifdef DEBUG
|
||||
debug (5, "Push dependGraph for new event (zombie push)\n");
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("r%ii%i --> r%ii%i\n", r1, e1, r2, e2);
|
||||
globalError--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// change: make new graph copy of the old one
|
||||
dependPushGeneric (dependCopy (currentdepgraph));
|
||||
// add new binding
|
||||
setDependEvent (r1, e1, r2, e2);
|
||||
// recompute closure
|
||||
transitive_closure (currentdepgraph->G, currentdepgraph->n);
|
||||
// check for cycles
|
||||
if (hasCycle ())
|
||||
{
|
||||
//warning ("Cycle slipped undetected by the reverse check.");
|
||||
// Closure introduced cycle, undo it
|
||||
dependPopEvent ();
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
debug (5, "Push dependGraph for new event (real push)\n");
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("r%ii%i --> r%ii%i\n", r1, e1, r2, e2);
|
||||
globalError--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//! restore graph to state before previous binding add
|
||||
void
|
||||
dependPopEvent (void)
|
||||
{
|
||||
if (currentdepgraph->zombie > 0)
|
||||
{
|
||||
// zombie pushed
|
||||
#ifdef DEBUG
|
||||
debug (5, "Pop dependGraph for new event (zombie pop)\n");
|
||||
#endif
|
||||
currentdepgraph->zombie -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentdepgraph->fornewrun)
|
||||
{
|
||||
globalError++;
|
||||
dependPrint ();
|
||||
globalError--;
|
||||
error ("Trying to pop graph created for new run.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// real graph
|
||||
#ifdef DEBUG
|
||||
debug (5, "Pop dependGraph for new event (real pop)\n");
|
||||
#endif
|
||||
dependPopGeneric ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Current event to node
|
||||
int
|
||||
eventNode (const int r, const int e)
|
||||
{
|
||||
return eventtonode (currentdepgraph, r, e);
|
||||
}
|
||||
|
||||
//! Iterate over any preceding events
|
||||
int
|
||||
iteratePrecedingEvents (const System sys, int (*func) (int run, int ev),
|
||||
const int run, const int ev)
|
||||
{
|
||||
int run2;
|
||||
|
||||
for (run2 = 0; run2 < sys->maxruns; run2++)
|
||||
{
|
||||
int ev2;
|
||||
|
||||
for (ev2 = 0; ev2 < sys->runs[run2].step; ev2++)
|
||||
{
|
||||
if (isDependEvent (run2, ev2, run, ev))
|
||||
{
|
||||
if (!func (run2, ev2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#ifndef DEPEND
|
||||
#define DEPEND
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/*
|
||||
* The code here mainly involves an interface for creating graphs etc., but
|
||||
* most of it is implicit: we just add dependencies/runs and undo them again
|
||||
* later.
|
||||
*/
|
||||
|
||||
void dependInit (const System sys);
|
||||
void dependPrint ();
|
||||
void dependDone (const System sys);
|
||||
|
||||
/*
|
||||
* The push code returns true or false: if false, the operation fails because
|
||||
* it there is now a cycle in the graph, and there is no need to pop the
|
||||
* result.
|
||||
*/
|
||||
void dependPushRun (const System sys);
|
||||
void dependPopRun ();
|
||||
int dependPushEvent (const int r1, const int e1, const int r2, const int e2);
|
||||
void dependPopEvent ();
|
||||
|
||||
/*
|
||||
* Test/set
|
||||
*/
|
||||
|
||||
int getNode (const int n1, const int n2);
|
||||
void setNode (const int n1, const int n2);
|
||||
int isDependEvent (const int r1, const int e1, const int r2, const int e2);
|
||||
void setDependEvent (const int r1, const int e1, const int r2, const int e2);
|
||||
|
||||
/*
|
||||
* Outside helpers
|
||||
*/
|
||||
int hasCycle ();
|
||||
int eventNode (const int r, const int e);
|
||||
int nodeCount (void);
|
||||
int iteratePrecedingEvents (const System sys, int (*func) (int run, int ev),
|
||||
const int run, const int ev);
|
||||
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
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)
|
||||
|
||||
|
||||
|
1814
gui/src/dotout.c
1814
gui/src/dotout.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
#ifndef DOTOUTPUT
|
||||
#define DOTOUTPUT
|
||||
|
||||
void dotSemiState (const System sys);
|
||||
|
||||
#endif
|
@ -1,94 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "error.h"
|
||||
|
||||
//! Die from error with exit code
|
||||
void
|
||||
error_die (void)
|
||||
{
|
||||
exit (EXIT_ERROR);
|
||||
}
|
||||
|
||||
//! print to stderror (must be generic to capture linux variants)
|
||||
void
|
||||
vprintfstderr (char *fmt, va_list args)
|
||||
{
|
||||
#ifdef USESTDERR
|
||||
vfprintf (stderr, fmt, args);
|
||||
#else
|
||||
// no alternative yet
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
printfstderr (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
vprintfstderr (fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
//! Print error message header
|
||||
/**
|
||||
* Adapted from [K&R2], p. 174
|
||||
*@todo It would be nice to redirect all output to stderr, which would enable use of termprint etc.
|
||||
*/
|
||||
void
|
||||
error_pre (void)
|
||||
{
|
||||
printfstderr ("error: ");
|
||||
}
|
||||
|
||||
//! Print post-error message and die.
|
||||
/**
|
||||
* Adapted from [K&R2], p. 174
|
||||
* Input is comparable to printf, only end of line is not required.
|
||||
*/
|
||||
void
|
||||
error_post (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
vprintfstderr (fmt, args);
|
||||
printfstderr ("\n");
|
||||
va_end (args);
|
||||
exit (EXIT_ERROR);
|
||||
}
|
||||
|
||||
//! Print error message and die.
|
||||
/**
|
||||
* Adapted from [K&R2], p. 174
|
||||
* Input is comparable to printf, only end of line is not required.
|
||||
*/
|
||||
void
|
||||
error (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
error_pre ();
|
||||
va_start (args, fmt);
|
||||
vprintfstderr (fmt, args);
|
||||
printfstderr ("\n");
|
||||
va_end (args);
|
||||
error_die ();
|
||||
}
|
||||
|
||||
//! Print warning
|
||||
/**
|
||||
* Input is comparable to printf, only end of line is not required.
|
||||
*/
|
||||
void
|
||||
warning (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
printfstderr ("warning: ");
|
||||
vprintfstderr (fmt, args);
|
||||
printfstderr ("\n");
|
||||
va_end (args);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#ifndef ERROR
|
||||
#define ERROR
|
||||
|
||||
//! usestderr is defined iff we use it
|
||||
#define USESTDERR
|
||||
|
||||
//! Types of exit codes
|
||||
enum exittypes
|
||||
{ EXIT_NOATTACK = 0, EXIT_ERROR = 1, EXIT_ATTACK = 3 };
|
||||
|
||||
void vprintfstderr (char *fmt, va_list args);
|
||||
void printfstderr (char *fmt, ...);
|
||||
void error_die (void);
|
||||
void error_pre (void);
|
||||
void error_post (char *fmt, ...);
|
||||
void error (char *fmt, ...);
|
||||
void warning (char *fmt, ...);
|
||||
|
||||
#endif
|
@ -1,4 +0,0 @@
|
||||
Test file to see whether it works.
|
||||
Wow.
|
||||
New line.
|
||||
And a better conflict should start here.
|
@ -1,399 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*@file heuristic.c
|
||||
*
|
||||
* Heuristics code for Arachne method
|
||||
*
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "binding.h"
|
||||
#include "system.h"
|
||||
#include "specialterm.h"
|
||||
#include "switches.h"
|
||||
#include "hidelevel.h"
|
||||
#include "arachne.h"
|
||||
#include "error.h"
|
||||
|
||||
//! Check whether a binding (goal) is selectable
|
||||
int
|
||||
is_goal_selectable (const Binding b)
|
||||
{
|
||||
if (b != NULL)
|
||||
{
|
||||
if ((!b->blocked) && (!b->done))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Count selectable goals
|
||||
int
|
||||
count_selectable_goals (const System sys)
|
||||
{
|
||||
List bl;
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
bl = sys->bindings;
|
||||
while (bl != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
if (is_goal_selectable (b))
|
||||
{
|
||||
n++;
|
||||
}
|
||||
bl = bl->next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
//! Return first selectable goal in the list
|
||||
/**
|
||||
* The return list entry is either NULL, or a selectable goal.
|
||||
*/
|
||||
List
|
||||
first_selectable_goal (List bl)
|
||||
{
|
||||
while (bl != NULL && !is_goal_selectable ((Binding) bl->data))
|
||||
{
|
||||
bl = bl->next;
|
||||
}
|
||||
return bl;
|
||||
}
|
||||
|
||||
//! Determine whether a term is an open nonce variable
|
||||
/**
|
||||
* Does not explore subterms
|
||||
*/
|
||||
int
|
||||
isOpenNonceVar (Term t)
|
||||
{
|
||||
t = deVar (t);
|
||||
if (realTermVariable (t))
|
||||
{
|
||||
return inTermlist (t->stype, TERM_Nonce);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! Count unique open variables in term
|
||||
/**
|
||||
*/
|
||||
int
|
||||
count_open_variables (const Term t)
|
||||
{
|
||||
Termlist tl;
|
||||
int n;
|
||||
|
||||
tl = NULL;
|
||||
termlistAddVariables (tl, t);
|
||||
n = 0;
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (!inTermlist (tl->next, t))
|
||||
{
|
||||
if (isOpenNonceVar (t))
|
||||
{
|
||||
n = n + 1;
|
||||
}
|
||||
}
|
||||
tl = tl->next;
|
||||
}
|
||||
termlistDelete (tl);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Athena-like factor
|
||||
/**
|
||||
* Lower is better (more nonce variables)
|
||||
*/
|
||||
float
|
||||
term_noncevariables_level (const Term t)
|
||||
{
|
||||
int onv;
|
||||
const int enough = 2;
|
||||
|
||||
onv = count_open_variables (t);
|
||||
if (onv >= enough)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 - (onv / enough);
|
||||
}
|
||||
}
|
||||
|
||||
//! Determine weight based on hidelevel
|
||||
float
|
||||
weighHidelevel (const System sys, const Term t, const float massknow,
|
||||
const float massprot)
|
||||
{
|
||||
switch (hidelevelFlag (sys, t))
|
||||
{
|
||||
case HLFLAG_NONE:
|
||||
return 0;
|
||||
case HLFLAG_KNOW:
|
||||
return massknow;
|
||||
case HLFLAG_PROT:
|
||||
return massprot;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! newkeylevel (weighted)
|
||||
int
|
||||
newkeylevel (const int level)
|
||||
{
|
||||
// keylevel is from { -1,0,1 } where -1 means delay
|
||||
if (level == 1)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! count local constants
|
||||
float
|
||||
term_constcount (const System sys, Term t)
|
||||
{
|
||||
int n, total;
|
||||
float ratio;
|
||||
|
||||
int countMe (Term t)
|
||||
{
|
||||
if (TermRunid (t) >= 0)
|
||||
{
|
||||
total++;
|
||||
if (!isTermVariable (t))
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
total = 0;
|
||||
term_iterate_deVar (t, countMe, NULL, NULL, NULL);
|
||||
if (total == 0)
|
||||
{
|
||||
ratio = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ratio = ((total - n) / total);
|
||||
}
|
||||
return ratio;
|
||||
}
|
||||
|
||||
//! Determine the weight of a given goal
|
||||
/**
|
||||
* 0 to ... (lower is better)
|
||||
*
|
||||
* --heuristic has two distint interpretations. If it is 0 or greater, it a
|
||||
* selection mask. If it is smaller than 0, it is some special tactic.
|
||||
*
|
||||
* selection masks for --select-goal
|
||||
* 1: constrain level of term
|
||||
* 2: key or not
|
||||
* 4: consequences determination
|
||||
* 8: select also single variables (that are not role variables)
|
||||
* 16: single variables are better
|
||||
* 32: incorporate keylevel information
|
||||
*
|
||||
* special tactics for --select-goal
|
||||
* -1: random goal selection
|
||||
*
|
||||
*/
|
||||
float
|
||||
computeGoalWeight (const System sys, const Binding b)
|
||||
{
|
||||
float w;
|
||||
int smode;
|
||||
Term t;
|
||||
|
||||
void erode (const float deltaw)
|
||||
{
|
||||
if (smode & 1)
|
||||
{
|
||||
w = w + deltaw;
|
||||
}
|
||||
smode = smode / 2;
|
||||
}
|
||||
|
||||
// Total weight
|
||||
w = 0;
|
||||
// We will shift this mode variable
|
||||
smode = switches.heuristic;
|
||||
t = b->term;
|
||||
|
||||
// Determine buf_constrain levels
|
||||
// Bit 0: 1 use hidelevel
|
||||
erode (2 * weighHidelevel (sys, t, 0.5, 0.5));
|
||||
// Bit 1: 2 key level (inverted)
|
||||
erode (0.5 * (1 - b->level));
|
||||
// Bit 2: 4 constrain level
|
||||
erode (term_constrain_level (t));
|
||||
// Bit 3: 8 nonce variables level (Cf. what I think is in Athena)
|
||||
erode (term_noncevariables_level (t));
|
||||
|
||||
// Bit 4: 16 use hidelevel (normal)
|
||||
erode (1 * weighHidelevel (sys, t, 0.5, 0.5));
|
||||
// Bit 5: 32 use known nonces (Athena try 2)
|
||||
erode (term_constcount (sys, t));
|
||||
|
||||
// Bit 6: 64 use hidelevel (but only single-weight)
|
||||
erode (weighHidelevel (sys, t, 0.5, 0.5));
|
||||
// Bit 7: 128 use hidelevel (quadruple-weight)
|
||||
erode (4 * weighHidelevel (sys, t, 0.5, 0.5));
|
||||
|
||||
// Bit 8: 256 use known nonces (Athena try 2), half weight
|
||||
erode (0.5 * term_constcount (sys, t));
|
||||
|
||||
// Define legal range
|
||||
if (smode > 0)
|
||||
error ("--heuristic mode %i is illegal", switches.heuristic);
|
||||
|
||||
// Return
|
||||
return w;
|
||||
}
|
||||
|
||||
//! Goal selection
|
||||
/**
|
||||
* Selects the most constrained goal.
|
||||
*
|
||||
* Because the list starts with the newest terms, and we use <= (as opposed to <), we
|
||||
* ensure that for goals with equal constraint levels, we select the oldest one.
|
||||
*
|
||||
*/
|
||||
Binding
|
||||
select_goal_masked (const System sys)
|
||||
{
|
||||
List bl;
|
||||
Binding best;
|
||||
float best_weight;
|
||||
|
||||
// Find the most constrained goal
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Listing open goals that might be chosen: ");
|
||||
}
|
||||
best_weight = FLT_MAX;
|
||||
best = NULL;
|
||||
bl = sys->bindings;
|
||||
while (bl != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = (Binding) bl->data;
|
||||
|
||||
// Only if not done and not blocked
|
||||
if (is_goal_selectable (b))
|
||||
{
|
||||
if (!isTermVariable (b->term))
|
||||
{
|
||||
float w;
|
||||
|
||||
w = computeGoalWeight (sys, b);
|
||||
|
||||
// Spacing between output
|
||||
if (switches.output == PROOF && best != NULL)
|
||||
eprintf (", ");
|
||||
|
||||
// Better alternative?
|
||||
if (w <= best_weight)
|
||||
{
|
||||
best_weight = w;
|
||||
best = b;
|
||||
if (switches.output == PROOF)
|
||||
eprintf ("*");
|
||||
}
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
termPrint (b->term);
|
||||
eprintf ("<%.2f>", w);
|
||||
}
|
||||
}
|
||||
}
|
||||
bl = bl->next;
|
||||
}
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
if (best == NULL)
|
||||
eprintf ("none");
|
||||
eprintf ("\n");
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
//! Goal selection special case -1: random
|
||||
/**
|
||||
* Simply picks an open goal randomly. Has to be careful to skip singular stuff etc.
|
||||
*/
|
||||
Binding
|
||||
select_goal_random (const System sys)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = count_selectable_goals (sys);
|
||||
if (n > 0)
|
||||
{
|
||||
int choice;
|
||||
List bl;
|
||||
|
||||
// Choose a random goal between 0 and n
|
||||
choice = rand () % n;
|
||||
|
||||
// Fetch it
|
||||
bl = sys->bindings;
|
||||
while (choice >= 0)
|
||||
{
|
||||
bl = first_selectable_goal (bl);
|
||||
if (bl == NULL)
|
||||
{
|
||||
error ("Random chooser selected a NULL goal.");
|
||||
}
|
||||
choice--;
|
||||
}
|
||||
return (Binding) bl->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Binding) NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//! Goal selection function, generic
|
||||
Binding
|
||||
select_goal (const System sys)
|
||||
{
|
||||
if (switches.heuristic >= 0)
|
||||
{
|
||||
// Masked
|
||||
return select_goal_masked (sys);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special cases
|
||||
switch (switches.heuristic)
|
||||
{
|
||||
case -1:
|
||||
return select_goal_random (sys);
|
||||
}
|
||||
error ("Unknown value (<0) for --goal-select.");
|
||||
}
|
||||
return (Binding) NULL;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef HEURISTIC
|
||||
#define HEURISTIC
|
||||
|
||||
#include "system.h"
|
||||
#include "binding.h"
|
||||
|
||||
Binding select_goal (const System sys);
|
||||
|
||||
#endif
|
@ -1,261 +0,0 @@
|
||||
/** @file hidelevel.c \brief Hidelevel lemma base functions.
|
||||
*
|
||||
* The Hidelevel lemma is fairly complex and so it requires some buffering,
|
||||
* instead of fully recomputing the required data each time again.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include "hidelevel.h"
|
||||
#include "system.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern Term TERM_Hidden;
|
||||
|
||||
//! hide level within protocol
|
||||
unsigned int
|
||||
protocolHidelevel (const System sys, const Term t)
|
||||
{
|
||||
unsigned int minlevel;
|
||||
|
||||
int itsends (const Protocol p, const Role r)
|
||||
{
|
||||
int sends (Roledef rd)
|
||||
{
|
||||
if (rd->type == SEND)
|
||||
{
|
||||
unsigned int l;
|
||||
|
||||
l = termHidelevel (t, rd->from);
|
||||
if (l < minlevel)
|
||||
minlevel = l;
|
||||
l = termHidelevel (t, rd->to);
|
||||
if (l < minlevel)
|
||||
minlevel = l;
|
||||
l = termHidelevel (t, rd->message);
|
||||
if (l < minlevel)
|
||||
minlevel = l;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
roledef_iterate_events (r->roledef, sends);
|
||||
return true;
|
||||
}
|
||||
|
||||
minlevel = INT_MAX;
|
||||
iterateRoles (sys, itsends);
|
||||
|
||||
return minlevel;
|
||||
}
|
||||
|
||||
//! hide level within initial knowledge
|
||||
unsigned int
|
||||
knowledgeHidelevel (const System sys, const Term t)
|
||||
{
|
||||
unsigned int minlevel;
|
||||
Termlist tl;
|
||||
|
||||
minlevel = INT_MAX;
|
||||
tl = knowledgeSet (sys->know);
|
||||
while (tl != NULL)
|
||||
{
|
||||
unsigned int l;
|
||||
|
||||
l = termHidelevel (t, tl->term);
|
||||
if (l < minlevel)
|
||||
{
|
||||
minlevel = l;
|
||||
}
|
||||
tl = tl->next;
|
||||
}
|
||||
termlistDelete (tl);
|
||||
|
||||
return minlevel;
|
||||
}
|
||||
|
||||
//! Check hide levels
|
||||
void
|
||||
hidelevelCompute (const System sys)
|
||||
{
|
||||
Termlist tl;
|
||||
|
||||
sys->hidden = NULL;
|
||||
tl = sys->globalconstants;
|
||||
|
||||
// Add 'hidden' terms
|
||||
tl = termlistAdd (tl, TERM_Hidden);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (4))
|
||||
{
|
||||
eprintf ("Global constants: ");
|
||||
termlistPrint (tl);
|
||||
eprintf ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (tl != NULL)
|
||||
{
|
||||
unsigned int l1, l2, l;
|
||||
|
||||
l1 = knowledgeHidelevel (sys, tl->term);
|
||||
l2 = protocolHidelevel (sys, tl->term);
|
||||
if (l1 < l2)
|
||||
{
|
||||
l = l1;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = l2;
|
||||
}
|
||||
|
||||
// Interesting only if higher than zero
|
||||
if (l > 0)
|
||||
{
|
||||
Hiddenterm ht;
|
||||
|
||||
ht = (Hiddenterm) malloc (sizeof (struct hiddenterm));
|
||||
ht->term = tl->term;
|
||||
ht->hideminimum = l;
|
||||
ht->hideprotocol = l2;
|
||||
ht->hideknowledge = l1;
|
||||
ht->next = sys->hidden;
|
||||
sys->hidden = ht;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
eprintf ("Added possibly interesting term: ");
|
||||
termPrint (tl->term);
|
||||
eprintf ("; know %i, prot %i\n", l1, l2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
tl = tl->next;
|
||||
}
|
||||
}
|
||||
|
||||
//! Determine flag from parameters
|
||||
unsigned int
|
||||
hidelevelParamFlag (unsigned int l, unsigned int lmin, unsigned int lprot,
|
||||
unsigned int lknow)
|
||||
{
|
||||
// Given the parameters, determine where the term with hidelevel l could be generated from.
|
||||
if (l < lmin)
|
||||
{
|
||||
return HLFLAG_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// One should work (at least)
|
||||
if (l < lprot)
|
||||
{
|
||||
// Know should be possible
|
||||
return HLFLAG_KNOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prot can, know also?
|
||||
if (l < lknow)
|
||||
{
|
||||
// Nope, just prot
|
||||
return HLFLAG_PROT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Both
|
||||
return HLFLAG_BOTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Given a term, iterate over all factors
|
||||
int
|
||||
iterate_interesting (const System sys, const Term goalterm, int (*func) ())
|
||||
{
|
||||
Hiddenterm ht;
|
||||
|
||||
ht = sys->hidden;
|
||||
while (ht != NULL)
|
||||
{
|
||||
unsigned int l;
|
||||
// Test the goalterm for occurrences of this
|
||||
|
||||
l = termHidelevel (ht->term, goalterm);
|
||||
if (l < INT_MAX)
|
||||
{
|
||||
if (!func (l, ht->hideminimum, ht->hideprotocol, ht->hideknowledge))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ht = ht->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Determine whether a goal might be interesting from the viewpoint of hide levels (the highest minimum is best)
|
||||
int
|
||||
hidelevelInteresting (const System sys, const Term goalterm)
|
||||
{
|
||||
int uninteresting (unsigned int l, unsigned int lmin, unsigned int lprot,
|
||||
unsigned int lknow)
|
||||
{
|
||||
if (lmin > 0)
|
||||
{
|
||||
// anything higher than usual is interesting :)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return !iterate_interesting (sys, goalterm, uninteresting);
|
||||
}
|
||||
|
||||
//! Determine whether a goal is impossible to satisfy because of the hidelevel lemma.
|
||||
int
|
||||
hidelevelImpossible (const System sys, const Term goalterm)
|
||||
{
|
||||
int possible (unsigned int l, unsigned int lmin, unsigned int lprot,
|
||||
unsigned int lknow)
|
||||
{
|
||||
if (l < lmin)
|
||||
{
|
||||
// impossible, abort!
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return !iterate_interesting (sys, goalterm, possible);
|
||||
}
|
||||
|
||||
//! Return flag on the basis of the Hidelevel lemma
|
||||
unsigned int
|
||||
hidelevelFlag (const System sys, const Term goalterm)
|
||||
{
|
||||
unsigned int flag;
|
||||
|
||||
int getflag (unsigned int l, unsigned int lmin, unsigned int lprot,
|
||||
unsigned int lknow)
|
||||
{
|
||||
// Determine new flag
|
||||
flag = flag | hidelevelParamFlag (l, lmin, lprot, lknow);
|
||||
|
||||
// Should we proceed?
|
||||
if (flag == HLFLAG_NONE)
|
||||
{
|
||||
// abort iteration: it cannot get worse
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
flag = HLFLAG_BOTH;
|
||||
iterate_interesting (sys, goalterm, getflag);
|
||||
return flag;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#ifndef HIDELEVELS
|
||||
#define HIDELEVELS
|
||||
|
||||
#include "term.h"
|
||||
#include "system.h"
|
||||
|
||||
/*
|
||||
* Flags for hidelevel lemma
|
||||
*
|
||||
* Use binary or (|) to compose results: by default, a term can be satisfied by
|
||||
* both the protocol and the initial knowledge.
|
||||
*/
|
||||
#define HLFLAG_BOTH 0
|
||||
#define HLFLAG_KNOW 1
|
||||
#define HLFLAG_PROT 2
|
||||
#define HLFLAG_NONE 3
|
||||
|
||||
/*
|
||||
* The structure hiddenterm/Hiddenterm is defined in system.h
|
||||
*/
|
||||
|
||||
void hidelevelCompute (const System sys);
|
||||
int hidelevelInteresting (const System sys, const Term goalterm);
|
||||
int hidelevelImpossible (const System sys, const Term goalterm);
|
||||
unsigned int hidelevelFlag (const System sys, const Term goalterm);
|
||||
|
||||
#endif
|
@ -1,31 +0,0 @@
|
||||
Implemented:
|
||||
|
||||
- scans
|
||||
- test functions (in hidelevel.c)
|
||||
|
||||
TODO:
|
||||
|
||||
- use test functions (impossible for pruning, interesting for goal selection heuristic)
|
||||
- state count display switch for comparisons
|
||||
- consider adding info for goal stuff (only from M_0, not by create)
|
||||
|
||||
*******************************************************************
|
||||
|
||||
roivas:~scyther% ./scyther ccitt509-1c.spdl
|
||||
Global constants: [te, ne, Eve, Bob, Alice, unhash, sk, hash, pk]
|
||||
|
||||
Possibly interesting term: unhash; know 2147483647, prot 2147483647
|
||||
Possibly interesting term: sk; know 1, prot 2
|
||||
|
||||
|
||||
roivas:~scyther% ./scyther yahalom.spdl
|
||||
warning: variable T was declared in role yahalom,R but never used in a read event.
|
||||
Global constants: [Simon, Bob, Alice, Compromised, Fresh, k]
|
||||
|
||||
Possibly interesting term: k; know 2147483647, prot 2
|
||||
|
||||
|
||||
roivas:~scyther% ./scyther ns3.spdl
|
||||
Global constants: [Eve, sk, pk]
|
||||
|
||||
Possibly interesting term: sk; know 1, prot 2147483647
|
@ -1,197 +0,0 @@
|
||||
/**
|
||||
* Initial intruder knowledge computation.
|
||||
*/
|
||||
|
||||
#include "intruderknowledge.h"
|
||||
|
||||
//! Add a (copy of) a term to the intruder knowledge
|
||||
void
|
||||
addSTerm (const System sys, Term t, Termlist fromlist, Termlist tolist)
|
||||
{
|
||||
Term t2;
|
||||
|
||||
t2 = termLocal (t, fromlist, tolist);
|
||||
|
||||
if (switches.check)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("[ Adding ");
|
||||
termPrint (t2);
|
||||
eprintf (" to the initial intruder knowledge]\n");
|
||||
globalError--;
|
||||
}
|
||||
}
|
||||
|
||||
//! Unfold the term for all possible options
|
||||
void
|
||||
addEnumTerm (const System sys, Term t, Term actor, Termlist todo,
|
||||
Termlist fromlist, Termlist tolist)
|
||||
{
|
||||
if (todo == NULL)
|
||||
{
|
||||
addSTerm (sys, t, fromlist, tolist);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (termSubTerm (t, todo->term))
|
||||
{
|
||||
// Occurs, we have to iterate
|
||||
void iterateThis (Term to)
|
||||
{
|
||||
tolist = termlistPrepend (tolist, to);
|
||||
|
||||
addEnumTerm (sys, t, actor, todo->next, fromlist, tolist);
|
||||
|
||||
tolist = termlistDelTerm (tolist);
|
||||
}
|
||||
|
||||
fromlist = termlistPrepend (fromlist, todo->term);
|
||||
if (isTermEqual (todo->term, actor))
|
||||
{
|
||||
// Untrusted agents only
|
||||
Termlist tl;
|
||||
|
||||
for (tl = sys->untrusted; tl != NULL; tl = tl->next)
|
||||
{
|
||||
iterateThis (tl->term);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// any agents
|
||||
Termlist tl;
|
||||
|
||||
for (tl = sys->agentnames; tl != NULL; tl = tl->next)
|
||||
{
|
||||
iterateThis (tl->term);
|
||||
}
|
||||
}
|
||||
fromlist = termlistDelTerm (fromlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simply proceed to next
|
||||
addEnumTerm (sys, t, actor, todo->next, fromlist, tolist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Does t contain any of sublist?
|
||||
int
|
||||
anySubTerm (Term t, Termlist sublist)
|
||||
{
|
||||
while (sublist != NULL)
|
||||
{
|
||||
if (termSubTerm (t, sublist->term))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
sublist = sublist->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
initialIntruderKnowledge (const System sys)
|
||||
{
|
||||
/*
|
||||
* display initial role knowledge
|
||||
*/
|
||||
int deriveFromRole (Protocol p, Role r)
|
||||
{
|
||||
void addListKnowledge (Termlist tl, Term actor)
|
||||
{
|
||||
void addTermKnowledge (Term t)
|
||||
{
|
||||
if (anySubTerm (t, p->rolenames))
|
||||
{
|
||||
Term f;
|
||||
// Has rolename subterms. We have to enumerate those.
|
||||
/**
|
||||
* Hack. Enumerating is not always good (or even desirable).
|
||||
* If some I knows sk(I), sk should not be in the intruder knowledge.
|
||||
* But for hash(I), we typically would have h; but if it is never used differently, it would suffice.
|
||||
* To summarize, the operational semantics definition is perfectly fine, but maybe a bit strict sometimes.
|
||||
*
|
||||
* The hack is that if function application:
|
||||
*/
|
||||
f = getTermFunction (t);
|
||||
if (f != NULL)
|
||||
{
|
||||
// it's a function, right. So we see whether it is public. It is if it does not contain the actor...
|
||||
if (!termSubTerm (t, actor))
|
||||
{
|
||||
// no actor, then nothing secret I guess.
|
||||
addSTerm (sys, f, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// has actor. but does it contain even more?
|
||||
|
||||
int allagents (Term t)
|
||||
{
|
||||
if (!inTermlist (sys->agentnames, t))
|
||||
{
|
||||
if (!inTermlist (p->rolenames, t))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!term_iterate_leaves (TermOp (t), allagents))
|
||||
{
|
||||
// something else as well, so that probably means a hash or something like that.
|
||||
addSTerm (sys, f, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise, we enumerate
|
||||
addEnumTerm (sys, t, actor, p->rolenames, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No actor subterm. Simply add.
|
||||
addSTerm (sys, t, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
while (tl != NULL)
|
||||
{
|
||||
addTermKnowledge (tl->term);
|
||||
tl = tl->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (switches.check)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("Role ");
|
||||
termPrint (r->nameterm);
|
||||
eprintf (" knows ");
|
||||
termlistPrint (r->knows);
|
||||
eprintf ("\n");
|
||||
globalError--;
|
||||
}
|
||||
addListKnowledge (r->knows, r->nameterm);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (switches.check)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("Computing initial intruder knowledge.\n\n");
|
||||
eprintf ("Agent names : ");
|
||||
termlistPrint (sys->agentnames);
|
||||
eprintf ("\n");
|
||||
eprintf ("Untrusted agents : ");
|
||||
termlistPrint (sys->untrusted);
|
||||
eprintf ("\n");
|
||||
globalError--;
|
||||
}
|
||||
|
||||
iterateRoles (sys, deriveFromRole);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef INTRUDERKNOWLEDGE
|
||||
#define INTRUDERKNOWLEDGE
|
||||
|
||||
#include "system.h"
|
||||
#include "switches.h"
|
||||
|
||||
void initialIntruderKnowledge (const System sys);
|
||||
|
||||
#endif
|
@ -1,550 +0,0 @@
|
||||
/**
|
||||
*@file knowledge.c
|
||||
*\brief Procedures concerning knowledge structures.
|
||||
*
|
||||
* The main issue of this code is to maintain the minimal property of the knowledge set.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "termlist.h"
|
||||
#include "knowledge.h"
|
||||
#include "system.h"
|
||||
#include "debug.h"
|
||||
#include "error.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.
|
||||
*/
|
||||
|
||||
//! Open knowledge code.
|
||||
void
|
||||
knowledgeInit (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//! Close knowledge code.
|
||||
void
|
||||
knowledgeDone (void)
|
||||
{
|
||||
}
|
||||
|
||||
//! Allocate a fresh memory block the size of a knowledge struct.
|
||||
/**
|
||||
* Memory will not be initialized.
|
||||
*@return Pointer to a fresh memory block.
|
||||
*/
|
||||
Knowledge
|
||||
makeKnowledge ()
|
||||
{
|
||||
return (Knowledge) malloc (sizeof (struct knowledge));
|
||||
}
|
||||
|
||||
//! Create a new empty knowledge structure.
|
||||
/**
|
||||
*@return Pointer to an empty knowledge structure.
|
||||
*/
|
||||
Knowledge
|
||||
emptyKnowledge ()
|
||||
{
|
||||
Knowledge know;
|
||||
|
||||
know = makeKnowledge ();
|
||||
know->basic = NULL;
|
||||
know->encrypt = NULL;
|
||||
know->inverses = NULL;
|
||||
know->vars = NULL;
|
||||
return know;
|
||||
}
|
||||
|
||||
//! Duplicate a knowledge structure.
|
||||
/**
|
||||
* Makes copies using termlistShallow() of knowledge::basic, knowledge::encrypt and
|
||||
* knowledge::vars.
|
||||
* For the inverses, only the pointer is copied.
|
||||
*@param know The knowledge structure to be copied.
|
||||
*@return A pointer to a new memory struct.
|
||||
*\sa termlistShallow(), knowledgeDelete()
|
||||
*/
|
||||
Knowledge
|
||||
knowledgeDuplicate (Knowledge know)
|
||||
{
|
||||
Knowledge newknow;
|
||||
|
||||
if (know == NULL)
|
||||
{
|
||||
warning ("Trying to copy empty knowledge.");
|
||||
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;
|
||||
}
|
||||
|
||||
//! Delete a knowledge set.
|
||||
/**
|
||||
* Typically used to destroy something made with knowledgeDuplicate().
|
||||
*\sa knowledgeDuplicate()
|
||||
*/
|
||||
void
|
||||
knowledgeDelete (Knowledge know)
|
||||
{
|
||||
if (know != NULL)
|
||||
{
|
||||
termlistDelete (know->basic);
|
||||
termlistDelete (know->encrypt);
|
||||
termlistDelete (know->vars);
|
||||
free (know);
|
||||
}
|
||||
}
|
||||
|
||||
//! Destroy a knowledge set.
|
||||
/**
|
||||
* Unlike knowledgeDelete(), uses termlistDestroy() to remove knowledge::basic,
|
||||
* knowledge::encrypt and knowledge::vars substructures.
|
||||
*\sa knowledgeDelete()
|
||||
*/
|
||||
void
|
||||
knowledgeDestroy (Knowledge know)
|
||||
{
|
||||
if (know != NULL)
|
||||
{
|
||||
termlistDestroy (know->basic);
|
||||
termlistDestroy (know->encrypt);
|
||||
termlistDestroy (know->vars);
|
||||
// termlistDestroy(know->inverses);
|
||||
free (know);
|
||||
}
|
||||
}
|
||||
|
||||
//! Add a term to a knowledge set.
|
||||
/**
|
||||
*@param know The knowledge set.
|
||||
*@param term The term to be added.
|
||||
*@return True iff the term was actually new, and added.
|
||||
*/
|
||||
int
|
||||
knowledgeAddTerm (Knowledge know, Term term)
|
||||
{
|
||||
if (know == NULL)
|
||||
{
|
||||
warning ("Trying to add term to uninitialised (NULL) Know pointer.");
|
||||
return 1;
|
||||
}
|
||||
if (term == NULL)
|
||||
return 0;
|
||||
|
||||
term = deVar (term);
|
||||
|
||||
/* for tuples, simply recurse for components */
|
||||
if (isTermTuple (term))
|
||||
{
|
||||
int status;
|
||||
|
||||
status = knowledgeAddTerm (know, TermOp1 (term));
|
||||
return knowledgeAddTerm (know, TermOp2 (term)) || status;
|
||||
}
|
||||
|
||||
/* test whether we knew it before */
|
||||
if (inKnowledge (know, term))
|
||||
return 0;
|
||||
|
||||
/* 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, TermKey (term));
|
||||
if (inKnowledge (know, invkey))
|
||||
{
|
||||
/* we can decrypt it */
|
||||
knowledgeAddTerm (know, TermOp (term));
|
||||
if (!inKnowledge (know, TermKey (term)))
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
//! Try to simplify knowledge based on a term.
|
||||
/**
|
||||
*@param know A knowledge set.
|
||||
*@param key A key, i.e. it can decrypt anything that was encrypted with term^{-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 (TermKey (scan->term), invkey))
|
||||
{
|
||||
tldecrypts = termlistAdd (tldecrypts, TermOp (scan->term));
|
||||
know->encrypt = termlistDelTerm (scan);
|
||||
scan = know->encrypt;
|
||||
}
|
||||
else
|
||||
scan = scan->next;
|
||||
}
|
||||
termDelete (invkey);
|
||||
knowledgeAddTermlist (know, tldecrypts);
|
||||
termlistDelete (tldecrypts);
|
||||
}
|
||||
|
||||
//! Add a termlist to the knowledge.
|
||||
/*
|
||||
*@return True iff there was at least one new item.
|
||||
*\sa knowledgeAddTerm()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Set an inverse pair list for the knowledge.
|
||||
/**
|
||||
* List pointer is simply copied, so don't delete it later!
|
||||
*/
|
||||
void
|
||||
knowledgeSetInverses (Knowledge know, Termlist tl)
|
||||
{
|
||||
know->inverses = tl;
|
||||
}
|
||||
|
||||
//! Is a term a part of the knowledge?
|
||||
/**
|
||||
*@param know The knowledge set.
|
||||
*@param term The term to be inferred.
|
||||
*@return True iff the term can be inferred from the knowledge set.
|
||||
*/
|
||||
int
|
||||
inKnowledge (const Knowledge know, Term term)
|
||||
{
|
||||
mindwipe (know, inKnowledge (know, 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;
|
||||
|
||||
term = deVar (term);
|
||||
if (isTermLeaf (term))
|
||||
{
|
||||
return inTermlist (know->basic, term);
|
||||
}
|
||||
if (term->type == ENCRYPT)
|
||||
{
|
||||
return inTermlist (know->encrypt, term) ||
|
||||
(inKnowledge (know, TermKey (term))
|
||||
&& inKnowledge (know, TermOp (term)));
|
||||
}
|
||||
if (term->type == TUPLE)
|
||||
{
|
||||
return (inTermlist (know->encrypt, term) ||
|
||||
(inKnowledge (know, TermOp1 (term)) &&
|
||||
inKnowledge (know, TermOp2 (term))));
|
||||
}
|
||||
return 0; /* unrecognized term type, weird */
|
||||
}
|
||||
|
||||
//! Compare two knowledge sets.
|
||||
/**
|
||||
* This does not check currently for equivalence of inverse sets, which it should.
|
||||
*@return True iff both knowledge sets are equal.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
//! Print a knowledge set.
|
||||
void
|
||||
knowledgePrint (Knowledge know)
|
||||
{
|
||||
indent ();
|
||||
if (know == NULL)
|
||||
{
|
||||
eprintf ("Empty.\n");
|
||||
return;
|
||||
}
|
||||
eprintf (" [Basic]: ");
|
||||
termlistPrint (know->basic);
|
||||
eprintf ("\n");
|
||||
indent ();
|
||||
eprintf (" [Encrp]: ");
|
||||
termlistPrint (know->encrypt);
|
||||
eprintf ("\n");
|
||||
indent ();
|
||||
eprintf (" [Vars]: ");
|
||||
termlistPrint (know->vars);
|
||||
eprintf ("\n");
|
||||
}
|
||||
|
||||
//! Print a knowledge set, short version (no newline)
|
||||
void
|
||||
knowledgePrintShort (const Knowledge know)
|
||||
{
|
||||
indent ();
|
||||
if (know == NULL)
|
||||
{
|
||||
eprintf ("Empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (know->basic != NULL)
|
||||
{
|
||||
termlistPrint (know->basic);
|
||||
if (know->encrypt != NULL);
|
||||
{
|
||||
eprintf (", ");
|
||||
}
|
||||
}
|
||||
if (know->encrypt != NULL)
|
||||
{
|
||||
termlistPrint (know->encrypt);
|
||||
}
|
||||
}
|
||||
|
||||
//! Print the inverses list of a knowledge set.
|
||||
void
|
||||
knowledgeInversesPrint (Knowledge know)
|
||||
{
|
||||
Termlist tl;
|
||||
int after = 0;
|
||||
|
||||
if (know == NULL)
|
||||
{
|
||||
eprintf ("Empty knowledge.");
|
||||
return;
|
||||
}
|
||||
|
||||
tl = knowledgeGetInverses (know);
|
||||
if (tl == NULL)
|
||||
{
|
||||
eprintf ("None.");
|
||||
}
|
||||
else
|
||||
{
|
||||
while (tl != NULL && tl->next != NULL)
|
||||
{
|
||||
if (after)
|
||||
{
|
||||
eprintf (",");
|
||||
}
|
||||
eprintf ("(");
|
||||
termPrint (tl->term);
|
||||
eprintf (",");
|
||||
termPrint (tl->next->term);
|
||||
eprintf (")");
|
||||
after = 1;
|
||||
tl = tl->next->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Yield the set of representatives for the knowledge.
|
||||
/**
|
||||
* Note: this is a shallow copy, and needs to be termlistDelete'd.
|
||||
*\sa termlistDelete()
|
||||
*/
|
||||
Termlist
|
||||
knowledgeSet (const 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 (const Knowledge know)
|
||||
{
|
||||
if (know == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return know->inverses;
|
||||
}
|
||||
|
||||
//! Get all basic elements in the knowledge
|
||||
/**
|
||||
* This function is used by match_basic, to determine all basic elements in the knowledge set.
|
||||
* Most of the time this doesn't even change, so it might become a parameter of knowledge.
|
||||
* For now, this will have to do.
|
||||
*
|
||||
*@todo Investigate whether the basics in the knowledge set should be a parameter of knowledge, as it doesn't change very often.
|
||||
*/
|
||||
__inline__ Termlist
|
||||
knowledgeGetBasics (const Knowledge know)
|
||||
{
|
||||
return termlistAddBasics (termlistAddBasics (NULL, know->basic),
|
||||
know->encrypt);
|
||||
}
|
||||
|
||||
//! check whether any substitutions where made in a knowledge set.
|
||||
/**
|
||||
* Typically, when a substitution is made, a knowledge set has to be reconstructed.
|
||||
* This procedure detects this by checking knowledge::vars.
|
||||
*@return True iff an open variable was later closed by a substitution.
|
||||
*\sa knowledgeReconstruction()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Reconstruct a knowledge set.
|
||||
/**
|
||||
* This is useful after e.g. substitutions.
|
||||
* Just rebuilds the knowledge in a new (shallow) copy.
|
||||
*@return The pointer to the new knowledge.
|
||||
*\sa knowledgeSubstNeeded()
|
||||
*/
|
||||
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.
|
||||
*\sa knowledgeReconstruction()
|
||||
*/
|
||||
Knowledge
|
||||
knowledgeSubstDo (const Knowledge know)
|
||||
{
|
||||
/* otherwise a copy (for deletion) is returned. */
|
||||
return knowledgeReconstruction (know);
|
||||
}
|
||||
|
||||
//! Undo substitutions that were not propagated yet.
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
//! Yield the minimal set of terms that are in some knowledge, but not in some other set.
|
||||
/**
|
||||
* Yield a termlist (or NULL) that represents the reduced items that are
|
||||
* in the new set, but not in the old one.
|
||||
*@param oldk The old knowledge.
|
||||
*@param newk The new knowledge, possibly with new terms.
|
||||
*@return A termlist of miminal terms in newk, but not in oldk.
|
||||
*/
|
||||
|
||||
Termlist
|
||||
knowledgeNew (const Knowledge oldk, const Knowledge newk)
|
||||
{
|
||||
Termlist newtl;
|
||||
|
||||
void addNewStuff (Termlist tl)
|
||||
{
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (!inKnowledge (oldk, tl->term))
|
||||
{
|
||||
newtl = termlistAdd (newtl, tl->term);
|
||||
}
|
||||
tl = tl->next;
|
||||
}
|
||||
}
|
||||
|
||||
newtl = NULL;
|
||||
addNewStuff (newk->basic);
|
||||
addNewStuff (newk->encrypt);
|
||||
return newtl;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
#ifndef KNOWLEDGE
|
||||
#define KNOWLEDGE
|
||||
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
|
||||
//! Knowledge structure.
|
||||
/**
|
||||
* Contains a miminal representation of a knowledge set.
|
||||
*/
|
||||
struct knowledge
|
||||
{
|
||||
//! A list of non-encrypted terms.
|
||||
Termlist basic;
|
||||
//! A list of terms encrypted, such that the inverse is not in the knowledge set.
|
||||
Termlist encrypt;
|
||||
//! List of inverse pairs (thus length of list is even)
|
||||
Termlist inverses;
|
||||
//! List of open variables in the knowledge set.
|
||||
/**
|
||||
* This list is used to determine whether the knowledge needs to be rewritten.
|
||||
* If a new substitution is done, one of the elements of this list will become closed,
|
||||
* and we need to reconstruct the knowledge set.
|
||||
*/
|
||||
Termlist vars; // special: denotes unsubstituted variables
|
||||
};
|
||||
|
||||
//! Shorthand for knowledge pointer.
|
||||
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 knowledgePrintShort (const Knowledge know);
|
||||
void knowledgeInversesPrint (Knowledge know);
|
||||
int isKnowledgeEqual (Knowledge know1, Knowledge know2);
|
||||
Termlist knowledgeSet (const Knowledge know);
|
||||
Termlist knowledgeGetInverses (const Knowledge know);
|
||||
Termlist knowledgeGetBasics (const 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);
|
||||
|
||||
//! Harnass macro for recursive procedures.
|
||||
#define mindwipe(k,recurse) \
|
||||
Termlist tl; \
|
||||
int flag; \
|
||||
if (k != NULL && k->vars != NULL) { \
|
||||
tl = k->vars; \
|
||||
while (tl != NULL) { \
|
||||
if (tl->term->subst != NULL) { \
|
||||
Term oldsubst = tl->term->subst; \
|
||||
tl->term->subst = NULL; \
|
||||
flag = recurse; \
|
||||
tl->term->subst = oldsubst; \
|
||||
return flag; \
|
||||
} \
|
||||
tl = tl->next; \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
#endif
|
@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Label info
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "term.h"
|
||||
#include "label.h"
|
||||
#include "list.h"
|
||||
#include "system.h"
|
||||
|
||||
//! Retrieve rightmost thing of label
|
||||
Term
|
||||
rightMostTerm (Term t)
|
||||
{
|
||||
if (t != NULL)
|
||||
{
|
||||
t = deVar (t);
|
||||
if (realTermTuple (t))
|
||||
{
|
||||
return rightMostTerm (TermOp2 (t));
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Create a new labelinfo node
|
||||
Labelinfo
|
||||
label_create (const Term label, const Protocol protocol)
|
||||
{
|
||||
Labelinfo li;
|
||||
Term tl;
|
||||
|
||||
li = (Labelinfo) malloc (sizeof (struct labelinfo));
|
||||
li->label = label;
|
||||
li->protocol = protocol;
|
||||
li->sendrole = NULL;
|
||||
li->readrole = NULL;
|
||||
// Should we ignore it?
|
||||
li->ignore = false;
|
||||
tl = rightMostTerm (label);
|
||||
if (tl != NULL)
|
||||
{
|
||||
if (TermSymb (tl)->text[0] == '!')
|
||||
{
|
||||
li->ignore = true;
|
||||
}
|
||||
}
|
||||
return li;
|
||||
}
|
||||
|
||||
//! Destroy a labelinfo node
|
||||
void
|
||||
label_destroy (Labelinfo linfo)
|
||||
{
|
||||
free (linfo);
|
||||
}
|
||||
|
||||
//! Given a list of label infos, yield the correct one or NULL
|
||||
Labelinfo
|
||||
label_find (List labellist, const Term label)
|
||||
{
|
||||
Labelinfo linfo;
|
||||
|
||||
int label_find_scan (void *data)
|
||||
{
|
||||
Labelinfo linfo_scan;
|
||||
|
||||
linfo_scan = (Labelinfo) data;
|
||||
if (isTermEqual (label, linfo_scan->label))
|
||||
{
|
||||
linfo = linfo_scan;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
linfo = NULL;
|
||||
if (label != NULL)
|
||||
{
|
||||
list_iterate (labellist, label_find_scan);
|
||||
}
|
||||
return linfo;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef LABEL
|
||||
#define LABEL
|
||||
|
||||
#include "term.h"
|
||||
#include "list.h"
|
||||
#include "system.h"
|
||||
|
||||
/*
|
||||
* Structure to store label information
|
||||
*/
|
||||
struct labelinfo
|
||||
{
|
||||
Term label;
|
||||
int ignore;
|
||||
Protocol protocol;
|
||||
Term sendrole;
|
||||
Term readrole;
|
||||
};
|
||||
|
||||
typedef struct labelinfo *Labelinfo;
|
||||
|
||||
Labelinfo label_create (const Term label, const Protocol protocol);
|
||||
void label_destroy (Labelinfo linfo);
|
||||
Labelinfo label_find (List labellist, const Term label);
|
||||
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
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>)+
|
||||
|
@ -1,3 +0,0 @@
|
||||
- GNU getopt
|
||||
- GNU bison/flex
|
||||
- de rest (c) Cas
|
272
gui/src/list.c
272
gui/src/list.c
@ -1,272 +0,0 @@
|
||||
/**
|
||||
*@file list.c
|
||||
* Generic list type
|
||||
*
|
||||
* A doubly linked list with void* as data type.
|
||||
*/
|
||||
|
||||
#include "list.h"
|
||||
#if !defined(__APPLE__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
//! Make a node
|
||||
List
|
||||
list_create (const void *data)
|
||||
{
|
||||
List newlist;
|
||||
|
||||
newlist = (List) malloc (sizeof (struct list_struct));
|
||||
newlist->prev = NULL;
|
||||
newlist->next = NULL;
|
||||
newlist->data = (void *) data;
|
||||
return newlist;
|
||||
}
|
||||
|
||||
//! Rewind list
|
||||
List
|
||||
list_rewind (List list)
|
||||
{
|
||||
if (list != NULL)
|
||||
{
|
||||
while (list->prev != NULL)
|
||||
{
|
||||
list = list->prev;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
//! Forward list
|
||||
List
|
||||
list_forward (List list)
|
||||
{
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (list->next != NULL)
|
||||
{
|
||||
list = list->next;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
//! Add element to list, inserting it just before the current node.
|
||||
/**
|
||||
* @returns the head of the list
|
||||
*/
|
||||
List
|
||||
list_insert (List list, const void *data)
|
||||
{
|
||||
List newnode;
|
||||
|
||||
newnode = list_create (data);
|
||||
if (list == NULL)
|
||||
{
|
||||
return newnode;
|
||||
}
|
||||
newnode->next = list;
|
||||
newnode->prev = list->prev;
|
||||
list->prev = newnode;
|
||||
if (newnode->prev != NULL)
|
||||
{
|
||||
newnode->prev->next = newnode;
|
||||
return list_rewind (newnode->prev);
|
||||
}
|
||||
else
|
||||
{
|
||||
return newnode;
|
||||
}
|
||||
}
|
||||
|
||||
//! Add element to list, inserting it just after the current node.
|
||||
/**
|
||||
* @returns the head of the list
|
||||
*/
|
||||
List
|
||||
list_add (List list, const void *data)
|
||||
{
|
||||
List newnode;
|
||||
|
||||
newnode = list_create (data);
|
||||
if (list == NULL)
|
||||
{
|
||||
return newnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
newnode->next = list->next;
|
||||
newnode->prev = list;
|
||||
list->next = newnode;
|
||||
if (newnode->next != NULL)
|
||||
{
|
||||
newnode->next->prev = newnode;
|
||||
}
|
||||
return list_rewind (list);
|
||||
}
|
||||
}
|
||||
|
||||
//! Add element to list, inserting it at the tail of the list.
|
||||
/**
|
||||
* @returns the head of the list
|
||||
*/
|
||||
List
|
||||
list_append (List list, const void *data)
|
||||
{
|
||||
List newnode;
|
||||
List lastnode;
|
||||
|
||||
newnode = list_create (data);
|
||||
if (list == NULL)
|
||||
{
|
||||
return newnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastnode = list_forward (list);
|
||||
newnode->prev = lastnode;
|
||||
lastnode->next = newnode;
|
||||
return list_rewind (list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Destroy a node
|
||||
/**
|
||||
* @returns the head of the list
|
||||
*/
|
||||
List
|
||||
list_delete (List list)
|
||||
{
|
||||
if (list != NULL)
|
||||
{
|
||||
List prenode, postnode;
|
||||
|
||||
prenode = list->prev;
|
||||
postnode = list->next;
|
||||
free (list);
|
||||
if (postnode != NULL)
|
||||
{
|
||||
postnode->prev = prenode;
|
||||
}
|
||||
if (prenode != NULL)
|
||||
{
|
||||
prenode->next = postnode;
|
||||
return list_rewind (prenode);
|
||||
}
|
||||
else
|
||||
{
|
||||
return postnode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//! Test if it's already in the list, using pointer equality.
|
||||
/**
|
||||
*@warn Only scans forward, so make sure the list is rewound.
|
||||
*@returns The boolean result.
|
||||
*/
|
||||
int
|
||||
in_list (List list, const void *compdata)
|
||||
{
|
||||
while (list != NULL)
|
||||
{
|
||||
if (list->data == compdata)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Iterator
|
||||
/**
|
||||
* Function used returns int; if non-zero (true), iteration continues.
|
||||
* Function is called with data as argument, *not* the list node.
|
||||
*
|
||||
*@returns true iff domain empty or all applications true. If false, some iteration aborted the run.
|
||||
*/
|
||||
int
|
||||
list_iterate (List list, int (*func) ())
|
||||
{
|
||||
while (list != NULL)
|
||||
{
|
||||
if (!func (list->data))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Duplicate (always shallow)
|
||||
List
|
||||
list_duplicate (List list)
|
||||
{
|
||||
List newlist;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
list = list_forward (list);
|
||||
newlist = NULL;
|
||||
while (list != NULL)
|
||||
{
|
||||
newlist = list_insert (newlist, list->data);
|
||||
list = list->prev;
|
||||
}
|
||||
return newlist;
|
||||
}
|
||||
|
||||
//! Destroy (shallow)
|
||||
void
|
||||
list_destroy (List list)
|
||||
{
|
||||
list = list_rewind (list);
|
||||
while (list != NULL)
|
||||
{
|
||||
List node;
|
||||
|
||||
node = list;
|
||||
list = list->next;
|
||||
free (node);
|
||||
}
|
||||
}
|
||||
|
||||
//! Shift n positions to the right
|
||||
List
|
||||
list_shift (List list, int n)
|
||||
{
|
||||
while (n > 0 && list != NULL)
|
||||
{
|
||||
list = list->next;
|
||||
n--;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
//! Determine length of list from this point onwards
|
||||
int
|
||||
list_length (List list)
|
||||
{
|
||||
int n;
|
||||
|
||||
while (list != NULL)
|
||||
{
|
||||
n++;
|
||||
list = list->next;
|
||||
}
|
||||
return n;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef GENERICLIST
|
||||
#define GENERICLIST
|
||||
|
||||
//! generic list structure node
|
||||
struct list_struct
|
||||
{
|
||||
struct list_struct *next; //!< pointer to next node
|
||||
struct list_struct *prev; //!< pointer to previous node
|
||||
void *data; //!< pointer to the actual data element (should be typecast)
|
||||
};
|
||||
|
||||
typedef struct list_struct *List; //!< pointer to generic list node
|
||||
|
||||
List list_create (const void *data);
|
||||
List list_rewind (List list);
|
||||
List list_forward (List list);
|
||||
List list_insert (List list, const void *data);
|
||||
List list_add (List list, const void *data);
|
||||
List list_append (List list, const void *data);
|
||||
List list_delete (List list);
|
||||
int in_list (List list, const void *data);
|
||||
int list_iterate (List list, int (*func) ());
|
||||
List list_duplicate (List list);
|
||||
void list_destroy (List list);
|
||||
List list_shift (List list, int n);
|
||||
int list_length (List list);
|
||||
|
||||
#endif
|
260
gui/src/main.c
260
gui/src/main.c
@ -1,260 +0,0 @@
|
||||
/**
|
||||
*@file main.c
|
||||
* \brief The main file.
|
||||
*
|
||||
* Contains the main switch handling, and passes everything to the core logic.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \mainpage
|
||||
*
|
||||
* \section intro Introduction
|
||||
*
|
||||
* Scyther is a model checker for security protocols.
|
||||
*
|
||||
* \section install Installation
|
||||
*
|
||||
* How to install Scyther.
|
||||
*
|
||||
* \section exit Exit codes
|
||||
*
|
||||
* 0 Okay No attack found, claims encountered
|
||||
*
|
||||
* 1 Error Something went wrong (error) E.g. switch error, or scenario ran out.
|
||||
*
|
||||
* 2 Okay No attack found (because) no claims encountered
|
||||
*
|
||||
* 3 Okay Attack found
|
||||
*
|
||||
* \section coding Coding conventions
|
||||
*
|
||||
* Usually, each source file except main.c has an myfileInit() and myfileDone() function
|
||||
* available. These allow any initialisation and destruction of required structures.
|
||||
*
|
||||
* GNU indent rules are used, but K&R derivatives are allowed as well. Conversion can
|
||||
* be done for any style using the GNU indent program.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include "system.h"
|
||||
#include "debug.h"
|
||||
#include "symbol.h"
|
||||
#include "pheading.h"
|
||||
#include "symbol.h"
|
||||
#include "tac.h"
|
||||
#include "timer.h"
|
||||
#include "compiler.h"
|
||||
#include "binding.h"
|
||||
#include "switches.h"
|
||||
#include "specialterm.h"
|
||||
#include "color.h"
|
||||
#include "error.h"
|
||||
#include "claim.h"
|
||||
#include "arachne.h"
|
||||
#include "xmlout.h"
|
||||
|
||||
//! The global system state pointer
|
||||
System sys;
|
||||
|
||||
//! Pointer to the tac node container
|
||||
extern struct tacnode *spdltac;
|
||||
//! Match mode
|
||||
extern int mgu_match;
|
||||
|
||||
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);
|
||||
|
||||
//! The main body, as called by the environment.
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int exitcode = EXIT_NOATTACK;
|
||||
|
||||
/* initialize symbols */
|
||||
termsInit ();
|
||||
termmapsInit ();
|
||||
termlistsInit ();
|
||||
knowledgeInit ();
|
||||
symbolsInit ();
|
||||
tacInit ();
|
||||
|
||||
/*
|
||||
* ------------------------------------------------
|
||||
* generate system
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
|
||||
/* process any command-line switches */
|
||||
switchesInit (argc, argv);
|
||||
|
||||
/* process colors */
|
||||
colorInit ();
|
||||
|
||||
/* start system */
|
||||
sys = systemInit ();
|
||||
|
||||
/* init compiler for this system */
|
||||
compilerInit (sys);
|
||||
|
||||
sys->know = emptyKnowledge ();
|
||||
|
||||
|
||||
/* parse input */
|
||||
|
||||
yyparse ();
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (1))
|
||||
tacPrint (spdltac);
|
||||
#endif
|
||||
|
||||
/* compile */
|
||||
|
||||
// Compile no runs for Arachne and preprocess
|
||||
compile (spdltac, 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 */
|
||||
|
||||
|
||||
/*
|
||||
* ---------------------------------------
|
||||
* Switches consistency checking.
|
||||
* ---------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (4))
|
||||
{
|
||||
warning ("Selected output method is %i", switches.output);
|
||||
}
|
||||
#endif
|
||||
|
||||
arachneInit (sys);
|
||||
|
||||
/*
|
||||
* ---------------------------------------
|
||||
* Start real stuff
|
||||
* ---------------------------------------
|
||||
*/
|
||||
|
||||
/* xml init */
|
||||
if (switches.xml)
|
||||
xmlOutInit ();
|
||||
|
||||
/* model check system */
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (1))
|
||||
warning ("Start modelchecking system.");
|
||||
#endif
|
||||
MC_single (sys);
|
||||
|
||||
/*
|
||||
* ---------------------------------------
|
||||
* After checking the system, results
|
||||
* ---------------------------------------
|
||||
*/
|
||||
|
||||
/* Exitcodes are *not* correct anymore */
|
||||
|
||||
exitcode = EXIT_ATTACK;
|
||||
|
||||
/* xml closeup */
|
||||
if (switches.xml)
|
||||
xmlOutDone ();
|
||||
|
||||
/*
|
||||
* Now we clean up any memory that was allocated.
|
||||
*/
|
||||
|
||||
arachneDone ();
|
||||
knowledgeDestroy (sys->know);
|
||||
systemDone (sys);
|
||||
colorDone ();
|
||||
compilerDone ();
|
||||
|
||||
/* done symbols */
|
||||
tacDone ();
|
||||
symbolsDone ();
|
||||
knowledgeDone ();
|
||||
termlistsDone ();
|
||||
termmapsDone ();
|
||||
termsDone ();
|
||||
|
||||
/* memory clean up? */
|
||||
strings_cleanup ();
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
//! Analyse the model
|
||||
/**
|
||||
* Traditional handywork.
|
||||
*/
|
||||
|
||||
void
|
||||
MC_single (const System sys)
|
||||
{
|
||||
/*
|
||||
* simple one-time check
|
||||
*/
|
||||
|
||||
systemReset (sys); // reset any globals
|
||||
systemRuns (sys); // init runs data
|
||||
modelCheck (sys);
|
||||
}
|
||||
|
||||
//! Model check the system, given all parameters.
|
||||
/*
|
||||
* Precondition: the system was reset with the corresponding parameters.
|
||||
* Reports time and states traversed.
|
||||
* Note that the return values doubles as the number of failed claims.
|
||||
*@return True iff any claim failed, and thus an attack was found.
|
||||
*/
|
||||
|
||||
int
|
||||
modelCheck (const System sys)
|
||||
{
|
||||
int claimcount;
|
||||
|
||||
/* modelcheck the system */
|
||||
claimcount = arachne ();
|
||||
|
||||
if (claimcount == 0)
|
||||
{
|
||||
warning ("No claims in system.");
|
||||
}
|
||||
|
||||
return (sys->failed != STATES0);
|
||||
}
|
624
gui/src/mgu.c
624
gui/src/mgu.c
@ -1,624 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
#include "mgu.h"
|
||||
#include "type.h"
|
||||
#include "debug.h"
|
||||
#include "specialterm.h"
|
||||
#include "switches.h"
|
||||
|
||||
/*
|
||||
Most General Unifier
|
||||
|
||||
Unification etc.
|
||||
|
||||
New version yields a termlist with substituted variables, which can later be reset to NULL.
|
||||
*/
|
||||
|
||||
//! Internal constant. If true, typed checking
|
||||
/**
|
||||
* Analoguous to switches.match
|
||||
* 0 typed
|
||||
* 1 basic typeflaws
|
||||
* 2 all typeflaws
|
||||
*/
|
||||
static int mgu_match = 0;
|
||||
|
||||
//! Set mgu mode (basically switches.match)
|
||||
void
|
||||
setMguMode (const int match)
|
||||
{
|
||||
mgu_match = match;
|
||||
}
|
||||
|
||||
void
|
||||
showSubst (Term t)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!DEBUGL (5))
|
||||
return;
|
||||
|
||||
indent ();
|
||||
eprintf ("Substituting ");
|
||||
termPrint (t);
|
||||
eprintf (", typed ");
|
||||
termlistPrint (t->stype);
|
||||
if (realTermLeaf (t->subst))
|
||||
{
|
||||
eprintf ("->");
|
||||
termlistPrint (t->subst->stype);
|
||||
}
|
||||
else
|
||||
{
|
||||
eprintf (", composite term");
|
||||
}
|
||||
if (t->type != VARIABLE)
|
||||
{
|
||||
eprintf (" (bound roleconstant)");
|
||||
}
|
||||
eprintf ("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//! See if this is preferred substitution
|
||||
/**
|
||||
* By default, ta->tb will map. Returning 0 (false) will swap them.
|
||||
*/
|
||||
int
|
||||
preferSubstitutionOrder (Term ta, Term tb)
|
||||
{
|
||||
if (termlistLength (ta->stype) == 1 && inTermlist (ta->stype, TERM_Agent))
|
||||
{
|
||||
/**
|
||||
* If the first one is an agent type, we prefer swapping.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Per default, leave it as it is.
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! See if a substitution is valid
|
||||
__inline__ int
|
||||
goodsubst (Term tvar, Term tsubst)
|
||||
{
|
||||
Term tbuf;
|
||||
int res;
|
||||
|
||||
tbuf = tvar->subst;
|
||||
tvar->subst = tsubst;
|
||||
|
||||
res = checkTypeTerm (mgu_match, tvar);
|
||||
|
||||
tvar->subst = tbuf;
|
||||
return res;
|
||||
}
|
||||
|
||||
//! Undo all substitutions in a list of variables.
|
||||
/**
|
||||
* The termlist should contain only variables.
|
||||
*/
|
||||
void
|
||||
termlistSubstReset (Termlist tl)
|
||||
{
|
||||
while (tl != NULL)
|
||||
{
|
||||
tl->term->subst = NULL;
|
||||
tl = tl->next;
|
||||
}
|
||||
}
|
||||
|
||||
//! Most general unifier iteration
|
||||
/**
|
||||
* Try to determine the most general unifier of two terms, if so calls function.
|
||||
*
|
||||
* The callback receives a list of variables, that were previously open, but are now closed
|
||||
* in such a way that the two terms unify.
|
||||
*
|
||||
* The callback must return true for the iteration to proceed: if it returns false, a single call would abort the scan.
|
||||
* The return value shows this: it is false if the scan was aborted, and true if not.
|
||||
*/
|
||||
int
|
||||
unify (Term t1, Term t2, Termlist tl, int (*callback) (Termlist))
|
||||
{
|
||||
int callsubst (Termlist tl, Term t, Term tsubst)
|
||||
{
|
||||
int proceed;
|
||||
|
||||
t->subst = tsubst;
|
||||
#ifdef DEBUG
|
||||
showSubst (t);
|
||||
#endif
|
||||
tl = termlistAdd (tl, t);
|
||||
proceed = callback (tl);
|
||||
tl = termlistDelTerm (tl);
|
||||
t->subst = NULL;
|
||||
return proceed;
|
||||
}
|
||||
|
||||
/* added for speed */
|
||||
t1 = deVar (t1);
|
||||
t2 = deVar (t2);
|
||||
if (t1 == t2)
|
||||
{
|
||||
return callback (tl);
|
||||
}
|
||||
|
||||
if (!(hasTermVariable (t1) || hasTermVariable (t2)))
|
||||
{
|
||||
// None has a variable
|
||||
if (isTermEqual (t1, t2))
|
||||
{
|
||||
// Equal!
|
||||
return callback (tl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can never be fixed, no variables
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Distinguish a special case where both are unbound variables that will be
|
||||
* connected, and I want to give one priority over the other for readability.
|
||||
*
|
||||
* Because t1 and t2 have been deVar'd means that if they are variables, they
|
||||
* are also unbound.
|
||||
*/
|
||||
|
||||
if (realTermVariable (t1) && realTermVariable (t2) && goodsubst (t1, t2))
|
||||
{
|
||||
/* Both are unbound variables. Decide.
|
||||
*
|
||||
* The plan: t1->subst will point to t2. But maybe we prefer the other
|
||||
* way around?
|
||||
*/
|
||||
if (preferSubstitutionOrder (t2, t1))
|
||||
{
|
||||
Term t3;
|
||||
|
||||
// Swappy.
|
||||
t3 = t1;
|
||||
t1 = t2;
|
||||
t2 = t3;
|
||||
}
|
||||
return callsubst (tl, t1, t2);
|
||||
}
|
||||
|
||||
/* symmetrical tests for single variable.
|
||||
*/
|
||||
|
||||
if (realTermVariable (t2))
|
||||
{
|
||||
if (termSubTerm (t1, t2) || !goodsubst (t2, t1))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
return callsubst (tl, t2, t1);
|
||||
}
|
||||
}
|
||||
if (realTermVariable (t1))
|
||||
{
|
||||
if (termSubTerm (t2, t1) || !goodsubst (t1, t2))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
return callsubst (tl, t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
/* left & right are compounds with variables */
|
||||
if (t1->type != t2->type)
|
||||
return true;
|
||||
|
||||
/* identical compound types */
|
||||
|
||||
/* encryption first */
|
||||
if (realTermEncrypt (t1))
|
||||
{
|
||||
int unify_combined_enc (Termlist tl)
|
||||
{
|
||||
// now the keys are unified (subst in this tl)
|
||||
// and we try the inner terms
|
||||
return unify (TermOp (t1), TermOp (t2), tl, callback);
|
||||
}
|
||||
|
||||
return unify (TermKey (t1), TermKey (t2), tl, unify_combined_enc);
|
||||
}
|
||||
|
||||
/* tupling second
|
||||
non-associative version ! TODO other version */
|
||||
if (isTermTuple (t1))
|
||||
{
|
||||
int unify_combined_tup (Termlist tl)
|
||||
{
|
||||
// now the keys are unified (subst in this tl)
|
||||
// and we try the inner terms
|
||||
return unify (TermOp2 (t1), TermOp2 (t2), tl, callback);
|
||||
}
|
||||
return unify (TermOp1 (t1), TermOp1 (t2), tl, unify_combined_tup);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Subterm unification
|
||||
/**
|
||||
* Try to unify (a subterm of) tbig with tsmall.
|
||||
*
|
||||
* Callback is called with a list of substitutions, and a list of terms that
|
||||
* need to be decrypted in order for this to work.
|
||||
*
|
||||
* E.g. subtermUnify ( {{m}k1}k2, m ) yields a list : {{m}k1}k2, {m}k1 (where
|
||||
* the {m}k1 is the last added node to the list)
|
||||
*
|
||||
* The callback should return true for the iteration to proceed, or false to abort.
|
||||
* The final result is this flag.
|
||||
*/
|
||||
int
|
||||
subtermUnify (Term tbig, Term tsmall, Termlist tl, Termlist keylist,
|
||||
int (*callback) (Termlist, Termlist))
|
||||
{
|
||||
int proceed;
|
||||
|
||||
int keycallback (Termlist tl)
|
||||
{
|
||||
return callback (tl, keylist);
|
||||
}
|
||||
|
||||
proceed = true;
|
||||
|
||||
// Devar
|
||||
tbig = deVar (tbig);
|
||||
tsmall = deVar (tsmall);
|
||||
|
||||
// Three options:
|
||||
// 1. simple unification
|
||||
proceed = proceed && unify (tbig, tsmall, tl, keycallback);
|
||||
|
||||
// [2/3]: complex
|
||||
if (switches.intruder)
|
||||
{
|
||||
// 2. interm unification
|
||||
// Only if there is an intruder
|
||||
if (realTermTuple (tbig))
|
||||
{
|
||||
proceed = proceed
|
||||
&& subtermUnify (TermOp1 (tbig), tsmall, tl, keylist, callback);
|
||||
proceed = proceed
|
||||
&& subtermUnify (TermOp2 (tbig), tsmall, tl, keylist, callback);
|
||||
}
|
||||
|
||||
// 3. unification with encryption needed
|
||||
if (realTermEncrypt (tbig))
|
||||
{
|
||||
// extend the keylist
|
||||
keylist = termlistAdd (keylist, tbig);
|
||||
proceed = proceed
|
||||
&& subtermUnify (TermOp (tbig), tsmall, tl, keylist, callback);
|
||||
// remove last item again
|
||||
keylist = termlistDelTerm (keylist);
|
||||
}
|
||||
}
|
||||
return proceed;
|
||||
}
|
||||
|
||||
|
||||
//! Most general unifier.
|
||||
/**
|
||||
* Try to determine the most general unifier of two terms.
|
||||
* Resulting termlist must be termlistDelete'd.
|
||||
*
|
||||
*@return Returns a list of variables, that were previously open, but are now closed
|
||||
* in such a way that the two terms unify. Returns \ref MGUFAIL if it is impossible.
|
||||
* The termlist should be deleted.
|
||||
*/
|
||||
Termlist
|
||||
termMguTerm (Term t1, Term t2)
|
||||
{
|
||||
/* added for speed */
|
||||
t1 = deVar (t1);
|
||||
t2 = deVar (t2);
|
||||
if (t1 == t2)
|
||||
return NULL;
|
||||
|
||||
if (!(hasTermVariable (t1) || hasTermVariable (t2)))
|
||||
{
|
||||
if (isTermEqual (t1, t2))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MGUFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Distinguish a special case where both are unbound variables that will be
|
||||
* connected, and I want to give one priority over the other for readability.
|
||||
*
|
||||
* Because t1 and t2 have been deVar'd means that if they are variables, they
|
||||
* are also unbound.
|
||||
*/
|
||||
|
||||
if (realTermVariable (t1) && realTermVariable (t2) && goodsubst (t1, t2))
|
||||
{
|
||||
/* Both are unbound variables. Decide.
|
||||
*
|
||||
* The plan: t1->subst will point to t2. But maybe we prefer the other
|
||||
* way around?
|
||||
*/
|
||||
if (preferSubstitutionOrder (t2, t1))
|
||||
{
|
||||
Term t3;
|
||||
|
||||
// Swappy.
|
||||
t3 = t1;
|
||||
t1 = t2;
|
||||
t2 = t3;
|
||||
}
|
||||
t1->subst = t2;
|
||||
#ifdef DEBUG
|
||||
showSubst (t1);
|
||||
#endif
|
||||
return termlistAdd (NULL, t1);
|
||||
}
|
||||
|
||||
/* symmetrical tests for single variable.
|
||||
*/
|
||||
|
||||
if (realTermVariable (t2))
|
||||
{
|
||||
if (termSubTerm (t1, t2) || !goodsubst (t2, t1))
|
||||
return MGUFAIL;
|
||||
else
|
||||
{
|
||||
t2->subst = t1;
|
||||
#ifdef DEBUG
|
||||
showSubst (t2);
|
||||
#endif
|
||||
return termlistAdd (NULL, t2);
|
||||
}
|
||||
}
|
||||
if (realTermVariable (t1))
|
||||
{
|
||||
if (termSubTerm (t2, t1) || !goodsubst (t1, t2))
|
||||
return MGUFAIL;
|
||||
else
|
||||
{
|
||||
t1->subst = t2;
|
||||
#ifdef DEBUG
|
||||
showSubst (t1);
|
||||
#endif
|
||||
return termlistAdd (NULL, t1);
|
||||
}
|
||||
}
|
||||
|
||||
/* left & right are compounds with variables */
|
||||
if (t1->type != t2->type)
|
||||
return MGUFAIL;
|
||||
|
||||
/* identical compounds */
|
||||
/* encryption first */
|
||||
if (realTermEncrypt (t1))
|
||||
{
|
||||
Termlist tl1, tl2;
|
||||
|
||||
tl1 = termMguTerm (TermKey (t1), TermKey (t2));
|
||||
if (tl1 == MGUFAIL)
|
||||
{
|
||||
return MGUFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tl2 = termMguTerm (TermOp (t1), TermOp (t2));
|
||||
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 (TermOp1 (t1), TermOp1 (t2));
|
||||
if (tl1 == MGUFAIL)
|
||||
{
|
||||
return MGUFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tl2 = termMguTerm (TermOp2 (t1), TermOp2 (t2));
|
||||
if (tl2 == MGUFAIL)
|
||||
{
|
||||
termlistSubstReset (tl1);
|
||||
termlistDelete (tl1);
|
||||
return MGUFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return termlistConcat (tl1, tl2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return MGUFAIL;
|
||||
}
|
||||
|
||||
//! Most general interm unifiers of t1 interm t2
|
||||
/**
|
||||
* Try to determine the most general interm unifiers of two terms.
|
||||
*@returns Nothing. Iteration gets termlist of substitutions.
|
||||
*/
|
||||
int
|
||||
termMguInTerm (Term t1, Term t2, int (*iterator) (Termlist))
|
||||
{
|
||||
Termlist tl;
|
||||
int flag;
|
||||
|
||||
flag = 1;
|
||||
t2 = deVar (t2);
|
||||
if (t2 != NULL)
|
||||
{
|
||||
if (realTermTuple (t2))
|
||||
{
|
||||
// t2 is a tuple, consider interm options as well.
|
||||
flag = flag && termMguInTerm (t1, TermOp1 (t2), iterator);
|
||||
flag = flag && termMguInTerm (t1, TermOp2 (t2), iterator);
|
||||
}
|
||||
// simple clause or combined
|
||||
tl = termMguTerm (t1, t2);
|
||||
if (tl != MGUFAIL)
|
||||
{
|
||||
// Iterate
|
||||
flag = flag && iterator (tl);
|
||||
// Reset variables
|
||||
termlistSubstReset (tl);
|
||||
// Remove list
|
||||
termlistDelete (tl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (deVar (t1) != NULL)
|
||||
{
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
//! Most general subterm unifiers of smallterm subterm bigterm
|
||||
/**
|
||||
* Try to determine the most general subterm unifiers of two terms.
|
||||
*@returns Nothing. Iteration gets termlist of subst, and list of keys needed
|
||||
* to decrypt. This termlist does not need to be deleted, because it is handled
|
||||
* by the mguSubTerm itself.
|
||||
*/
|
||||
int
|
||||
termMguSubTerm (Term smallterm, Term bigterm,
|
||||
int (*iterator) (Termlist, Termlist), Termlist inverses,
|
||||
Termlist cryptlist)
|
||||
{
|
||||
int flag;
|
||||
|
||||
flag = 1;
|
||||
smallterm = deVar (smallterm);
|
||||
bigterm = deVar (bigterm);
|
||||
if (bigterm != NULL)
|
||||
{
|
||||
Termlist tl;
|
||||
|
||||
if (!realTermLeaf (bigterm))
|
||||
{
|
||||
if (realTermTuple (bigterm))
|
||||
{
|
||||
// 'simple' tuple
|
||||
flag =
|
||||
flag
|
||||
&& termMguSubTerm (smallterm, TermOp1 (bigterm), iterator,
|
||||
inverses, cryptlist);
|
||||
flag = flag
|
||||
&& termMguSubTerm (smallterm, TermOp2 (bigterm), iterator,
|
||||
inverses, cryptlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be encryption
|
||||
Term keyneeded;
|
||||
|
||||
keyneeded = inverseKey (inverses, TermKey (bigterm));
|
||||
// We can never produce the TERM_Hidden key, thus, this is not a valid iteration.
|
||||
if (!isTermEqual (keyneeded, TERM_Hidden))
|
||||
{
|
||||
cryptlist = termlistAdd (cryptlist, bigterm); // Append, so the last encrypted term in the list is the most 'inner' one, and the first is the outer one.
|
||||
|
||||
// Recurse
|
||||
flag =
|
||||
flag
|
||||
&& termMguSubTerm (smallterm, TermOp (bigterm), iterator,
|
||||
inverses, cryptlist);
|
||||
|
||||
|
||||
cryptlist = termlistDelTerm (cryptlist);
|
||||
}
|
||||
termDelete (keyneeded);
|
||||
}
|
||||
}
|
||||
// simple clause or combined
|
||||
tl = termMguTerm (smallterm, bigterm);
|
||||
if (tl != MGUFAIL)
|
||||
{
|
||||
// Iterate
|
||||
flag = flag && iterator (tl, cryptlist);
|
||||
// Reset variables
|
||||
termlistSubstReset (tl);
|
||||
// Remove list
|
||||
termlistDelete (tl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (smallterm != NULL)
|
||||
{
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
//! Check if role terms might match in some way
|
||||
/**
|
||||
* Interesting case: role names are variables here, so they always match. We catch that case by inspecting the variable list.
|
||||
*/
|
||||
int
|
||||
checkRoletermMatch (const Term t1, const Term t2, const Termlist notmapped)
|
||||
{
|
||||
Termlist tl;
|
||||
|
||||
// simple clause or combined
|
||||
tl = termMguTerm (t1, t2);
|
||||
if (tl == MGUFAIL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int result;
|
||||
Termlist vl;
|
||||
|
||||
result = true;
|
||||
// Reset variables
|
||||
termlistSubstReset (tl);
|
||||
// Check variable list etc: should not contain mapped role names
|
||||
vl = tl;
|
||||
while (vl != NULL)
|
||||
{
|
||||
// This term should not be in the notmapped list
|
||||
if (inTermlist (notmapped, vl->term))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
vl = vl->next;
|
||||
|
||||
}
|
||||
// Remove list
|
||||
termlistDelete (tl);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#ifndef MGU
|
||||
#define MGU
|
||||
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
|
||||
//! A special constant do denote failure.
|
||||
/**
|
||||
* \c NULL already denotes equality, so an extra signal is needed to
|
||||
* denote that a unification fails.
|
||||
* \todo Find a portable solution for this \c MGUFAIL constant:
|
||||
* maybe a pointer to some special constant.
|
||||
*/
|
||||
#define MGUFAIL (Termlist) -1
|
||||
|
||||
void setMguMode (const int mgu);
|
||||
Termlist termMguTerm (Term t1, Term t2);
|
||||
int termMguInTerm (Term t1, Term t2, int (*iterator) (Termlist));
|
||||
int termMguSubTerm (Term t1, Term t2, int (*iterator) (Termlist, Termlist),
|
||||
Termlist inverses, Termlist keylist);
|
||||
void termlistSubstReset (Termlist tl);
|
||||
int checkRoletermMatch (const Term t1, const Term t2, const Termlist tl);
|
||||
|
||||
// The new iteration methods
|
||||
int unify (Term t1, Term t2, Termlist tl, int (*callback) (Termlist));
|
||||
int
|
||||
subtermUnify (Term tbig, Term tsmall, Termlist tl, Termlist keylist,
|
||||
int (*callback) (Termlist, Termlist));
|
||||
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
- (!!) Are the Arachne rules for keys that are variables sane? E.g. what
|
||||
is their inverse key? Check! Intuition: one cannot know what the
|
||||
inverse is of a non-instantiated key variable, given the current
|
||||
semantics, if asymmetric keys are allowed.
|
||||
Consequence: the current implementation is just fine, because
|
||||
asymmetric key variables cannot be defined in the language. Thus, the
|
||||
rules are fine. Investigate for the other case.
|
||||
- If no attack/state output is needed, maybe the attack heuristic should
|
||||
be simpler (which means just weighting the trace length etc.) in order
|
||||
to avoid uneccesary continuation of the search. Maybe even stop
|
||||
altogether after finding *an* attack.
|
||||
- For the TimeStamps etc, we can implement an 'auto-leak' of such local
|
||||
constants. This should works also with a modifier of sorts (e.g.
|
||||
'predictable') and such constants should be leaked to the intruder at
|
||||
the start of the run, possibly by prefixing a send.
|
||||
- knowledgeAddTerm might be improved by scanning through key list only with
|
||||
things that are newly added.
|
File diff suppressed because it is too large
Load Diff
325
gui/src/parser.y
325
gui/src/parser.y
@ -1,325 +0,0 @@
|
||||
%{
|
||||
#include "pheading.h"
|
||||
#include "tac.h"
|
||||
#include "error.h"
|
||||
|
||||
struct tacnode* spdltac;
|
||||
|
||||
int yyerror(char *s);
|
||||
int yylex(void);
|
||||
|
||||
%}
|
||||
|
||||
%union{
|
||||
char* str;
|
||||
struct tacnode* tac;
|
||||
Symbol symb;
|
||||
int value;
|
||||
}
|
||||
|
||||
%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
|
||||
%token SINGULAR
|
||||
%token FUNCTION
|
||||
%token HASHFUNCTION
|
||||
%token KNOWS
|
||||
%token TRUSTED
|
||||
|
||||
%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> basicterm
|
||||
%type <tac> termlist
|
||||
%type <tac> basictermlist
|
||||
%type <tac> key
|
||||
%type <tac> roleref
|
||||
%type <tac> knowsdecl
|
||||
|
||||
%type <value> singular
|
||||
|
||||
%type <symb> label
|
||||
%type <symb> optlabel
|
||||
|
||||
%start spdlcomplete
|
||||
|
||||
|
||||
%%
|
||||
|
||||
spdlcomplete : spdlrep
|
||||
{ spdltac = $1; }
|
||||
;
|
||||
|
||||
spdlrep : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| spdl spdlrep
|
||||
{ $$ = tacCat($1,$2); }
|
||||
;
|
||||
|
||||
spdl : UNTRUSTED termlist ';'
|
||||
{
|
||||
Tac t = tacCreate(TAC_UNTRUSTED);
|
||||
t->t1.tac = $2;
|
||||
$$ = t;
|
||||
}
|
||||
| RUN roleref '(' termlist ')' ';'
|
||||
{
|
||||
Tac t = tacCreate(TAC_RUN);
|
||||
t->t1.tac = $2;
|
||||
t->t2.tac = $4;
|
||||
$$ = t;
|
||||
}
|
||||
| PROTOCOL ID '(' termlist ')' '{' roles '}' optclosing
|
||||
{
|
||||
Tac t = tacCreate(TAC_PROTOCOL);
|
||||
t->t1.sym = $2;
|
||||
t->t2.tac = $7;
|
||||
t->t3.tac = $4;
|
||||
$$ = t;
|
||||
}
|
||||
| USERTYPE termlist ';'
|
||||
{
|
||||
Tac t = tacCreate(TAC_USERTYPE);
|
||||
t->t1.tac = $2;
|
||||
$$ = t;
|
||||
}
|
||||
| declaration
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
roles : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| role roles
|
||||
{ $$ = tacCat($1,$2); }
|
||||
| declaration roles
|
||||
{ $$ = tacCat($1,$2); }
|
||||
;
|
||||
|
||||
role : singular ROLE ID '{' roledef '}' optclosing
|
||||
{
|
||||
// TODO process singular (0/1)
|
||||
Tac t = tacCreate(TAC_ROLE);
|
||||
t->t1.sym = $3;
|
||||
t->t2.tac = $5;
|
||||
t->t3.value = $1;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
singular : /* empty */
|
||||
{ $$ = 0; }
|
||||
| SINGULAR
|
||||
{ $$ = 1; }
|
||||
;
|
||||
|
||||
optclosing : /* empty */
|
||||
{ }
|
||||
| ';'
|
||||
{ }
|
||||
;
|
||||
|
||||
roledef : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| event roledef
|
||||
{ $$ = tacCat($1,$2); }
|
||||
| declaration roledef
|
||||
{ $$ = tacCat($1,$2); }
|
||||
| knowsdecl roledef
|
||||
{ $$ = tacCat($1,$2); }
|
||||
;
|
||||
|
||||
event : READT label '(' termlist ')' ';'
|
||||
{ Tac t = tacCreate(TAC_READ);
|
||||
t->t1.sym = $2;
|
||||
/* TODO test here: tac2 should have at least 3 elements */
|
||||
t->t2.tac = $4;
|
||||
$$ = t;
|
||||
}
|
||||
| SENDT label '(' termlist ')' ';'
|
||||
{ Tac t = tacCreate(TAC_SEND);
|
||||
t->t1.sym = $2;
|
||||
/* TODO test here: tac2 should have at least 3 elements */
|
||||
t->t2.tac = $4;
|
||||
$$ = t;
|
||||
}
|
||||
| CLAIMT optlabel '(' termlist ')' ';'
|
||||
/* TODO maybe claims should be in the syntax */
|
||||
{ Tac t = tacCreate(TAC_CLAIM);
|
||||
t->t1.sym = $2;
|
||||
t->t2.tac = $4;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
roleref : ID '.' ID
|
||||
{ Tac t = tacCreate(TAC_ROLEREF);
|
||||
t->t1.sym = $1;
|
||||
t->t2.sym = $3;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
knowsdecl : KNOWS termlist ';'
|
||||
{ Tac t = tacCreate(TAC_KNOWS);
|
||||
t->t1.tac = $2;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
declaration : secretpref CONST basictermlist typeinfo1 ';'
|
||||
{ Tac t = tacCreate(TAC_CONST);
|
||||
t->t1.tac = $3;
|
||||
t->t2.tac = $4;
|
||||
t->t3.tac = $1;
|
||||
$$ = t;
|
||||
}
|
||||
| secretpref VAR basictermlist typeinfoN ';'
|
||||
{ Tac t = tacCreate(TAC_VAR);
|
||||
t->t1.tac = $3;
|
||||
t->t2.tac = $4;
|
||||
t->t3.tac = $1;
|
||||
$$ = t;
|
||||
}
|
||||
| SECRET basictermlist typeinfo1 ';'
|
||||
{ Tac t = tacCreate(TAC_SECRET);
|
||||
t->t1.tac = $2;
|
||||
t->t2.tac = $3;
|
||||
$$ = t;
|
||||
}
|
||||
| INVERSEKEYS '(' term ',' term ')' ';'
|
||||
{ Tac t = tacCreate(TAC_INVERSEKEYS);
|
||||
t->t1.tac = $3;
|
||||
t->t2.tac = $5;
|
||||
$$ = t;
|
||||
}
|
||||
| COMPROMISED termlist ';'
|
||||
{ Tac t = tacCreate(TAC_COMPROMISED);
|
||||
t->t1.tac= $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->t1.sym = $2;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
typeinfoN : /* empty */
|
||||
{
|
||||
Tac t = tacCreate(TAC_UNDEF);
|
||||
$$ = t;
|
||||
}
|
||||
| ':' basictermlist
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
label : '_' ID
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
optlabel : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| label
|
||||
{ }
|
||||
;
|
||||
|
||||
|
||||
basicterm : ID
|
||||
{
|
||||
Tac t = tacCreate(TAC_STRING);
|
||||
t->t1.sym = $1;
|
||||
$$ = t;
|
||||
}
|
||||
;
|
||||
|
||||
term : basicterm
|
||||
{ }
|
||||
| ID '(' termlist ')'
|
||||
{
|
||||
Tac t = tacCreate(TAC_STRING);
|
||||
t->t1.sym = $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); }
|
||||
;
|
||||
|
||||
basictermlist : basicterm
|
||||
{ }
|
||||
| basicterm ',' basictermlist
|
||||
{ $$ = 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
|
||||
|
||||
error ("[%i] %s at symbol '%s'.\n", yylineno, s, yytext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
#ifndef PHEADING
|
||||
#define PHEADING
|
||||
|
||||
#define YY_NO_UNPUT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
#include "symbol.h"
|
||||
#include "system.h"
|
||||
#include "tac.h"
|
||||
#endif
|
@ -1,25 +0,0 @@
|
||||
// BAN modified version of the yahalom protocol
|
||||
// Type flaw
|
||||
|
||||
usertype Server;
|
||||
|
||||
const a,b,c : Agent;
|
||||
const s : Server;
|
||||
secret k : Function;
|
||||
|
||||
protocol yahalomBan(A,B,S)
|
||||
{
|
||||
role B
|
||||
{
|
||||
const nb;
|
||||
var na;
|
||||
var kab;
|
||||
|
||||
read_1(A,B, A,na,B,S);
|
||||
send_2(B,S, B,nb, {A,na}k(B,S) );
|
||||
read_4(A,B, {A,kab,nb}k(B,S) , {nb}kab );
|
||||
claim_6(B, Secret,kab);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,265 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*@file prune_bounds.c
|
||||
*
|
||||
* Prune stuff based on bounds
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "termlist.h"
|
||||
#include "list.h"
|
||||
#include "switches.h"
|
||||
#include "timer.h"
|
||||
#include "arachne.h"
|
||||
#include "system.h"
|
||||
#include "termmap.h"
|
||||
#include "cost.h"
|
||||
|
||||
extern int attack_length;
|
||||
extern int attack_leastcost;
|
||||
extern Protocol INTRUDER;
|
||||
extern int proofDepth;
|
||||
extern int max_encryption_level;
|
||||
|
||||
//! Forward declarations
|
||||
int tooManyOfRole (const System sys);
|
||||
|
||||
//! Prune determination for bounds
|
||||
/**
|
||||
* When something is pruned here, the state space is not complete anymore.
|
||||
*
|
||||
*@returns true iff this state is invalid for some reason
|
||||
*/
|
||||
int
|
||||
prune_bounds (const System sys)
|
||||
{
|
||||
/* prune for time */
|
||||
if (passed_time_limit ())
|
||||
{
|
||||
// Oh no, we ran out of time!
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: ran out of allowed time (-T %i switch)\n",
|
||||
get_time_limit ());
|
||||
}
|
||||
// Pruned because of time bound!
|
||||
sys->current_claim->timebound = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* prune for number of attacks if we are actually outputting them */
|
||||
if (enoughAttacks (sys))
|
||||
{
|
||||
// Oh no, we ran out of possible attacks!
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: we already found the maximum number of attacks.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* prune for proof depth */
|
||||
if (proofDepth > switches.maxproofdepth)
|
||||
{
|
||||
// Hardcoded limit on proof tree depth
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: proof tree too deep: %i (-d %i switch)\n",
|
||||
proofDepth, switches.maxproofdepth);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* prune for trace length */
|
||||
if (switches.maxtracelength < INT_MAX)
|
||||
{
|
||||
int tracelength;
|
||||
int run;
|
||||
|
||||
/* compute trace length of current semistate */
|
||||
tracelength = 0;
|
||||
run = 0;
|
||||
while (run < sys->maxruns)
|
||||
{
|
||||
/* ignore intruder actions */
|
||||
if (sys->runs[run].protocol != INTRUDER)
|
||||
{
|
||||
tracelength = tracelength + sys->runs[run].step;
|
||||
}
|
||||
run++;
|
||||
}
|
||||
/* test */
|
||||
if (tracelength > switches.maxtracelength)
|
||||
{
|
||||
// Hardcoded limit on proof tree depth
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: trace too long: %i (-l %i switch)\n",
|
||||
tracelength, switches.maxtracelength);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* prune for runs */
|
||||
if (sys->num_regular_runs > switches.runs)
|
||||
{
|
||||
// Hardcoded limit on runs
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: too many regular runs (%i).\n",
|
||||
sys->num_regular_runs);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* prune for role instances max */
|
||||
if (tooManyOfRole (sys))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: too many instances of a particular role.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This needs some foundation. Probably * 2^max_encryption_level
|
||||
//!@todo Remove later
|
||||
/**
|
||||
* This should be removed once the hidelevel lemma works correctly
|
||||
*/
|
||||
if (switches.experimental & 1)
|
||||
{
|
||||
if ((switches.match < 2)
|
||||
&& (sys->num_intruder_runs >
|
||||
((double) switches.runs * max_encryption_level * 8)))
|
||||
{
|
||||
// Hardcoded limit on iterations
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: %i intruder runs is too much. (max encr. level %i)\n",
|
||||
sys->num_intruder_runs, max_encryption_level);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Limit on exceeding any attack length
|
||||
if (get_semitrace_length () >= attack_length)
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned: attack length %i.\n", attack_length);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* prune for cheaper */
|
||||
if (switches.prune != 0 && attack_leastcost <= attackCost (sys))
|
||||
{
|
||||
// We already had an attack at least this cheap.
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: attack cost exceeds a previously found attack.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Limit on attack count
|
||||
if (enoughAttacks (sys))
|
||||
return 1;
|
||||
|
||||
// Pruning involving the number of intruder actions
|
||||
{
|
||||
// Count intruder actions
|
||||
int actioncount;
|
||||
|
||||
actioncount = countIntruderActions ();
|
||||
|
||||
// Limit intruder actions in any case
|
||||
if (!switches.intruder)
|
||||
{
|
||||
if (actioncount > 0)
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: no intruder allowed.\n",
|
||||
switches.maxIntruderActions);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Limit on intruder events count
|
||||
if (actioncount > switches.maxIntruderActions)
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: more than %i encrypt/decrypt events in the semitrace.\n",
|
||||
switches.maxIntruderActions);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// No pruning because of bounds
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Detect when there are too many instances of a certain role
|
||||
int
|
||||
tooManyOfRole (const System sys)
|
||||
{
|
||||
int toomany;
|
||||
|
||||
toomany = false;
|
||||
if (switches.maxOfRole > 0)
|
||||
{
|
||||
Termmap f;
|
||||
int run;
|
||||
|
||||
f = NULL;
|
||||
for (run = 0; run < sys->maxruns; run++)
|
||||
{
|
||||
if (sys->runs[run].protocol != INTRUDER)
|
||||
{
|
||||
// maybe this conflicts with equal protocols...? TODO
|
||||
Term role;
|
||||
int count;
|
||||
|
||||
role = sys->runs[run].role->nameterm;
|
||||
count = termmapGet (f, role);
|
||||
if (count == -1)
|
||||
count = 1;
|
||||
else
|
||||
count++;
|
||||
f = termmapSet (f, role, count);
|
||||
if (count > switches.maxOfRole)
|
||||
{
|
||||
toomany = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
termmapDelete (f);
|
||||
}
|
||||
return toomany;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#ifndef PRUNEBOUNDS
|
||||
#define PRUNEBOUNDS
|
||||
|
||||
int prune_bounds (const System sys);
|
||||
|
||||
#endif
|
@ -1,484 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*@file prune_theorems.c
|
||||
*
|
||||
* Prune stuff based on theorems.
|
||||
* Pruning leaves complete results.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include "list.h"
|
||||
#include "switches.h"
|
||||
#include "binding.h"
|
||||
#include "specialterm.h"
|
||||
#include "hidelevel.h"
|
||||
#include "depend.h"
|
||||
#include "arachne.h"
|
||||
#include "error.h"
|
||||
#include "type.h"
|
||||
|
||||
extern Protocol INTRUDER;
|
||||
extern int proofDepth;
|
||||
extern int max_encryption_level;
|
||||
|
||||
|
||||
//! Check locals occurrence
|
||||
/*
|
||||
* Returns true if the order is correct
|
||||
*/
|
||||
int
|
||||
correctLocalOrder (const System sys)
|
||||
{
|
||||
int flag;
|
||||
|
||||
int checkRun (int r1)
|
||||
{
|
||||
int checkTerm (Term t)
|
||||
{
|
||||
if (!isTermVariable (t))
|
||||
{
|
||||
int r2;
|
||||
int e1, e2;
|
||||
|
||||
// t is a term from r2 that occurs in r1
|
||||
r2 = TermRunid (t);
|
||||
e1 = firstOccurrence (sys, r1, t, ANYEVENT);
|
||||
if (e1 >= 0)
|
||||
{
|
||||
if (roledef_shift (sys->runs[r1].start, e1)->type == READ)
|
||||
{
|
||||
e2 = firstOccurrence (sys, r2, t, SEND);
|
||||
if (e2 >= 0)
|
||||
{
|
||||
// thus, it should not be the case that e1 occurs before e2
|
||||
if (isDependEvent (r1, e1, r2, e2))
|
||||
{
|
||||
// That's not good!
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because ordering for term ");
|
||||
termSubstPrint (t);
|
||||
eprintf
|
||||
(" cannot be correct: the first send r%ii%i occurs after the read r%ii%i.\n",
|
||||
r2, e2, r1, e1);
|
||||
}
|
||||
flag = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("error: ");
|
||||
termPrint (sys->runs[r2].protocol->nameterm);
|
||||
eprintf (",");
|
||||
termPrint (sys->runs[r2].role->nameterm);
|
||||
eprintf (": term ");
|
||||
termSubstPrint (t);
|
||||
eprintf
|
||||
(" from run %i should occur in run %i, but it doesn't.\n",
|
||||
r2, r2);
|
||||
globalError--;
|
||||
error ("Abort");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a read first? That's definitely impossible (can be caused by choices
|
||||
globalError++;
|
||||
eprintf ("error: term ");
|
||||
termSubstPrint (t);
|
||||
eprintf
|
||||
(" from run %i should occur in run %i first in a READ event, but it occurs first in event %i.\n",
|
||||
r2, r1, e1);
|
||||
eprintf ("It occurs first in ");
|
||||
roledefPrint (eventRoledef (sys, r1, e1));
|
||||
eprintf ("\n");
|
||||
eprintf ("which starts with ");
|
||||
roledefPrint (eventRoledef (sys, r1, 0));
|
||||
eprintf ("\n");
|
||||
globalError--;
|
||||
error ("Abort");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("error: term ");
|
||||
termSubstPrint (t);
|
||||
eprintf
|
||||
(" from run %i should occur in run %i, but it doesn't.\n", r2,
|
||||
r1);
|
||||
globalError--;
|
||||
error ("Abort");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return iterateLocalToOther (sys, r1, checkTerm);
|
||||
}
|
||||
|
||||
flag = true;
|
||||
iterateRegularRuns (sys, checkRun);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
//! Check initiator roles
|
||||
/**
|
||||
* Returns false iff an agent type is wrong
|
||||
*/
|
||||
int
|
||||
initiatorAgentsType (const System sys)
|
||||
{
|
||||
int run;
|
||||
|
||||
run = 0;
|
||||
while (run < sys->maxruns)
|
||||
{
|
||||
// Only for initiators
|
||||
if (sys->runs[run].role->initiator)
|
||||
{
|
||||
Termlist agents;
|
||||
|
||||
agents = sys->runs[run].rho;
|
||||
while (agents != NULL)
|
||||
{
|
||||
if (!goodAgentType (agents->term))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
agents = agents->next;
|
||||
}
|
||||
}
|
||||
run++;
|
||||
}
|
||||
return true; // seems to be okay
|
||||
}
|
||||
|
||||
//! Prune determination because of theorems
|
||||
/**
|
||||
* When something is pruned because of this function, the state space is still
|
||||
* considered to be complete.
|
||||
*
|
||||
*@returns true iff this state is invalid because of a theorem
|
||||
*/
|
||||
int
|
||||
prune_theorems (const System sys)
|
||||
{
|
||||
List bl;
|
||||
int run;
|
||||
|
||||
// Check all types of the local agents according to the matching type
|
||||
if (!checkAllSubstitutions (sys))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned because some local variable was incorrectly subsituted.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if all actors are agents for responders (initiators come next)
|
||||
run = 0;
|
||||
while (run < sys->maxruns)
|
||||
{
|
||||
if (!sys->runs[run].role->initiator)
|
||||
{
|
||||
Term actor;
|
||||
|
||||
actor = agentOfRun (sys, run);
|
||||
if (!goodAgentType (actor))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the actor ");
|
||||
termPrint (actor);
|
||||
eprintf (" of run %i is not of a compatible type.\n", run);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
run++;
|
||||
}
|
||||
|
||||
// Prune if any initiator run talks to itself
|
||||
/**
|
||||
* This effectively disallows Alice from talking to Alice, for all
|
||||
* initiators. We still allow it for responder runs, because we assume the
|
||||
* responder is not checking this.
|
||||
*/
|
||||
if (switches.initUnique)
|
||||
{
|
||||
if (selfInitiators (sys) > 0)
|
||||
{
|
||||
// XXX TODO
|
||||
// Still need to fix proof output for this
|
||||
//
|
||||
// Pruning because some agents are equal for this role.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (switches.respUnique)
|
||||
{
|
||||
if (selfResponders (sys) > 0)
|
||||
{
|
||||
// XXX TODO
|
||||
// Still need to fix proof output for this
|
||||
//
|
||||
// Pruning because some agents are equal for this role.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Prune wrong agents type for initators
|
||||
if (!initiatorAgentsType (sys))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned: an initiator role does not have the correct type for one of its agents.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the actors of all other runs are not untrusted
|
||||
if (sys->untrusted != NULL)
|
||||
{
|
||||
int run;
|
||||
|
||||
run = 1;
|
||||
while (run < sys->maxruns)
|
||||
{
|
||||
if (sys->runs[run].protocol != INTRUDER)
|
||||
{
|
||||
if (sys->runs[run].rho != NULL)
|
||||
{
|
||||
Term actor;
|
||||
|
||||
actor = agentOfRun (sys, run);
|
||||
if (actor == NULL)
|
||||
{
|
||||
error ("Agent of run %i is NULL", run);
|
||||
}
|
||||
if (!isAgentTrusted (sys, actor))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned because the actor of run %i is untrusted.\n",
|
||||
run);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Protocol p;
|
||||
|
||||
globalError++;
|
||||
eprintf ("error: Run %i: ", run);
|
||||
role_name_print (run);
|
||||
eprintf (" has an empty agents list.\n");
|
||||
eprintf ("protocol->rolenames: ");
|
||||
p = (Protocol) sys->runs[run].protocol;
|
||||
termlistPrint (p->rolenames);
|
||||
eprintf ("\n");
|
||||
error ("Aborting.");
|
||||
globalError--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
run++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for c-minimality
|
||||
{
|
||||
if (!bindings_c_minimal ())
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because this is not <=c-minimal.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for correct orderings involving local constants
|
||||
*/
|
||||
if (!(switches.experimental & 8))
|
||||
{
|
||||
if (!correctLocalOrder (sys))
|
||||
{
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf
|
||||
("Pruned because this does not have the correct local order.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the bindings are valid
|
||||
*/
|
||||
bl = sys->bindings;
|
||||
while (bl != NULL)
|
||||
{
|
||||
Binding b;
|
||||
|
||||
b = bl->data;
|
||||
|
||||
// Check for "Hidden" interm goals
|
||||
//! @todo in the future, this can be subsumed by adding TERM_Hidden to the hidelevel constructs
|
||||
if (termInTerm (b->term, TERM_Hidden))
|
||||
{
|
||||
// Prune the state: we can never meet this
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because intruder can never construnct ");
|
||||
termPrint (b->term);
|
||||
eprintf ("\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (switches.experimental & 4)
|
||||
{
|
||||
// Check for SK-type function occurrences
|
||||
//!@todo Needs a LEMMA, although this seems to be quite straightforward to prove.
|
||||
// The idea is that functions are never sent as a whole, but only used in applications.
|
||||
//! @todo Subsumed by hidelevel lemma later
|
||||
if (isTermFunctionName (b->term))
|
||||
{
|
||||
if (!inKnowledge (sys->know, b->term))
|
||||
{
|
||||
// Not in initial knowledge of the intruder
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the function ");
|
||||
termPrint (b->term);
|
||||
eprintf (" is not known initially to the intruder.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for encryption levels
|
||||
/*
|
||||
* if (switches.match < 2
|
||||
*! @todo Doesn't work yet as desired for Tickets. Prove lemma first.
|
||||
*/
|
||||
if (switches.experimental & 2)
|
||||
{
|
||||
if (!hasTicketSubterm (b->term))
|
||||
{
|
||||
if (term_encryption_level (b->term) > max_encryption_level)
|
||||
{
|
||||
// Prune: we do not need to construct such terms
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the encryption level of ");
|
||||
termPrint (b->term);
|
||||
eprintf (" is too high.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To be on the safe side, we currently limit the encryption level.
|
||||
/**
|
||||
* This is not a problem for known attacks, but should be addressed more
|
||||
* carefully at some point. If there are variables that can contain
|
||||
* encryptions, this is maybe not correct: make proof!
|
||||
*
|
||||
* @todo Fix untyped variables reasoning
|
||||
*/
|
||||
if (term_encryption_level (b->term) > max_encryption_level)
|
||||
{
|
||||
// Prune: we do not need to construct such terms
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the encryption level of ");
|
||||
termPrint (b->term);
|
||||
eprintf (" is too high.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune on the basis of hidelevel lemma
|
||||
*/
|
||||
if (hidelevelImpossible (sys, b->term))
|
||||
{
|
||||
// Prune: we do not need to construct such terms
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the hidelevel of ");
|
||||
termPrint (b->term);
|
||||
eprintf (" is impossible to satisfy.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bl = bl->next;
|
||||
}
|
||||
|
||||
/* check for singular roles */
|
||||
run = 0;
|
||||
while (run < sys->maxruns)
|
||||
{
|
||||
if (sys->runs[run].role->singular)
|
||||
{
|
||||
// This is a singular role: it therefore should not occur later on again.
|
||||
int run2;
|
||||
Term rolename;
|
||||
|
||||
rolename = sys->runs[run].role->nameterm;
|
||||
run2 = run + 1;
|
||||
while (run2 < sys->maxruns)
|
||||
{
|
||||
Term rolename2;
|
||||
|
||||
rolename2 = sys->runs[run2].role->nameterm;
|
||||
if (isTermEqual (rolename, rolename2))
|
||||
{
|
||||
// This is not allowed: the singular role occurs twice in the semitrace.
|
||||
// Thus we prune.
|
||||
if (switches.output == PROOF)
|
||||
{
|
||||
indentPrint ();
|
||||
eprintf ("Pruned because the singular role ");
|
||||
termPrint (rolename);
|
||||
eprintf (" occurs more than once in the semitrace.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
run2++;
|
||||
}
|
||||
}
|
||||
run++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#ifndef PRUNETHEOREMS
|
||||
#define PRUNETHEOREMS
|
||||
|
||||
int prune_theorems (const System sys);
|
||||
|
||||
#endif
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Indent any changed files, ending in .c or .h
|
||||
#
|
||||
svn st | grep "^[MA].*\.[ch]$"| awk '{print $2}' | xargs indent
|
@ -1,33 +0,0 @@
|
||||
? 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.
|
||||
|
515
gui/src/role.c
515
gui/src/role.c
@ -1,515 +0,0 @@
|
||||
/**
|
||||
* @file role.c
|
||||
* \brief role related logic.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
#include "knowledge.h"
|
||||
#include "system.h"
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
#include "role.h"
|
||||
|
||||
extern int protocolCount; // from system.c
|
||||
|
||||
//! Allocate memory the size of a roledef struct.
|
||||
Roledef
|
||||
makeRoledef ()
|
||||
{
|
||||
return (Roledef) malloc (sizeof (struct roledef));
|
||||
}
|
||||
|
||||
//! Print a role event.
|
||||
/**
|
||||
* If print_actor is true, the actor is included (OS version), otherwise it is left out (short stuff)
|
||||
*/
|
||||
void
|
||||
roledefPrintGeneric (Roledef rd, int print_actor)
|
||||
{
|
||||
if (rd == NULL)
|
||||
{
|
||||
eprintf ("[Empty roledef]");
|
||||
return;
|
||||
}
|
||||
if (rd->type == READ && rd->internal)
|
||||
{
|
||||
/* special case: internal read == choose ! */
|
||||
eprintf ("CHOOSE(");
|
||||
termPrint (rd->message);
|
||||
eprintf (")");
|
||||
return;
|
||||
}
|
||||
if (rd->type == READ)
|
||||
eprintf ("READ");
|
||||
if (rd->type == SEND)
|
||||
eprintf ("SEND");
|
||||
if (rd->type == CLAIM)
|
||||
eprintf ("CLAIM");
|
||||
if (rd->label != NULL)
|
||||
{
|
||||
//! Print label
|
||||
Term label;
|
||||
|
||||
/* Old version: sometimes prints protocol stuff (really unique labels)
|
||||
label = deVar (rd->label);
|
||||
if (protocolCount < 2 && realTermTuple (label))
|
||||
{
|
||||
// Only one protocol, so we don't need to show the extra label info
|
||||
label = TermOp2 (label);
|
||||
}
|
||||
*/
|
||||
label = deVar (rd->label);
|
||||
if (realTermTuple (label))
|
||||
{
|
||||
label = TermOp2 (label);
|
||||
}
|
||||
|
||||
eprintf ("_");
|
||||
termPrint (label);
|
||||
}
|
||||
eprintf ("(");
|
||||
if (!(rd->from == NULL && rd->to == NULL))
|
||||
{
|
||||
if (print_actor || rd->type == READ)
|
||||
{
|
||||
termPrint (rd->from);
|
||||
eprintf (",");
|
||||
}
|
||||
if (rd->type == CLAIM)
|
||||
eprintf (" ");
|
||||
if (print_actor || rd->type != READ)
|
||||
{
|
||||
termPrint (rd->to);
|
||||
eprintf (", ");
|
||||
}
|
||||
}
|
||||
termPrint (rd->message);
|
||||
eprintf (" )");
|
||||
}
|
||||
|
||||
//! Print a roledef
|
||||
void
|
||||
roledefPrint (Roledef rd)
|
||||
{
|
||||
roledefPrintGeneric (rd, 1);
|
||||
}
|
||||
|
||||
//! Print a roledef, but shorten it
|
||||
void
|
||||
roledefPrintShort (Roledef rd)
|
||||
{
|
||||
roledefPrintGeneric (rd, 0);
|
||||
}
|
||||
|
||||
|
||||
//! Duplicate a single role event node.
|
||||
/**
|
||||
*\sa roledefDelete()
|
||||
*/
|
||||
Roledef
|
||||
roledefDuplicate1 (const Roledef rd)
|
||||
{
|
||||
Roledef newrd;
|
||||
|
||||
if (rd == NULL)
|
||||
return NULL;
|
||||
newrd = makeRoledef ();
|
||||
memcpy (newrd, rd, sizeof (struct roledef));
|
||||
newrd->next = NULL;
|
||||
return newrd;
|
||||
}
|
||||
|
||||
//! Duplicate a role event list.
|
||||
/**
|
||||
*\sa roledefDelete()
|
||||
*/
|
||||
Roledef
|
||||
roledefDuplicate (Roledef rd)
|
||||
{
|
||||
Roledef newrd;
|
||||
|
||||
if (rd == NULL)
|
||||
return NULL;
|
||||
newrd = roledefDuplicate1 (rd);
|
||||
newrd->next = roledefDuplicate (rd->next);
|
||||
return newrd;
|
||||
}
|
||||
|
||||
//! Delete a role event or event list.
|
||||
/**
|
||||
*\sa roledefDuplicate()
|
||||
*/
|
||||
void
|
||||
roledefDelete (Roledef rd)
|
||||
{
|
||||
if (rd == NULL)
|
||||
return;
|
||||
roledefDelete (rd->next);
|
||||
free (rd);
|
||||
return;
|
||||
}
|
||||
|
||||
//! Destroy a role event or event list.
|
||||
void
|
||||
roledefDestroy (Roledef rd)
|
||||
{
|
||||
if (rd == NULL)
|
||||
return;
|
||||
roledefDestroy (rd->next);
|
||||
termDelete (rd->from);
|
||||
termDelete (rd->to);
|
||||
termDelete (rd->message);
|
||||
free (rd);
|
||||
return;
|
||||
}
|
||||
|
||||
//! Make a new role event with the specified parameters.
|
||||
/**
|
||||
*@return A pointer to a new role event with the given parameters.
|
||||
*/
|
||||
Roledef
|
||||
roledefInit (int type, Term label, Term from, Term to, Term msg, Claimlist cl)
|
||||
{
|
||||
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->claiminfo = cl; // only for claims
|
||||
if (type == READ)
|
||||
newEvent->bound = 0; // bound goal (Used for arachne only). Technically involves choose events as well.
|
||||
else
|
||||
newEvent->bound = 1; // other stuff does not need to be bound
|
||||
newEvent->next = NULL;
|
||||
newEvent->lineno = 0;
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
//! Add a role event to an existing list, with the given parameters.
|
||||
/**
|
||||
*\sa roledefInit()
|
||||
*/
|
||||
Roledef
|
||||
roledefAdd (Roledef rd, int type, Term label, Term from, Term to, Term msg,
|
||||
Claimlist cl)
|
||||
{
|
||||
Roledef scan;
|
||||
|
||||
if (rd == NULL)
|
||||
return roledefInit (type, label, from, to, msg, cl);
|
||||
|
||||
scan = rd;
|
||||
while (scan->next != NULL)
|
||||
scan = scan->next;
|
||||
scan->next = roledefInit (type, label, from, to, msg, cl);
|
||||
return rd;
|
||||
}
|
||||
|
||||
//! Create an empty role structure with a name.
|
||||
Role
|
||||
roleCreate (Term name)
|
||||
{
|
||||
Role r;
|
||||
|
||||
r = malloc (sizeof (struct role));
|
||||
r->nameterm = name;
|
||||
r->roledef = NULL;
|
||||
r->locals = NULL;
|
||||
r->variables = NULL;
|
||||
r->declaredvars = NULL;
|
||||
r->declaredconsts = NULL;
|
||||
r->initiator = 1; //! Will be determined later, if a read is the first action (in compiler.c)
|
||||
r->singular = false; // by default, a role is not singular
|
||||
r->next = NULL;
|
||||
r->knows = NULL;
|
||||
r->lineno = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
//! Print a role.
|
||||
void
|
||||
rolePrint (Role r)
|
||||
{
|
||||
Roledef rd;
|
||||
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
indent ();
|
||||
eprintf ("[[Role : ");
|
||||
termPrint (r->nameterm);
|
||||
eprintf ("]]\n");
|
||||
locVarPrint (r->locals);
|
||||
|
||||
rd = r->roledef;
|
||||
while (rd != NULL)
|
||||
{
|
||||
roledefPrint (rd);
|
||||
eprintf ("\n");
|
||||
rd = rd->next;
|
||||
}
|
||||
}
|
||||
|
||||
//! Print a list of roles.
|
||||
void
|
||||
rolesPrint (Role r)
|
||||
{
|
||||
if (r == NULL)
|
||||
{
|
||||
eprintf ("Empty role.");
|
||||
}
|
||||
else
|
||||
{
|
||||
while (r != NULL)
|
||||
{
|
||||
rolePrint (r);
|
||||
r = r->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Iterate over the events in a roledef list
|
||||
/**
|
||||
* Function gets roledef pointer
|
||||
*/
|
||||
int
|
||||
roledef_iterate_events (Roledef rd, int (*func) ())
|
||||
{
|
||||
while (rd != NULL)
|
||||
{
|
||||
if (!func (rd))
|
||||
return 0;
|
||||
rd = rd->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Roledef length
|
||||
/**
|
||||
* Would be faster hard-coded,
|
||||
* but this just shows the use of the iteration.
|
||||
*/
|
||||
int
|
||||
roledef_length (const Roledef rd)
|
||||
{
|
||||
int count = 0;
|
||||
int countplus (Roledef rd)
|
||||
{
|
||||
count++;
|
||||
return 1;
|
||||
}
|
||||
roledef_iterate_events (rd, countplus);
|
||||
return count;
|
||||
}
|
||||
|
||||
//! Yield roledef pointer for a given index
|
||||
Roledef
|
||||
roledef_shift (Roledef rd, int i)
|
||||
{
|
||||
while (i > 0 && rd != NULL)
|
||||
{
|
||||
rd = rd->next;
|
||||
i--;
|
||||
}
|
||||
return rd;
|
||||
}
|
||||
|
||||
//! Check whether a term is a subterm of a roledef
|
||||
int
|
||||
roledefSubTerm (Roledef rd, Term tsub)
|
||||
{
|
||||
if (rd == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (termSubTerm (rd->from, tsub) ||
|
||||
termSubTerm (rd->to, tsub) || termSubTerm (rd->message, tsub));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some stuff directly from the semantics
|
||||
*/
|
||||
|
||||
//! Is a term readable (from some knowledge set)
|
||||
/**
|
||||
* Returns value of predicate
|
||||
*/
|
||||
int
|
||||
Readable (Knowledge know, Term t)
|
||||
{
|
||||
if (isTermVariable (t))
|
||||
{
|
||||
// Variable pattern
|
||||
return true;
|
||||
}
|
||||
if (!isTermLeaf (t))
|
||||
{
|
||||
if (isTermTuple (t))
|
||||
{
|
||||
// Tuple pattern
|
||||
Knowledge knowalt;
|
||||
int both;
|
||||
|
||||
both = false;
|
||||
knowalt = knowledgeDuplicate (know);
|
||||
knowledgeAddTerm (knowalt, TermOp2 (t));
|
||||
if (Readable (knowalt, TermOp1 (t)))
|
||||
{
|
||||
// Yes, left half works
|
||||
knowledgeDelete (knowalt);
|
||||
knowalt = knowledgeDuplicate (know);
|
||||
knowledgeAddTerm (knowalt, TermOp1 (t));
|
||||
if (Readable (knowalt, TermOp2 (t)))
|
||||
{
|
||||
both = true;
|
||||
}
|
||||
}
|
||||
knowledgeDelete (knowalt);
|
||||
return both;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Encryption pattern
|
||||
// But we exclude functions
|
||||
if (getTermFunction (t) == NULL)
|
||||
{
|
||||
// Real encryption pattern
|
||||
Term inv;
|
||||
int either;
|
||||
|
||||
// Left disjunct
|
||||
if (inKnowledge (know, t))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Right disjunct
|
||||
inv = inverseKey (know->inverses, TermKey (t));
|
||||
either = false;
|
||||
if (inKnowledge (know, inv))
|
||||
{
|
||||
if (Readable (know, TermOp (t)))
|
||||
{
|
||||
either = true;
|
||||
}
|
||||
}
|
||||
termDelete (inv);
|
||||
return either;
|
||||
}
|
||||
}
|
||||
}
|
||||
return inKnowledge (know, t);
|
||||
}
|
||||
|
||||
//! Well-formed error reporting.
|
||||
void
|
||||
wfeError (Knowledge know, Roledef rd, char *errorstring, Term was,
|
||||
Term shouldbe)
|
||||
{
|
||||
globalError++;
|
||||
eprintf ("Well-formedness error.\n");
|
||||
roledefPrint (rd);
|
||||
eprintf ("\nKnowing ");
|
||||
knowledgePrintShort (know);
|
||||
eprintf ("\n");
|
||||
if (was != NULL || shouldbe != NULL)
|
||||
{
|
||||
eprintf ("while parsing ");
|
||||
termPrint (was);
|
||||
if (shouldbe != NULL)
|
||||
{
|
||||
eprintf (" which should have been ");
|
||||
termPrint (shouldbe);
|
||||
}
|
||||
eprintf ("\n");
|
||||
}
|
||||
globalError--;
|
||||
error (errorstring);
|
||||
}
|
||||
|
||||
|
||||
//! Is an event well-formed
|
||||
/**
|
||||
* Returns the new knowledge or NULL if it was not well-formed.
|
||||
*/
|
||||
Knowledge
|
||||
WellFormedEvent (Term role, Knowledge know, Roledef rd)
|
||||
{
|
||||
if (rd == NULL)
|
||||
{
|
||||
return know;
|
||||
}
|
||||
if (rd->type == READ)
|
||||
{
|
||||
// Read
|
||||
if (!isTermEqual (role, rd->to))
|
||||
{
|
||||
wfeError (know, rd, "Reading role incorrect.", rd->to, role);
|
||||
return NULL;
|
||||
}
|
||||
if (!inKnowledge (know, rd->from))
|
||||
{
|
||||
wfeError (know, rd, "Unknown sender role.", rd->from, NULL);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
if (!Readable (know, rd->message))
|
||||
{
|
||||
wfeError (know, rd, "Cannot read message pattern.", rd->message,
|
||||
NULL);
|
||||
return NULL;
|
||||
}
|
||||
knowledgeAddTerm (know, rd->message);
|
||||
return know;
|
||||
}
|
||||
if (rd->type == SEND)
|
||||
{
|
||||
// Send
|
||||
if (!isTermEqual (role, rd->from))
|
||||
{
|
||||
wfeError (know, rd, "Sending role incorrect.", rd->from, role);
|
||||
return NULL;
|
||||
}
|
||||
if (!inKnowledge (know, rd->to))
|
||||
{
|
||||
wfeError (know, rd, "Unknown reading role.", rd->to, NULL);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
if (!inKnowledge (know, rd->message))
|
||||
{
|
||||
wfeError (know, rd, "Unable to construct message.", rd->message,
|
||||
NULL);
|
||||
return NULL;
|
||||
}
|
||||
return know;
|
||||
}
|
||||
if (rd->type == CLAIM)
|
||||
{
|
||||
// Claim
|
||||
if (!isTermEqual (role, rd->from))
|
||||
{
|
||||
wfeError (know, rd, "Claiming role incorrect.", rd->from, role);
|
||||
return NULL;
|
||||
}
|
||||
return know;
|
||||
}
|
||||
// Unknown, false
|
||||
globalError++;
|
||||
roledefPrint (rd);
|
||||
globalError--;
|
||||
error ("I don't know this event");
|
||||
return NULL;
|
||||
}
|
174
gui/src/role.h
174
gui/src/role.h
@ -1,174 +0,0 @@
|
||||
#ifndef ROLES
|
||||
#define ROLES
|
||||
|
||||
#include "term.h"
|
||||
#include "termmap.h"
|
||||
#include "termlist.h"
|
||||
#include "knowledge.h"
|
||||
#include "states.h"
|
||||
|
||||
enum eventtype
|
||||
{ READ, SEND, CLAIM, ANYEVENT };
|
||||
|
||||
//! The container for the claim info list
|
||||
/**
|
||||
* Defaults are set in compiler.c (claimCreate)
|
||||
*/
|
||||
struct claimlist
|
||||
{
|
||||
//! The type of claim
|
||||
Term type;
|
||||
//! The term element for this node.
|
||||
Term label;
|
||||
//! Any parameters
|
||||
Term parameter;
|
||||
//! The pointer to the protocol (not defined typically, because
|
||||
//! at compile time of the claim the protocol structure is not known yet.)
|
||||
void *protocol;
|
||||
//! The name of the role in which it occurs.
|
||||
Term rolename;
|
||||
//! The pointer to the role structure
|
||||
void *role;
|
||||
//! The pointer to the roledef
|
||||
void *roledef;
|
||||
//! Number of occurrences in system exploration.
|
||||
states_t count;
|
||||
//! Number of occurrences that failed.
|
||||
states_t failed;
|
||||
//! Number of iterations traversed for this claim.
|
||||
states_t states;
|
||||
//! Whether the result is complete or not (failings always are!)
|
||||
int complete;
|
||||
//! If we ran into the time bound (incomplete, and bad for results)
|
||||
int timebound;
|
||||
//! Some claims are always true (shown by the initial scan)
|
||||
int alwaystrue;
|
||||
//! Warnings should tell you more
|
||||
int warnings;
|
||||
|
||||
int r; //!< role number for mapping
|
||||
int ev; //!< event index in role
|
||||
//! Preceding label list
|
||||
Termlist prec;
|
||||
//! Roles that are involved (nameterms)
|
||||
Termlist roles;
|
||||
//! Next node pointer or NULL for the last element of the function.
|
||||
struct claimlist *next;
|
||||
|
||||
int lineno;
|
||||
};
|
||||
|
||||
//! Shorthand for claimlist pointers.
|
||||
typedef struct claimlist *Claimlist;
|
||||
|
||||
//! Structure for a role event node or list.
|
||||
/**
|
||||
*\sa role
|
||||
*/
|
||||
struct roledef
|
||||
{
|
||||
//! flag for internal actions.
|
||||
/**
|
||||
* Typically, this is true to signify internal reads (e.g. variable choices)
|
||||
* as opposed to a normal read.
|
||||
*/
|
||||
int internal;
|
||||
//! Type of event.
|
||||
/**
|
||||
*\sa READ, SEND, CLAIM
|
||||
*/
|
||||
int type;
|
||||
//! Event label.
|
||||
Term label;
|
||||
//! Event sender.
|
||||
Term from;
|
||||
//! Event target.
|
||||
Term to;
|
||||
//! Event message.
|
||||
Term message;
|
||||
//! Pointer to next roledef node.
|
||||
struct roledef *next;
|
||||
|
||||
/*
|
||||
* Substructure for reads
|
||||
*/
|
||||
//! Illegal injections for this event.
|
||||
/**
|
||||
* For send this means that the send is allowed if it is NULL, otherwise it is blocked.
|
||||
*/
|
||||
Knowledge forbidden;
|
||||
//! knowledge transitions counter.
|
||||
int knowPhase;
|
||||
|
||||
/*
|
||||
* Substructure for claims
|
||||
*/
|
||||
//! Pointer to claim type info
|
||||
Claimlist claiminfo;
|
||||
|
||||
/*
|
||||
* Bindings for Arachne engine
|
||||
*/
|
||||
int bound; //!< determines whether it is already bound
|
||||
|
||||
/* evt runid for synchronisation, but that is implied in the
|
||||
base array */
|
||||
int lineno;
|
||||
};
|
||||
|
||||
//! Shorthand for roledef pointer.
|
||||
typedef struct roledef *Roledef;
|
||||
|
||||
//! Role definition.
|
||||
/**
|
||||
*\sa roledef
|
||||
*/
|
||||
struct role
|
||||
{
|
||||
//! Name of the role encoded in a term.
|
||||
Term nameterm;
|
||||
//! List of role events.
|
||||
Roledef roledef;
|
||||
//! Local constants for this role.
|
||||
Termlist locals;
|
||||
//! Local variables for this role.
|
||||
Termlist variables;
|
||||
//! Declared constants for this role
|
||||
Termlist declaredconsts;
|
||||
//! Declared variables for this role
|
||||
Termlist declaredvars;
|
||||
//! Initial role knowledge
|
||||
Termlist knows;
|
||||
//! Flag for initiator roles
|
||||
int initiator;
|
||||
//! Flag for singular roles
|
||||
int singular;
|
||||
//! Pointer to next role definition.
|
||||
struct role *next;
|
||||
//! Line number
|
||||
int lineno;
|
||||
};
|
||||
|
||||
//! Shorthand for role pointer.
|
||||
typedef struct role *Role;
|
||||
|
||||
void roledefPrint (Roledef rd);
|
||||
void roledefPrintShort (Roledef rd);
|
||||
Roledef roledefDuplicate1 (const Roledef rd);
|
||||
Roledef roledefDuplicate (Roledef rd);
|
||||
void roledefDelete (Roledef rd);
|
||||
void roledefDestroy (Roledef rd);
|
||||
Roledef roledefInit (int type, Term label, Term from, Term to, Term msg,
|
||||
Claimlist cl);
|
||||
Roledef roledefAdd (Roledef rd, int type, Term label, Term from, Term to,
|
||||
Term msg, Claimlist cl);
|
||||
Role roleCreate (Term nameterm);
|
||||
void rolePrint (Role r);
|
||||
void rolesPrint (Role r);
|
||||
int roledef_iterate_events (Roledef rd, int (*func) ());
|
||||
int roledef_length (const Roledef rd);
|
||||
Roledef roledef_shift (Roledef rd, int i);
|
||||
int roledefSubTerm (Roledef rd, Term tsub);
|
||||
Knowledge WellFormedEvent (Term role, Knowledge know, Roledef rd);
|
||||
|
||||
#endif
|
@ -1,227 +0,0 @@
|
||||
%option yylineno
|
||||
|
||||
%{
|
||||
/* scanner for security protocols language */
|
||||
|
||||
#include <strings.h>
|
||||
#include "pheading.h"
|
||||
#include "tac.h"
|
||||
#include "switches.h"
|
||||
#include "error.h"
|
||||
|
||||
/* tokens for language */
|
||||
#include "parser.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\r\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}|[\^\-!'])+
|
||||
|
||||
/* the "incl" state is used for picking up the name of an include file
|
||||
*/
|
||||
%x incl inclend
|
||||
|
||||
%{
|
||||
#define MAX_INCLUDE_DEPTH 10
|
||||
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
|
||||
int include_stack_ptr = 0;
|
||||
%}
|
||||
|
||||
%%
|
||||
include BEGIN(incl);
|
||||
<incl>[ \t]*\" /* eat the whitespace */
|
||||
<incl>[^\"]+ { /* got the include file name */
|
||||
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
|
||||
{
|
||||
printfstderr( "Includes nested too deeply" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
include_stack[include_stack_ptr++] =
|
||||
YY_CURRENT_BUFFER;
|
||||
|
||||
/* try to open, using scytherdirs environment variable as well. */
|
||||
yyin = openFileSearch (yytext, NULL);
|
||||
|
||||
if (! yyin)
|
||||
{
|
||||
error ("could not open include file %s.", yytext);
|
||||
}
|
||||
|
||||
yy_switch_to_buffer(
|
||||
yy_create_buffer( yyin, YY_BUF_SIZE ) );
|
||||
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<inclend>\";? { /* eat the closing things */
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
<INITIAL><<EOF>> {
|
||||
if ( --include_stack_ptr < 0 )
|
||||
{
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
yy_delete_buffer( YY_CURRENT_BUFFER );
|
||||
yy_switch_to_buffer(
|
||||
include_stack[include_stack_ptr] );
|
||||
BEGIN(inclend);
|
||||
}
|
||||
}
|
||||
|
||||
"/*" {
|
||||
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; }
|
||||
singular { return SINGULAR; }
|
||||
function { return FUNCTION; }
|
||||
hashfunction { return HASHFUNCTION; }
|
||||
knows { return KNOWS; }
|
||||
trusted { return TRUSTED; }
|
||||
{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 *)malloc(len+1);
|
||||
sl = (Stringlist) malloc(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;
|
||||
free(sl->string);
|
||||
free(sl);
|
||||
}
|
||||
}
|
||||
|
||||
int yywrap (void)
|
||||
{
|
||||
/* signal true to let lex know that nothing else is coming */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void mkval(void);
|
||||
void mktext(void);
|
||||
*/
|
||||
|
||||
|
||||
// vim:ft=lex:
|
@ -1,119 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import commands
|
||||
import sys
|
||||
|
||||
class Tag(object):
|
||||
"""
|
||||
Object for tag (ctag line)
|
||||
"""
|
||||
|
||||
def __init__(self,tagline):
|
||||
tl = tagline.strip().split('\t')
|
||||
self.id = tl[0]
|
||||
self.filename = tl[1]
|
||||
|
||||
def __str__(self):
|
||||
return self.id
|
||||
|
||||
class GrepRes(object):
|
||||
"""
|
||||
Object for a result line from grep
|
||||
"""
|
||||
|
||||
def __init__(self,line):
|
||||
self.line = line
|
||||
x = line.find(":")
|
||||
if x:
|
||||
self.filename = line[:x]
|
||||
self.text = line[x:].strip()
|
||||
else:
|
||||
self.filename = None
|
||||
self.text = None
|
||||
|
||||
def __str__(self):
|
||||
return self.line
|
||||
|
||||
|
||||
def outToRes(out,filter=[]):
|
||||
"""
|
||||
filter grep output and make a list of GrepRes objects. Filter out
|
||||
any that come from the filenames in the filter list. Also return the
|
||||
count of all results (not taking the filter into account).
|
||||
"""
|
||||
|
||||
reslist = []
|
||||
count = 0
|
||||
for l in out.splitlines():
|
||||
gr = GrepRes(l)
|
||||
if gr.filename not in filter:
|
||||
reslist.append(gr)
|
||||
count = count+1
|
||||
return (reslist,count)
|
||||
|
||||
def gettags():
|
||||
"""
|
||||
Get all the tags in a list
|
||||
"""
|
||||
|
||||
f = open("tags","r")
|
||||
tags = []
|
||||
for l in f.readlines():
|
||||
if not l.startswith("!"):
|
||||
tags.append(Tag(l))
|
||||
f.close()
|
||||
return tags
|
||||
|
||||
def tagoccurs(problems,tag,filter=[]):
|
||||
"""
|
||||
Check tag occurrences in certain files and show interesting ones.
|
||||
"""
|
||||
|
||||
cmd = "grep \"\\<%s\\>\" *.[chly]" % tag
|
||||
(reslist,count) = outToRes(commands.getoutput(cmd),[tag.filename])
|
||||
if (len(reslist) == 0) and (count < 2):
|
||||
if tag.filename not in filter:
|
||||
# this might be a problem, store it
|
||||
if tag.filename not in problems.keys():
|
||||
problems[tag.filename] = {}
|
||||
problems[tag.filename][tag.id] = count
|
||||
|
||||
return problems
|
||||
|
||||
|
||||
def tagreport(problems):
|
||||
for fn in problems.keys():
|
||||
print "file: %s" % fn
|
||||
for t in problems[fn].keys():
|
||||
print "\t%i\t%s" % (problems[fn][t],t)
|
||||
|
||||
|
||||
def main():
|
||||
# Generate tags
|
||||
print "Generating tags using 'ctags'"
|
||||
cmd = "ctags *.c *.h *.l *.y"
|
||||
commands.getoutput(cmd)
|
||||
|
||||
# Analyze results
|
||||
print "Analyzing results"
|
||||
filter = ["scanner.c","parser.c"]
|
||||
tags = gettags()
|
||||
problems = {}
|
||||
total = len(tags)
|
||||
count = 0
|
||||
steps = 20
|
||||
print "_ " * (steps)
|
||||
|
||||
for t in tags:
|
||||
problems = tagoccurs(problems,t,filter)
|
||||
count = count + 1
|
||||
if count % (total / steps) == 0:
|
||||
print "^",
|
||||
sys.stdout.flush()
|
||||
print
|
||||
print
|
||||
|
||||
tagreport (problems)
|
||||
|
||||
main()
|
||||
|
@ -1,97 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
#include "compiler.h"
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* Some macros
|
||||
*/
|
||||
#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)
|
||||
|
||||
/* externally used:
|
||||
*/
|
||||
|
||||
Term TERM_Agent;
|
||||
Term TERM_Function;
|
||||
Term TERM_Hidden;
|
||||
Term TERM_Type;
|
||||
Term TERM_Nonce;
|
||||
Term TERM_Ticket;
|
||||
Term TERM_Data;
|
||||
|
||||
Term TERM_Claim;
|
||||
Term CLAIM_Secret;
|
||||
Term CLAIM_Nisynch;
|
||||
Term CLAIM_Niagree;
|
||||
Term CLAIM_Empty;
|
||||
Term CLAIM_Reachable;
|
||||
|
||||
Termlist CLAIMS_dep_prec;
|
||||
|
||||
//! Init special terms
|
||||
/**
|
||||
* This is called by compilerInit
|
||||
*/
|
||||
void
|
||||
specialTermInit (const System sys)
|
||||
{
|
||||
/* Init system constants */
|
||||
|
||||
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 (TERM_Ticket, "Ticket", TERM_Type);
|
||||
langcons (TERM_Data, "Data", TERM_Type);
|
||||
|
||||
langcons (CLAIM_Secret, "Secret", TERM_Claim);
|
||||
langcons (CLAIM_Nisynch, "Nisynch", TERM_Claim);
|
||||
langcons (CLAIM_Niagree, "Niagree", TERM_Claim);
|
||||
langcons (CLAIM_Empty, "Empty", TERM_Claim);
|
||||
langcons (CLAIM_Reachable, "Reachable", TERM_Claim);
|
||||
|
||||
/* Construct a list of claims that depend on prec being not-empty */
|
||||
/* basically all authentication claims */
|
||||
CLAIMS_dep_prec = termlistAdd (NULL, CLAIM_Niagree);
|
||||
CLAIMS_dep_prec = termlistAdd (CLAIMS_dep_prec, CLAIM_Nisynch);
|
||||
|
||||
}
|
||||
|
||||
//! Determine whether this is a leaf construct with a ticket in it
|
||||
int
|
||||
isTicketTerm (Term t)
|
||||
{
|
||||
if (t != NULL)
|
||||
{
|
||||
if (realTermLeaf (t))
|
||||
{
|
||||
if (inTermlist (t->stype, TERM_Ticket))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (realTermVariable (t))
|
||||
{
|
||||
return isTicketTerm (t->subst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Determine whether this is a term with a Ticket in it
|
||||
int
|
||||
hasTicketSubterm (Term t)
|
||||
{
|
||||
// Doesn't work yet
|
||||
return true;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#ifndef SPECIALTERM
|
||||
#define SPECIALTERM
|
||||
|
||||
#include "term.h"
|
||||
#include "termlist.h"
|
||||
#include "system.h"
|
||||
|
||||
/*
|
||||
* Some declarations in spercialterm.c
|
||||
*/
|
||||
|
||||
extern Term TERM_Agent;
|
||||
extern Term TERM_Function;
|
||||
extern Term TERM_Hidden;
|
||||
extern Term TERM_Type;
|
||||
extern Term TERM_Nonce;
|
||||
extern Term TERM_Ticket;
|
||||
extern Term TERM_Data;
|
||||
|
||||
extern Term TERM_Claim;
|
||||
extern Term CLAIM_Secret;
|
||||
extern Term CLAIM_Nisynch;
|
||||
extern Term CLAIM_Niagree;
|
||||
extern Term CLAIM_Empty;
|
||||
extern Term CLAIM_Reachable;
|
||||
|
||||
extern Termlist CLAIMS_dep_prec;
|
||||
|
||||
void specialTermInit (const System sys);
|
||||
int isTicketTerm (Term t);
|
||||
int hasTicketSubterm (Term t);
|
||||
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
#include "states.h"
|
||||
#include "symbol.h"
|
||||
|
||||
/* States counter operations
|
||||
*
|
||||
* Note that these are also used for encountered claims and such.
|
||||
*/
|
||||
|
||||
__inline__ states_t
|
||||
statesIncrease (const states_t states)
|
||||
{
|
||||
return states + 1;
|
||||
}
|
||||
|
||||
__inline__ double
|
||||
statesDouble (const states_t states)
|
||||
{
|
||||
return (double) states;
|
||||
}
|
||||
|
||||
__inline__ int
|
||||
statesSmallerThan (const states_t states, unsigned long int reflint)
|
||||
{
|
||||
if (states < (states_t) reflint)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sensible output for number of states/claims
|
||||
/**
|
||||
* Acts like a modified form of %g
|
||||
*/
|
||||
__inline__ void
|
||||
statesFormat (const states_t states)
|
||||
{
|
||||
eprintf ("%lu", states);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#ifndef STATES
|
||||
#define STATES
|
||||
/**
|
||||
* Header file for the states counter datatype.
|
||||
*
|
||||
* Previously, the states number was just a unsigned int, but that
|
||||
* turned out to be insufficient.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef unsigned long int states_t;
|
||||
#define STATES0 0
|
||||
|
||||
__inline__ states_t statesIncrease (const states_t states);
|
||||
__inline__ double statesDouble (const states_t states);
|
||||
__inline__ int statesSmallerThan (const states_t states,
|
||||
unsigned long int reflint);
|
||||
__inline__ void statesFormat (const states_t states);
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Default flags
|
||||
CMFLAGS="-D CMAKE_BUILD_TYPE:STRING=Release"
|
||||
|
||||
# Make for ppc and intel, and combine into universal binary
|
||||
cmake $CMFLAGS -D TARGETOS=MacPPC . && make
|
||||
cmake $CMFLAGS -D TARGETOS=MacIntel . && make
|
||||
cmake $CMFLAGS . && make scyther-mac
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "---------------------------------------------------------"
|
||||
echo "Built the Mac universal binary"
|
||||
|
||||
# Copy to the correct locations
|
||||
cp scyther-mac ../gui/Scyther/Bin
|
||||
|
||||
echo Copied the files to their respective locations
|
||||
echo "---------------------------------------------------------"
|
||||
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Default flags
|
||||
CMFLAGS="-D CMAKE_BUILD_TYPE:STRING=Release"
|
||||
|
||||
# Make for windows and linux
|
||||
cmake $CMFLAGS -D TARGETOS=Win32 . && make
|
||||
cmake $CMFLAGS . && make
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "---------------------------------------------------------"
|
||||
echo "Built the Linux and Windows binaries"
|
||||
|
||||
# Copy to the correct locations
|
||||
cp scyther-linux ../gui/Scyther/Bin
|
||||
cp scyther-w32.exe ../gui/Scyther/Bin
|
||||
|
||||
# bonus...
|
||||
cp scyther-linux ~/bin
|
||||
|
||||
echo Copied the files to their respective locations and \~/bin
|
||||
echo "---------------------------------------------------------"
|
||||
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# svnversion executable path
|
||||
#
|
||||
|
||||
SVNVERSION=`svnversion`
|
||||
TAGVERSION=`awk 'BEGIN { FS="\""; } { print $2; }' ../gui/Gui/Version.py`
|
||||
|
||||
echo $SVNVERSION
|
||||
echo $TAGVERSION
|
||||
|
||||
# Fix svnversion information
|
||||
echo "#define SVNVERSION \"$SVNVERSION\"" >version.h
|
||||
# Fix version tag
|
||||
echo "#define TAGVERSION \"$TAGVERSION\"" >>version.h
|
||||
|
||||
|
1575
gui/src/switches.c
1575
gui/src/switches.c
File diff suppressed because it is too large
Load Diff
@ -1,74 +0,0 @@
|
||||
#ifndef SWITCHES
|
||||
#define SWITCHES
|
||||
|
||||
#include "term.h"
|
||||
#include "system.h"
|
||||
|
||||
void switchesInit ();
|
||||
void switchesDone ();
|
||||
|
||||
//! Command-line switches structure
|
||||
struct switchdata
|
||||
{
|
||||
// Command-line
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
// Methods
|
||||
int match; //!< Matching type.
|
||||
int tupling; //!< Tupling is by default 0: right-associative, optionally 1: left-associative.
|
||||
|
||||
// Pruning and Bounding
|
||||
int prune; //!< Type of pruning.
|
||||
int maxproofdepth; //!< Maximum proof depth
|
||||
int maxtracelength; //!< Maximum trace length allowed
|
||||
int runs; //!< The number of runs as in the switch
|
||||
char *filterProtocol; //!< Which claim should be checked?
|
||||
char *filterLabel; //!< Which claim should be checked?
|
||||
int maxAttacks; //!< When not 0, maximum number of attacks
|
||||
int maxOfRole; //!< When not 0, maximum number of instances of each unique (non intruder) role
|
||||
|
||||
// Arachne
|
||||
int heuristic; //!< Goal selection method for Arachne engine
|
||||
int maxIntruderActions; //!< Maximum number of intruder actions in the semitrace (encrypt/decrypt)
|
||||
int agentTypecheck; //!< Check type of agent variables in all matching modes
|
||||
int concrete; //!< Swap out variables at the end.
|
||||
int initUnique; //!< Default allows duplicate terms in rho (init)
|
||||
int respUnique; //!< Default allows duplicate terms in rho (resp)
|
||||
int intruder; //!< Enable intruder actions (default)
|
||||
int agentUnfold; //!< Explicitly unfold for N honest agents and 1 compromised iff > 0
|
||||
int abstractionMethod; //!< 0 means none, others are specific modes
|
||||
int useAttackBuffer; //!< Use temporary file for attack storage
|
||||
|
||||
// Misc
|
||||
int switchP; //!< A multi-purpose integer parameter, passed to the partial order reduction method selected.
|
||||
int experimental; //!< Experimental stuff goes here until it moves into main stuff.
|
||||
int removeclaims; //!< Remove any claims in the spdl file
|
||||
int addreachableclaim; //!< Adds 'reachable' claims to each role
|
||||
int addallclaims; //!< Adds all sorts of claims to the roles
|
||||
int check; //!< Check protocol correctness
|
||||
int expert; //!< Expert mode
|
||||
|
||||
// Output
|
||||
int output; //!< From enum outputs: what should be produced. Default ATTACK.
|
||||
int report;
|
||||
int reportClaims; //!< Enable claims report
|
||||
int xml; //!< xml output
|
||||
int dot; //!< dot output
|
||||
int human; //!< human readable
|
||||
int reportMemory; //!< Memory display switch.
|
||||
int reportTime; //!< Time display switch.
|
||||
int countStates; //!< Count states
|
||||
int extendNonReads; //!< Show further events in arachne xml output.
|
||||
int extendTrivial; //!< Show further events in arachne xml output, based on knowledge underapproximation. (Includes at least the events of the nonreads extension)
|
||||
int plain; //!< Disable color output on terminal
|
||||
int monochrome; //!< Disable colors in dot output
|
||||
int lightness; //!< Lightness increment 0-100
|
||||
int clusters; //!> Enable clusters in output
|
||||
};
|
||||
|
||||
extern struct switchdata switches; //!< pointer to switchdata structure
|
||||
|
||||
FILE *openFileSearch (char *filename, FILE * reopener);
|
||||
|
||||
#endif
|
371
gui/src/symbol.c
371
gui/src/symbol.c
@ -1,371 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "symbol.h"
|
||||
#include "debug.h"
|
||||
#include "error.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.
|
||||
*/
|
||||
|
||||
/* accessible for externals */
|
||||
|
||||
int globalError; //!< If >0, stdout output goes to stderr (for e.g. terms)
|
||||
char *globalStream; //!< Defaults to stdout
|
||||
|
||||
/* external declarations */
|
||||
|
||||
extern int yylineno;
|
||||
|
||||
/* global declarations */
|
||||
|
||||
//! Symbol hash table.
|
||||
Symbol symbtab[HASHSIZE];
|
||||
//! List of available (freed) symbol blocks.
|
||||
Symbol symb_list;
|
||||
//! List of all allocated symbol blocks.
|
||||
Symbol symb_alloc;
|
||||
|
||||
/* main code */
|
||||
|
||||
//! Open symbols code.
|
||||
void
|
||||
symbolsInit (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HASHSIZE; i++)
|
||||
symbtab[i] = NULL;
|
||||
symb_list = NULL;
|
||||
symb_alloc = NULL;
|
||||
globalError = 0;
|
||||
globalStream = (char *) stdout;
|
||||
}
|
||||
|
||||
//! Close symbols code.
|
||||
void
|
||||
symbolsDone (void)
|
||||
{
|
||||
Symbol s;
|
||||
|
||||
while (symb_alloc != NULL)
|
||||
{
|
||||
s = symb_alloc;
|
||||
symb_alloc = s->allocnext;
|
||||
free (s);
|
||||
}
|
||||
}
|
||||
|
||||
//! Create a memory block for a symbol.
|
||||
/**
|
||||
* Internal memory management is used.
|
||||
*@return A pointer to a memory block of size struct.
|
||||
*/
|
||||
Symbol
|
||||
get_symb (void)
|
||||
{
|
||||
Symbol t;
|
||||
if (symb_list != NULL)
|
||||
{
|
||||
t = symb_list;
|
||||
symb_list = symb_list->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (Symbol) malloc (sizeof (struct symbol));
|
||||
t->allocnext = symb_alloc;
|
||||
symb_alloc = t;
|
||||
}
|
||||
t->keylevel = INT_MAX;
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Declare a symbol to be freed.
|
||||
void
|
||||
free_symb (const Symbol s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return;
|
||||
s->next = symb_list;
|
||||
symb_list = s;
|
||||
}
|
||||
|
||||
//! Return the index in the hash table for the string.
|
||||
int
|
||||
hash (const 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;
|
||||
}
|
||||
|
||||
//! Insert a string into the hash table.
|
||||
void
|
||||
insert (const Symbol s)
|
||||
{
|
||||
int hv;
|
||||
|
||||
if (s == NULL)
|
||||
return; /* illegal insertion of empty stuff */
|
||||
|
||||
hv = hash (s->text);
|
||||
s->next = symbtab[hv];
|
||||
symbtab[hv] = s;
|
||||
}
|
||||
|
||||
//! Find a string in the hash table.
|
||||
Symbol
|
||||
lookup (const char *s)
|
||||
{
|
||||
int hv;
|
||||
Symbol t;
|
||||
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
hv = hash (s);
|
||||
t = symbtab[hv];
|
||||
|
||||
while (t != NULL)
|
||||
{
|
||||
if (strcmp (t->text, s) == 0)
|
||||
break;
|
||||
else
|
||||
t = t->next;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Print a symbol.
|
||||
void
|
||||
symbolPrint (const Symbol s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
/* TODO maybe action depending on type? */
|
||||
eprintf ("%s", s->text);
|
||||
}
|
||||
|
||||
//! Print all symbols
|
||||
void
|
||||
symbolPrintAll (void)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
eprintf ("List of all symbols\n");
|
||||
count = 0;
|
||||
for (i = 0; i < HASHSIZE; i++)
|
||||
{
|
||||
Symbol sym;
|
||||
|
||||
sym = symbtab[i];
|
||||
if (sym != NULL)
|
||||
{
|
||||
eprintf ("H%i:\t", i);
|
||||
while (sym != NULL)
|
||||
{
|
||||
count++;
|
||||
eprintf ("[%s]\t", sym->text);
|
||||
sym = sym->next;
|
||||
}
|
||||
eprintf ("\n");
|
||||
}
|
||||
}
|
||||
eprintf ("Total:\t%i\n", count);
|
||||
}
|
||||
|
||||
//! Insert a string into the symbol table, if it wasn't there yet.
|
||||
/**
|
||||
* Also sets line numbers and type.
|
||||
*\sa T_SYSCONST
|
||||
*/
|
||||
Symbol
|
||||
symbolSysConst (const char *str)
|
||||
{
|
||||
Symbol symb;
|
||||
|
||||
symb = lookup (str);
|
||||
if (symb == NULL)
|
||||
{
|
||||
symb = get_symb ();
|
||||
symb->lineno = yylineno;
|
||||
symb->type = T_SYSCONST;
|
||||
symb->text = str;
|
||||
insert (symb);
|
||||
}
|
||||
return symb;
|
||||
}
|
||||
|
||||
//! Generate the first fresh free number symbol, prefixed by a certain symbol's string.
|
||||
/**
|
||||
* Note that there is an upper limit to this, to avoid some problems with buffer overflows etc.
|
||||
*/
|
||||
Symbol
|
||||
symbolNextFree (Symbol prefixsymbol)
|
||||
{
|
||||
char *prefixstr;
|
||||
int n;
|
||||
int len;
|
||||
|
||||
if (prefixsymbol != NULL)
|
||||
{
|
||||
prefixstr = (char *) prefixsymbol->text;
|
||||
len = strlen (prefixstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefixstr = "";
|
||||
len = 0;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
while (n <= 9999)
|
||||
{
|
||||
/*
|
||||
* The construction below (variable buffer length) is not allowed in ISO C90
|
||||
*/
|
||||
char buffer[len + 5]; // thus we must enforce a maximum of 9.999 (allowing for storage of \0 )
|
||||
Symbol symb;
|
||||
int slen;
|
||||
|
||||
slen = sprintf (buffer, "%s%i", prefixstr, n);
|
||||
buffer[slen] = EOS;
|
||||
symb = lookup (buffer);
|
||||
if (symb == NULL)
|
||||
{
|
||||
char *newstring;
|
||||
// Copy the buffer to something that will survive
|
||||
/**
|
||||
* Memory leak: although this routine should not be called recursively, it will never de-allocate this memory.
|
||||
* Thus, some precaution is necessary.
|
||||
* [x][CC]
|
||||
*/
|
||||
newstring = (char *) malloc (slen + 1);
|
||||
memcpy (newstring, buffer, slen + 1);
|
||||
|
||||
/* This persistent string can be used to return a fresh symbol */
|
||||
|
||||
return symbolSysConst (newstring);
|
||||
}
|
||||
|
||||
// Try next one
|
||||
n++;
|
||||
}
|
||||
error ("We ran out of numbers (%i) when trying to generate a fresh symbol.",
|
||||
n);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! Fix all the unset keylevels
|
||||
void
|
||||
symbol_fix_keylevels (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HASHSIZE; i++)
|
||||
{
|
||||
Symbol sym;
|
||||
|
||||
sym = symbtab[i];
|
||||
while (sym != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
eprintf ("Symbol ");
|
||||
symbolPrint (sym);
|
||||
}
|
||||
#endif
|
||||
if (sym->keylevel == INT_MAX)
|
||||
{
|
||||
// Nothing currently, this simply does not originate on a strand.
|
||||
#ifdef DEBUG
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
eprintf (" doesn't have a keylevel yet.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
if (DEBUGL (5))
|
||||
{
|
||||
eprintf (" has keylevel %i\n", sym->keylevel);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sym = sym->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Get output stream pointer
|
||||
FILE *
|
||||
getOutputStream (void)
|
||||
{
|
||||
if (globalError == 0)
|
||||
return (FILE *) globalStream;
|
||||
else
|
||||
#ifdef USESTDERR
|
||||
return stderr;
|
||||
#else
|
||||
// we simply omit it
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Print out according to globalError
|
||||
/**
|
||||
* Input is comparable to printf, only depends on globalError. This should be
|
||||
* used by any function trying to do output.
|
||||
*
|
||||
* Furthermore, if globalError == 0, it can still be overriden by
|
||||
* globalStream, which can be another stream pointer. If it is null, stdout
|
||||
* is assumed.
|
||||
*
|
||||
*\sa globalError
|
||||
*/
|
||||
void
|
||||
eprintf (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
FILE *stream;
|
||||
|
||||
va_start (args, fmt);
|
||||
stream = getOutputStream ();
|
||||
if (stream != NULL)
|
||||
{
|
||||
vfprintf (stream, fmt, args);
|
||||
}
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
// Variable list variant
|
||||
void
|
||||
veprintf (const char *fmt, va_list args)
|
||||
{
|
||||
FILE *stream;
|
||||
|
||||
stream = getOutputStream ();
|
||||
if (stream != NULL)
|
||||
{
|
||||
vfprintf (stream, fmt, args);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
#ifndef SYMBOLS
|
||||
#define SYMBOLS
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
//! Size of symbol hashtable.
|
||||
/** Optimistically large. Should be a prime, says theory.
|
||||
*/
|
||||
#define HASHSIZE 997
|
||||
|
||||
enum symboltypes
|
||||
{ T_UNDEF = -1, T_PROTOCOL, T_CONST, T_VAR, T_SYSCONST };
|
||||
|
||||
#define EOS 0
|
||||
|
||||
//! Symbol structure
|
||||
struct symbol
|
||||
{
|
||||
//! Type of symbol.
|
||||
/**
|
||||
*\sa T_UNDEF, T_PROTOCOL, T_CONST, T_VAR, T_SYSCONST
|
||||
*/
|
||||
int type;
|
||||
//! Line number at which it occurred.
|
||||
int lineno;
|
||||
//! Level of occurrence in role nodes. 0 for as non-key, 1 for key only, 2 for key of key only, etc..
|
||||
int keylevel;
|
||||
//! Ascii string with name of the symbol.
|
||||
const char *text;
|
||||
//! Possible next pointer.
|
||||
struct symbol *next;
|
||||
//! Used for linking all symbol blocks, freed or in use.
|
||||
struct symbol *allocnext;
|
||||
};
|
||||
|
||||
typedef struct symbol *Symbol; //!< pointer to symbol structure
|
||||
|
||||
void symbolsInit (void);
|
||||
void symbolsDone (void);
|
||||
|
||||
Symbol get_symb (void);
|
||||
void free_symb (const Symbol s);
|
||||
|
||||
void insert (const Symbol s);
|
||||
Symbol lookup (const char *s);
|
||||
void symbolPrint (const Symbol s);
|
||||
void symbolPrintAll (void);
|
||||
Symbol symbolSysConst (const char *str);
|
||||
void symbol_fix_keylevels (void);
|
||||
Symbol symbolNextFree (Symbol prefixsymbol);
|
||||
|
||||
void eprintf (char *fmt, ...);
|
||||
void veprintf (const char *fmt, va_list args);
|
||||
|
||||
extern int globalError;
|
||||
extern char *globalStream;
|
||||
|
||||
#endif
|
1454
gui/src/system.c
1454
gui/src/system.c
File diff suppressed because it is too large
Load Diff
208
gui/src/system.h
208
gui/src/system.h
@ -1,208 +0,0 @@
|
||||
#ifndef SYSTEM
|
||||
#define SYSTEM
|
||||
|
||||
#include "term.h"
|
||||
#include "termmap.h"
|
||||
#include "termlist.h"
|
||||
#include "knowledge.h"
|
||||
#include "states.h"
|
||||
#include "role.h"
|
||||
#include "list.h"
|
||||
|
||||
#define runPointerGet(sys,run) sys->runs[run].index
|
||||
#define runPointerSet(sys,run,newp) sys->runs[run].index = newp
|
||||
|
||||
enum outputs
|
||||
{ EMPTY, ATTACK, STATESPACE, SUMMARY, PROOF };
|
||||
|
||||
//! Protocol definition.
|
||||
struct protocol
|
||||
{
|
||||
//! Name of the protocol encoded in a term.
|
||||
Term nameterm;
|
||||
//! List of role definitions.
|
||||
Role roles;
|
||||
//! List of role names.
|
||||
Termlist rolenames;
|
||||
//! List of local terms for this protocol.
|
||||
Termlist locals;
|
||||
//! Pointer to next protocol.
|
||||
struct protocol *next;
|
||||
int lineno; //!< Line number of definition (for errors)?
|
||||
};
|
||||
|
||||
//! Shorthand for protocol pointer.
|
||||
typedef struct protocol *Protocol;
|
||||
|
||||
//! Run container.
|
||||
struct run
|
||||
{
|
||||
Protocol protocol; //!< Protocol of this run.
|
||||
Role role; //!< Role of this run.
|
||||
int step; //!< Current execution point in the run (integer)
|
||||
int rolelength; //!< Length of role
|
||||
|
||||
Roledef index; //!< Current execution point in the run (roledef pointer)
|
||||
Roledef start; //!< Head of the run definition.
|
||||
Knowledge know; //!< Current knowledge of the run.
|
||||
|
||||
Termlist rho; //!< As in semantics (copies in artefacts)
|
||||
Termlist sigma; //!< As in semantics (copies in artefacts)
|
||||
Termlist constants; //!< As in semantics (copies in artefacts)
|
||||
|
||||
Termlist locals; //!< Locals of the run (will be deprecated eventually)
|
||||
Termlist artefacts; //!< Stuff created especially for this run, which can also include tuples (anything allocated)
|
||||
Termlist substitutions; //!< The substitutions as they came from the roledef unifier
|
||||
|
||||
int prevSymmRun; //!< Used for symmetry reduction. Either -1, or the previous run with the same role def and at least a single parameter.
|
||||
int firstNonAgentRead; //!< Used for symmetry reductions for equal agents runs; -1 if there is no candidate.
|
||||
int firstReal; //!< 1 if a choose was inserted, otherwise 0
|
||||
};
|
||||
|
||||
//! Shorthand for run pointer.
|
||||
typedef struct run *Run;
|
||||
|
||||
//! Structure for information on special terms (cacheing)
|
||||
struct hiddenterm
|
||||
{
|
||||
Term term;
|
||||
unsigned int hideminimum;
|
||||
unsigned int hideprotocol;
|
||||
unsigned int hideknowledge;
|
||||
struct hiddenterm *next;
|
||||
};
|
||||
|
||||
//! Pointer shorthand
|
||||
typedef struct hiddenterm *Hiddenterm;
|
||||
|
||||
//! The main state structure.
|
||||
struct system
|
||||
{
|
||||
int step; //!< Step in trace during exploration. Can be managed globally
|
||||
Knowledge know; //!< Knowledge in currect step of system.
|
||||
struct parameters *parameters; // misc
|
||||
/* static run info, maxruns */
|
||||
Run runs;
|
||||
|
||||
/* global */
|
||||
int maxruns; //!< Number of runs in the system.
|
||||
|
||||
/* properties */
|
||||
Termlist secrets; //!< Integrate secrets list into system.
|
||||
Termlist synchronising_labels; //!< List of labels that might synchronise.
|
||||
int shortestattack; //!< Length of shortest attack trace.
|
||||
int maxtracelength; //!< helps to remember the length of the last trace.
|
||||
|
||||
/* traversal */
|
||||
int traverse; //!< Traversal method.
|
||||
int explore; //!< Boolean: explore states after actions or not.
|
||||
|
||||
/* counters */
|
||||
states_t states; //!< States traversed
|
||||
states_t interval; //!< Used to update state printing at certain intervals
|
||||
states_t claims; //!< Number of claims encountered.
|
||||
states_t failed; //!< Number of claims failed.
|
||||
int attackid; //!< Global counter of attacks (used for assigning identifiers) within this Scyther call.
|
||||
int num_regular_runs; //!< Number of regular runs
|
||||
int num_intruder_runs; //!< Number of intruder runs
|
||||
|
||||
/* protocol definition */
|
||||
Protocol protocols; //!< List of protocols in the system
|
||||
Termlist locals; //!< List of local terms
|
||||
Termlist variables; //!< List of all variables
|
||||
Termlist agentnames; //!< List of all agent names (trusted and untrusted)
|
||||
Termlist untrusted; //!< List of untrusted agent names
|
||||
Termlist globalconstants; //!< List of global constants
|
||||
Hiddenterm hidden; //!< List of hiddenterm constructs for Hidelevel lemma
|
||||
|
||||
/* protocol preprocessing */
|
||||
int rolecount; //!< Number of roles in the system
|
||||
int roleeventmax; //!< Maximum number of events in a single role
|
||||
int lastChooseRun; //!< Last run with a choose event
|
||||
Claimlist claimlist; //!< List of claims in the system, with occurrence counts
|
||||
List labellist; //!< List of labelinfo stuff
|
||||
int knowledgedefined; //!< True if knowledge is defined for some role (which triggers well-formedness check etc.)
|
||||
|
||||
/* constructed trace pointers, static */
|
||||
Roledef *traceEvent; //!< Trace roledefs: MaxRuns * maxRoledef
|
||||
int *traceRun; //!< Trace run ids: MaxRuns * maxRoledef
|
||||
Knowledge *traceKnow; //!< Trace intruder knowledge: Maxruns * maxRoledef
|
||||
states_t *traceNode; //!< Trace node traversal: Maxruns * maxRoledef
|
||||
|
||||
/* Arachne assistance */
|
||||
List bindings; //!< List of bindings
|
||||
Claimlist current_claim; //!< The claim under current investigation
|
||||
Termlist trustedRoles; //!< Roles that should be trusted for this claim (the default, NULL, means all)
|
||||
};
|
||||
|
||||
typedef struct system *System;
|
||||
|
||||
|
||||
System systemInit ();
|
||||
void systemReset (const System sys);
|
||||
void systemRuns (const System sys);
|
||||
System systemDuplicate (const System fromsys);
|
||||
void statesPrint (const System sys);
|
||||
void statesPrintShort (const System sys);
|
||||
void systemDestroy (const System sys);
|
||||
void systemDone (const System sys);
|
||||
void ensureValidRun (const System sys, int run);
|
||||
void runPrint (Roledef rd);
|
||||
void runsPrint (const System sys);
|
||||
Term agentOfRunRole (const System sys, const int run, const Term role);
|
||||
Term agentOfRun (const System sys, const int run);
|
||||
void roleInstance (const System sys, const Protocol protocol, const Role role,
|
||||
const Termlist paramlist, Termlist substlist);
|
||||
void roleInstanceDestroy (const System sys);
|
||||
void systemStart (const System sys);
|
||||
void indentActivate ();
|
||||
void indentSet (int i);
|
||||
void indent ();
|
||||
|
||||
Protocol protocolCreate (Term nameterm);
|
||||
void locVarPrint (Termlist tl);
|
||||
void protocolPrint (Protocol p);
|
||||
void protocolsPrint (Protocol p);
|
||||
int untrustedAgent (const System sys, Termlist agents);
|
||||
int getMaxTraceLength (const System sys);
|
||||
void agentsOfRunPrint (const System sys, const int run);
|
||||
void violatedClaimPrint (const System sys, int i);
|
||||
void commandlinePrint (FILE * stream);
|
||||
|
||||
int compute_rolecount (const System sys);
|
||||
int compute_roleeventmax (const System sys);
|
||||
|
||||
void scenarioPrint (const System sys);
|
||||
int isAgentTrusted (const System sys, Term agent);
|
||||
int isAgentlistTrusted (const System sys, Termlist agents);
|
||||
int isRunTrusted (const System sys, const int run);
|
||||
|
||||
int iterateRuns (const System sys, int (*callback) (int r));
|
||||
int iterateRegularRuns (const System sys, int (*callback) (int r));
|
||||
int iterateEvents (const System sys, const int run,
|
||||
int (*callback) (Roledef rd, int ev));
|
||||
int iterateAllEvents (const System sys,
|
||||
int (*callback) (int run, Roledef rd, int ev));
|
||||
int iterateEventsType (const System sys, const int run, const int evtype,
|
||||
int (*callback) (Roledef rd, int ev));
|
||||
int iterateLocalToOther (const System sys, const int myrun,
|
||||
int (*callback) (Term t));
|
||||
int iterateRoles (const System sys, int (*callback) (Protocol p, Role r));
|
||||
int firstOccurrence (const System sys, const int r, Term t, int evtype);
|
||||
Roledef eventRoledef (const System sys, const int run, const int ev);
|
||||
int countInitiators (const System sys);
|
||||
int selfResponder (const System sys, const int run);
|
||||
int selfResponders (const System sys);
|
||||
int selfInitiator (const System sys, const int run);
|
||||
int selfInitiators (const System sys);
|
||||
int enoughAttacks (const System sys);
|
||||
|
||||
|
||||
//! Equality for run structure naming
|
||||
/**
|
||||
* For the modelchecker, there was an index called step. In Strand Space
|
||||
* terminology, something like that is the height of the strand.
|
||||
*/
|
||||
#define height step
|
||||
|
||||
#endif
|
337
gui/src/tac.c
337
gui/src/tac.c
@ -1,337 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "tac.h"
|
||||
#include "memory.h"
|
||||
#include "switches.h"
|
||||
#include "error.h"
|
||||
|
||||
extern int yylineno;
|
||||
|
||||
static Tac allocatedTacs;
|
||||
|
||||
//! Init segment
|
||||
void
|
||||
tacInit (void)
|
||||
{
|
||||
allocatedTacs = NULL;
|
||||
}
|
||||
|
||||
//! Closing segment
|
||||
void
|
||||
tacDone (void)
|
||||
{
|
||||
Tac ts;
|
||||
|
||||
ts = allocatedTacs;
|
||||
while (ts != NULL)
|
||||
{
|
||||
Tac tf;
|
||||
|
||||
tf = ts;
|
||||
ts = ts->allnext;
|
||||
free (tf);
|
||||
}
|
||||
}
|
||||
|
||||
//! Create a tac node of some type
|
||||
Tac
|
||||
tacCreate (int op)
|
||||
{
|
||||
/* maybe even store in scrapping list, so we could delete them
|
||||
* all later */
|
||||
Tac t = malloc (sizeof (struct tacnode));
|
||||
t->allnext = allocatedTacs;
|
||||
allocatedTacs = t;
|
||||
t->lineno = yylineno;
|
||||
t->op = op;
|
||||
t->next = NULL;
|
||||
t->prev = NULL;
|
||||
t->t1.tac = NULL;
|
||||
t->t2.tac = NULL;
|
||||
t->t3.tac = NULL;
|
||||
return t;
|
||||
}
|
||||
|
||||
Tac
|
||||
tacString (char *s)
|
||||
{
|
||||
Tac t;
|
||||
t = tacCreate (TAC_STRING);
|
||||
t->t1.str = s;
|
||||
return t;
|
||||
}
|
||||
|
||||
Tac
|
||||
tacJoin (int op, Tac t1, Tac t2, Tac t3)
|
||||
{
|
||||
Tac t;
|
||||
t = tacCreate (op);
|
||||
t->t1.tac = t1;
|
||||
t->t2.tac = t2;
|
||||
t->t3.tac = 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;
|
||||
}
|
||||
}
|
||||
|
||||
//! List to right-associative tuple
|
||||
Tac
|
||||
tacTupleRa (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->t1.tac = taclist;
|
||||
tc->t2.tac = tacTuple (taclist->next);
|
||||
|
||||
/* unlink list */
|
||||
tc->t1.tac->next = NULL;
|
||||
tc->t2.tac->prev = NULL;
|
||||
}
|
||||
return tc;
|
||||
}
|
||||
|
||||
//! List to left-associative tuple
|
||||
Tac
|
||||
tacTupleLa (Tac taclist)
|
||||
{
|
||||
Tac tc;
|
||||
|
||||
/* initial node is simple the first item */
|
||||
tc = taclist;
|
||||
tc->prev = NULL;
|
||||
|
||||
/* add any other nodes (one is ensured) */
|
||||
do
|
||||
{
|
||||
Tac tcnew;
|
||||
|
||||
taclist = taclist->next;
|
||||
/* add a new node (taclist) to the existing thing by first making the old one into the left-hand side of a tuple */
|
||||
tcnew = tacCreate (TAC_TUPLE);
|
||||
tcnew->t1.tac = tc;
|
||||
tcnew->t2.tac = taclist;
|
||||
tc = tcnew;
|
||||
/* unlink */
|
||||
tc->t1.tac->next = NULL;
|
||||
tc->t2.tac->prev = NULL;
|
||||
}
|
||||
while (taclist->next != NULL);
|
||||
|
||||
return tc;
|
||||
}
|
||||
|
||||
//! Compile a list into a tuple
|
||||
/* 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)
|
||||
{
|
||||
if (taclist == NULL || taclist->next == NULL)
|
||||
{
|
||||
/* just return */
|
||||
return taclist;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (switches.tupling)
|
||||
{
|
||||
case 0:
|
||||
/* case 0: as well as */
|
||||
/* DEFAULT behaviour */
|
||||
/* right-associative */
|
||||
return tacTupleRa (taclist);
|
||||
case 1:
|
||||
/* switch --la-tupling */
|
||||
/* left-associative */
|
||||
return tacTupleLa (taclist);
|
||||
default:
|
||||
error ("Unknown tupling mode (--tupling=%i)", switches.tupling);
|
||||
}
|
||||
}
|
||||
// @TODO this should be considered an error
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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->t1.sym->text);
|
||||
tacPrint (t->t3.tac);
|
||||
printf (")\n{\n");
|
||||
tacPrint (t->t2.tac);
|
||||
printf ("};\n");
|
||||
break;
|
||||
case TAC_ROLE:
|
||||
printf ("role %s\n{\n", t->t1.sym->text);
|
||||
tacPrint (t->t2.tac);
|
||||
printf ("};\n");
|
||||
break;
|
||||
case TAC_READ:
|
||||
printf ("read");
|
||||
if (t->t1.sym != NULL)
|
||||
{
|
||||
printf ("_%s", t->t1.sym->text);
|
||||
}
|
||||
printf ("(");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (");\n");
|
||||
break;
|
||||
case TAC_SEND:
|
||||
printf ("send");
|
||||
if (t->t1.sym != NULL)
|
||||
{
|
||||
printf ("_%s", t->t1.sym->text);
|
||||
}
|
||||
printf ("(");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (");\n");
|
||||
break;
|
||||
case TAC_CLAIM:
|
||||
printf ("claim");
|
||||
if (t->t1.sym != NULL)
|
||||
{
|
||||
printf ("_%s", t->t1.sym->text);
|
||||
}
|
||||
printf ("(");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (");\n");
|
||||
break;
|
||||
case TAC_CONST:
|
||||
printf ("const ");
|
||||
tacPrint (t->t1.tac);
|
||||
if (t->t2.tac != NULL)
|
||||
{
|
||||
printf (" : ");
|
||||
tacPrint (t->t2.tac);
|
||||
}
|
||||
printf (";\n");
|
||||
break;
|
||||
case TAC_VAR:
|
||||
printf ("var ");
|
||||
tacPrint (t->t1.tac);
|
||||
if (t->t2.tac != NULL)
|
||||
{
|
||||
printf (" : ");
|
||||
tacPrint (t->t2.tac);
|
||||
}
|
||||
printf (";\n");
|
||||
break;
|
||||
case TAC_UNDEF:
|
||||
printf ("undefined");
|
||||
if (t->next != NULL)
|
||||
printf (",");
|
||||
break;
|
||||
case TAC_STRING:
|
||||
printf ("%s", t->t1.sym->text);
|
||||
if (t->next != NULL)
|
||||
printf (",");
|
||||
break;
|
||||
case TAC_TUPLE:
|
||||
printf ("(");
|
||||
tacPrint (t->t1.tac);
|
||||
printf (",");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (")");
|
||||
break;
|
||||
case TAC_ENCRYPT:
|
||||
printf ("{");
|
||||
tacPrint (t->t1.tac);
|
||||
printf ("}");
|
||||
tacPrint (t->t2.tac);
|
||||
if (t->next != NULL)
|
||||
{
|
||||
printf (",");
|
||||
t = t->next;
|
||||
tacPrint (t);
|
||||
}
|
||||
break;
|
||||
case TAC_RUN:
|
||||
printf ("run ");
|
||||
tacPrint (t->t1.tac);
|
||||
printf ("(");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (");\n");
|
||||
break;
|
||||
case TAC_ROLEREF:
|
||||
symbolPrint (t->t1.sym);
|
||||
printf (".");
|
||||
symbolPrint (t->t2.sym);
|
||||
break;
|
||||
case TAC_COMPROMISED:
|
||||
printf ("compromised ");
|
||||
tacPrint (t->t1.tac);
|
||||
printf (";\n");
|
||||
break;
|
||||
case TAC_SECRET:
|
||||
printf ("secret ");
|
||||
tacPrint (t->t1.tac);
|
||||
printf (";\n");
|
||||
break;
|
||||
case TAC_INVERSEKEYS:
|
||||
printf ("inversekeys (");
|
||||
tacPrint (t->t1.tac);
|
||||
printf (",");
|
||||
tacPrint (t->t2.tac);
|
||||
printf (");\n");
|
||||
break;
|
||||
case TAC_UNTRUSTED:
|
||||
printf ("untrusted ");
|
||||
tacPrint (t->t1.tac);
|
||||
printf (";\n");
|
||||
break;
|
||||
default:
|
||||
printf ("[??]");
|
||||
}
|
||||
|
||||
/* and any other stuff */
|
||||
if (t->next != NULL)
|
||||
{
|
||||
tacPrint (t->next);
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
#ifndef TAC_H
|
||||
#define TAC_H
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
/*
|
||||
* TAC instructions
|
||||
*/
|
||||
|
||||
enum tactypes
|
||||
{
|
||||
TAC_UNDEF,
|
||||
TAC_SYM,
|
||||
TAC_TUPLE,
|
||||
TAC_ENCRYPT,
|
||||
TAC_VAR,
|
||||
TAC_CONST,
|
||||
TAC_READ,
|
||||
TAC_SEND,
|
||||
TAC_CLAIM,
|
||||
TAC_FUNC,
|
||||
TAC_STRING,
|
||||
TAC_ROLE,
|
||||
TAC_PROTOCOL,
|
||||
TAC_KNOWS,
|
||||
TAC_RUN,
|
||||
TAC_ROLEREF,
|
||||
TAC_SECRET,
|
||||
TAC_INVERSEKEYS,
|
||||
TAC_UNTRUSTED,
|
||||
TAC_COMPROMISED,
|
||||
TAC_USERTYPE
|
||||
};
|
||||
|
||||
//! Structure to hold the compilation tree nodes
|
||||
struct tacnode
|
||||
{
|
||||
struct tacnode *next; //!< pointer to previous node
|
||||
struct tacnode *prev; //!< pointer to next node
|
||||
struct tacnode *allnext;
|
||||
int op; //!< operator for this node
|
||||
int lineno; //!< line number of parser location in the input file
|
||||
union
|
||||
{
|
||||
Symbol sym;
|
||||
struct tacnode *tac;
|
||||
char *str;
|
||||
int value;
|
||||
} t1;
|
||||
union
|
||||
{
|
||||
Symbol sym;
|
||||
struct tacnode *tac;
|
||||
char *str;
|
||||
int value;
|
||||
} t2;
|
||||
union
|
||||
{
|
||||
Symbol sym;
|
||||
struct tacnode *tac;
|
||||
char *str;
|
||||
int value;
|
||||
} t3;
|
||||
};
|
||||
|
||||
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
|
1483
gui/src/term.c
1483
gui/src/term.c
File diff suppressed because it is too large
Load Diff
196
gui/src/term.h
196
gui/src/term.h
@ -1,196 +0,0 @@
|
||||
#ifndef TERMS
|
||||
#define TERMS
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
// type <= LEAF means it's a leaf, nkay?
|
||||
enum termtypes
|
||||
{ GLOBAL, VARIABLE, LEAF, ENCRYPT, TUPLE };
|
||||
|
||||
//! The most basic datatype in the modelchecker.
|
||||
/**
|
||||
* Describes a single term.
|
||||
*/
|
||||
|
||||
struct term
|
||||
{
|
||||
/* basic : name,runid
|
||||
encrypt: op,key
|
||||
tuple : op,next
|
||||
*/
|
||||
|
||||
//! The type of term.
|
||||
/**
|
||||
* \sa GLOBAL, VARIABLE, LEAF, ENCRYPT, TUPLE
|
||||
*/
|
||||
int type;
|
||||
//! Data Type termlist (e.g. agent or nonce)
|
||||
/** Only for leaves. */
|
||||
void *stype; // list of types
|
||||
int roleVar; //!< only for leaf, arachne engine: role variable flag
|
||||
|
||||
//! Substitution term.
|
||||
/**
|
||||
* If this is non-NULL, this leaf term is apparently substituted by
|
||||
* this term.
|
||||
*/
|
||||
struct term *subst; // only for variable/leaf, substitution term
|
||||
|
||||
union
|
||||
{
|
||||
//! Pointer to the symbol for leaves
|
||||
Symbol symb;
|
||||
//! Encrypted subterm.
|
||||
struct term *op;
|
||||
//! Left-hand side of tuple pair.
|
||||
struct term *op1;
|
||||
struct term *next; //!< for alternative memory management
|
||||
} left;
|
||||
union
|
||||
{
|
||||
//! run identifier for leaves
|
||||
int runid;
|
||||
//! Key used to encrypt subterm.
|
||||
struct term *key;
|
||||
//! Right-hand side of tuple pair.
|
||||
struct term *op2;
|
||||
} right;
|
||||
};
|
||||
|
||||
//! Component macros (left)
|
||||
#define TermSymb(t) (t->left.symb)
|
||||
#define TermOp1(t) (t->left.op1)
|
||||
#define TermOp(t) (t->left.op)
|
||||
|
||||
//! Component macros (right)
|
||||
#define TermRunid(t) (t->right.runid)
|
||||
#define TermOp2(t) (t->right.op2)
|
||||
#define TermKey(t) (t->right.key)
|
||||
|
||||
//! Flag for term status
|
||||
extern int rolelocal_variable;
|
||||
|
||||
//! Pointer shorthand.
|
||||
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);
|
||||
__inline__ Term deVarScan (Term 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 || (t->type <= LEAF && rolelocal_variable && TermRunid(t) == -3)))
|
||||
#define substVar(t) ((realTermVariable (t) && t->subst != NULL) ? 1 : 0)
|
||||
#define deVar(t) ( substVar(t) ? deVarScan(t->subst) : t)
|
||||
#define isTermLeaf(t) realTermLeaf(deVar(t))
|
||||
#define isTermTuple(t) realTermTuple(deVar(t))
|
||||
#define isTermEncrypt(t) realTermEncrypt(deVar(t))
|
||||
#define isTermVariable(t) realTermVariable(deVar(t))
|
||||
#ifdef DEBUG
|
||||
#define isTermEqual(t1,t2) isTermEqualDebug(t1,t2)
|
||||
int isTermEqualDebug (Term t1, Term t2);
|
||||
#else
|
||||
#define isTermEqual1(t1,t2) ((substVar(t1) || substVar(t2)) \
|
||||
? isTermEqualFn(t1,t2) \
|
||||
: ( \
|
||||
(t1 == t2) \
|
||||
? 1 \
|
||||
: ( \
|
||||
(t1 == NULL || t2 == NULL || t1->type != t2->type) \
|
||||
? 0 \
|
||||
: ( \
|
||||
realTermLeaf(t1) \
|
||||
? isTermEqualFn(t1,t2) \
|
||||
: ( \
|
||||
realTermEncrypt(t2) \
|
||||
? (isTermEqualFn(TermKey(t1), TermKey(t2)) && \
|
||||
isTermEqualFn(TermOp(t1), TermOp(t2))) \
|
||||
: (isTermEqualFn(TermOp1(t1), TermOp1(t2)) && \
|
||||
isTermEqualFn(TermOp2(t1), TermOp2(t2))) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define isTermEqual2(t1,t2) ((substVar(t1) || substVar(t2)) \
|
||||
? isTermEqualFn(t1,t2) \
|
||||
: ( \
|
||||
(t1 == t2) \
|
||||
? 1 \
|
||||
: ( \
|
||||
(t1 == NULL || t2 == NULL || t1->type != t2->type) \
|
||||
? 0 \
|
||||
: ( \
|
||||
realTermLeaf(t1) \
|
||||
? isTermEqualFn(t1,t2) \
|
||||
: ( \
|
||||
realTermEncrypt(t2) \
|
||||
? (isTermEqual1(TermKey(t1), TermKey(t2)) && \
|
||||
isTermEqual1(TermOp(t1), TermOp(t2))) \
|
||||
: (isTermEqual1(TermOp1(t1), TermOp1(t2)) && \
|
||||
isTermEqual1(TermOp2(t1), TermOp2(t2))) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define isTermEqual(t1,t2) isTermEqual2(t1,t2)
|
||||
#endif
|
||||
|
||||
int hasTermVariable (Term term);
|
||||
int isTermEqualFn (Term term1, Term term2);
|
||||
int termSubTerm (Term t, Term tsub);
|
||||
int termInTerm (Term t, Term tsub);
|
||||
void termPrintCustom (Term term, char *leftvar, char *rightvar, char *lefttup,
|
||||
char *righttup, char *leftenc, char *rightenc,
|
||||
void (*callback) (const Term t));
|
||||
void termPrint (Term term);
|
||||
void termTuplePrintCustom (Term term, char *leftvar, char *rightvar,
|
||||
char *lefttup, char *righttup, char *leftenc,
|
||||
char *rightenc, void (*callback) (const Term t));
|
||||
void termTuplePrint (Term term);
|
||||
Term termDuplicate (const Term term);
|
||||
Term termNodeDuplicate (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);
|
||||
int termOrder (Term t1, Term t2);
|
||||
int term_iterate (const Term term, int (*leaf) (Term t),
|
||||
int (*nodel) (Term t), int (*nodem) (Term t),
|
||||
int (*noder) (Term t));
|
||||
int term_iterate_deVar (Term term, int (*leaf) (Term t),
|
||||
int (*nodel) (Term t), int (*nodem) (Term t),
|
||||
int (*noder) (Term t));
|
||||
int term_iterate_leaves (const Term t, int (*func) (Term t));
|
||||
int term_iterate_open_leaves (const Term term, int (*func) (Term t));
|
||||
void term_rolelocals_are_variables ();
|
||||
int term_encryption_level (const Term term);
|
||||
float term_constrain_level (const Term term);
|
||||
void term_set_keylevels (const Term term);
|
||||
void termPrintDiff (Term t1, Term t2);
|
||||
int isLeafNameEqual (Term t1, Term t2);
|
||||
Term freshTermPrefix (Term prefixterm);
|
||||
int isTermFunctionName (Term t);
|
||||
Term getTermFunction (Term t);
|
||||
unsigned int termHidelevel (const Term tsmall, Term tbig);
|
||||
void termSubstPrint (Term t);
|
||||
|
||||
int iterateTermOther (const int myrun, Term t, int (*callback) (Term t));
|
||||
|
||||
extern char *RUNSEP; // by default, set to "#"
|
||||
|
||||
#endif
|
@ -1,972 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "termlist.h"
|
||||
#include "specialterm.h"
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* Shared stuff
|
||||
*/
|
||||
|
||||
//! Termlist error thing (for global use)
|
||||
Termlist TERMLISTERROR;
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
Termlist makeTermlist ();
|
||||
|
||||
//! Open termlists code.
|
||||
void
|
||||
termlistsInit (void)
|
||||
{
|
||||
TERMLISTERROR = makeTermlist ();
|
||||
TERMLISTERROR->term = NULL;
|
||||
TERMLISTERROR->prev = NULL;
|
||||
TERMLISTERROR->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
//! Close termlists code.
|
||||
void
|
||||
termlistsDone (void)
|
||||
{
|
||||
termlistDelete (TERMLISTERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
//! Allocate memory for a termlist node.
|
||||
/**
|
||||
*@return A pointer to uninitialised memory of the size of a termlist node.
|
||||
*/
|
||||
Termlist
|
||||
makeTermlist ()
|
||||
{
|
||||
/* inline candidate */
|
||||
return (Termlist) malloc (sizeof (struct termlist));
|
||||
}
|
||||
|
||||
//! Duplicate a termlist.
|
||||
/**
|
||||
* Uses termDuplicate to copy the elements, and allocated new memory for the list nodes.
|
||||
*\sa termDuplicate(), termlistShallow()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Shallow reverse copy of a termlist.
|
||||
/**
|
||||
* Just copies the element pointers. Allocates new memory for the list nodes.
|
||||
* Note that it reverses the order of the list.
|
||||
*\sa termlistDuplicate()
|
||||
*/
|
||||
Termlist
|
||||
termlistShallow (Termlist tl)
|
||||
{
|
||||
Termlist newtl;
|
||||
|
||||
newtl = NULL;
|
||||
while (tl != NULL)
|
||||
{
|
||||
newtl = termlistAdd (newtl, tl->term);
|
||||
tl = tl->next;
|
||||
}
|
||||
return newtl;
|
||||
}
|
||||
|
||||
//! Shallow deletion of a termlist.
|
||||
/**
|
||||
* Deletes the termlist nodes only. Elements are intact after exit.
|
||||
*\sa termlistShallow()
|
||||
*/
|
||||
void
|
||||
termlistDelete (Termlist tl)
|
||||
{
|
||||
if (tl == NULL)
|
||||
return;
|
||||
#ifdef DEBUG
|
||||
if (tl == TERMLISTERROR)
|
||||
{
|
||||
static int count = 0;
|
||||
|
||||
count++;
|
||||
if (count > 1)
|
||||
{
|
||||
// TERMLISTERROR should only be destroyed once (by the done function)
|
||||
error ("Trying to delete TERMLISTERROR a second time, whazzup?");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
termlistDelete (tl->next);
|
||||
free (tl);
|
||||
}
|
||||
|
||||
|
||||
//! Deep deletion of a termlist.
|
||||
/**
|
||||
* Deletes the termlist nodes as well as the elements.
|
||||
*\sa termlistDuplicate(), termDuplicate(), termDelete()
|
||||
*/
|
||||
void
|
||||
termlistDestroy (Termlist tl)
|
||||
{
|
||||
if (tl == NULL)
|
||||
return;
|
||||
termlistDestroy (tl->next);
|
||||
termDelete (tl->term);
|
||||
free (tl);
|
||||
}
|
||||
|
||||
//! Determine whether a term is an element of a termlist.
|
||||
/**
|
||||
* The NULL term is not an element of any list. (Not even of the NULL list)
|
||||
*
|
||||
*@return True iff the term is an element of the termlist.
|
||||
*/
|
||||
__inline__ int
|
||||
inTermlist (Termlist tl, const Term term)
|
||||
{
|
||||
if (term == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (isTermEqual (tl->term, term))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
tl = tl->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Determine whether a term is an element of a termlist: yield pointer
|
||||
__inline__ Termlist
|
||||
termlistFind (Termlist tl, const Term term)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (term == NULL)
|
||||
{
|
||||
error ("Trying to do inTermlist for a NULL term.");
|
||||
}
|
||||
#endif
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (isTermEqual (tl->term, term))
|
||||
{
|
||||
return tl;
|
||||
}
|
||||
tl = tl->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//! Equality of two term lists.
|
||||
/**
|
||||
* Are all elements of list 1 in list 2, and vice versa?
|
||||
* Note that we assume unique elements!
|
||||
*@return True iff every element of the list is in the other list.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//! Adds a term to the front of a termlist.
|
||||
/**
|
||||
* Duplicates are allowed.
|
||||
*@return A new list pointer.
|
||||
*\sa termlistAppend()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Adds a term to the end of a termlist.
|
||||
/**
|
||||
* Duplicates are allowed.
|
||||
*@return A new list pointer if the termlist was NULL.
|
||||
*\sa termlistAdd()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Add a term only to a list if it wasn't in it before.
|
||||
/**
|
||||
* Mimics a basic set type behaviour.
|
||||
*/
|
||||
Termlist
|
||||
termlistAddNew (const Termlist tl, const Term t)
|
||||
{
|
||||
if (t == NULL || inTermlist (tl, t))
|
||||
return tl;
|
||||
else
|
||||
return termlistAdd (tl, t);
|
||||
}
|
||||
|
||||
//! Concatenates two termlists.
|
||||
/**
|
||||
* The last pointer of the first list is made to point to the second list.
|
||||
*@return The pointer to the concatenated list.
|
||||
*/
|
||||
Termlist
|
||||
termlistConcat (Termlist tl1, Termlist tl2)
|
||||
{
|
||||
Termlist scan;
|
||||
|
||||
if (tl1 == NULL)
|
||||
return tl2;
|
||||
if (tl2 == NULL)
|
||||
return tl1;
|
||||
|
||||
scan = tl1;
|
||||
while (scan->next != NULL)
|
||||
scan = scan->next;
|
||||
scan->next = tl2;
|
||||
return tl1;
|
||||
}
|
||||
|
||||
//! Concatenates two termlists.
|
||||
/**
|
||||
* Creates a completely new list that can be deleted.
|
||||
*
|
||||
* Note that the order is not preserved currently.
|
||||
*/
|
||||
Termlist
|
||||
termlistConcatStatic (Termlist tl1, Termlist tl2)
|
||||
{
|
||||
Termlist tl, tls;
|
||||
|
||||
tl = NULL;
|
||||
for (tls = tl1; tls != NULL; tls = tls->next)
|
||||
{
|
||||
tl = termlistAdd (tl, tls->term);
|
||||
}
|
||||
for (tls = tl2; tls != NULL; tls = tls->next)
|
||||
{
|
||||
tl = termlistAdd (tl, tls->term);
|
||||
}
|
||||
return tl;
|
||||
}
|
||||
|
||||
//! Remove the pointed at element from the termlist.
|
||||
/**
|
||||
* Easier because of the double linked list. Note: does not do termDelete on the term.
|
||||
*
|
||||
*@param tl The pointer to the termlist node to be deleted from the list.
|
||||
*@return The possibly new head pointer to the termlist.
|
||||
*/
|
||||
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;
|
||||
free (tl);
|
||||
return newhead;
|
||||
}
|
||||
|
||||
//! Construct the conjunction of two termlists.
|
||||
/**
|
||||
*@return A new termlist containing the elements in both lists.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Construct the conjunction of two termlists, and a certain type.
|
||||
/**
|
||||
*@return A new termlist containing the elements in both lists, that are also of the desired type.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Construct the conjunction of a termlist and a certain type.
|
||||
/**
|
||||
*@return A new termlist containing the elements in the list that are of the desired type.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Display a termlist.
|
||||
/**
|
||||
* Lists of terms are displayed between square brackets, and seperated by commas.
|
||||
*/
|
||||
void
|
||||
termlistPrint (Termlist tl)
|
||||
{
|
||||
if (tl == NULL)
|
||||
{
|
||||
eprintf ("[Empty]");
|
||||
return;
|
||||
}
|
||||
eprintf ("[");
|
||||
while (tl != NULL)
|
||||
{
|
||||
termPrint (tl->term);
|
||||
tl = tl->next;
|
||||
if (tl != NULL)
|
||||
eprintf (", ");
|
||||
}
|
||||
eprintf ("]");
|
||||
}
|
||||
|
||||
//! Append all open variables in a term to a list.
|
||||
/**
|
||||
*@param tl The list to which to append to.
|
||||
*@param t The term possibly containing open variables.
|
||||
*@return The pointer to the extended list.
|
||||
*\sa termlistAddRealVariables()
|
||||
*/
|
||||
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, TermOp (t)),
|
||||
TermKey (t));
|
||||
else
|
||||
return
|
||||
termlistAddVariables (termlistAddVariables (tl, TermOp1 (t)),
|
||||
TermOp2 (t));
|
||||
}
|
||||
}
|
||||
|
||||
//! Append all variables in a term to a list.
|
||||
/**
|
||||
*@param tl The list to which to append to.
|
||||
*@param t The term possibly containing open and closed variables.
|
||||
*@return The pointer to the extended list.
|
||||
*\sa termlistAddVariables()
|
||||
*/
|
||||
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, TermOp (t)),
|
||||
TermKey (t));
|
||||
else
|
||||
return
|
||||
termlistAddVariables (termlistAddVariables (tl, TermOp1 (t)),
|
||||
TermOp2 (t));
|
||||
}
|
||||
}
|
||||
|
||||
//! Append all basic terms in a term to a list.
|
||||
/**
|
||||
*@param tl The list to which to append to.
|
||||
*@param t The term containing basic terms.
|
||||
*@return The pointer to the extended list.
|
||||
*\sa termlistAddBasics()
|
||||
*/
|
||||
Termlist
|
||||
termlistAddBasic (Termlist tl, Term t)
|
||||
{
|
||||
t = deVar (t);
|
||||
|
||||
if (t == NULL)
|
||||
return tl;
|
||||
if (!realTermLeaf (t))
|
||||
{
|
||||
if (realTermEncrypt (t))
|
||||
return termlistAddBasic (termlistAddBasic (tl, TermOp (t)),
|
||||
TermKey (t));
|
||||
else
|
||||
return termlistAddBasic (termlistAddBasic (tl, TermOp1 (t)),
|
||||
TermOp2 (t));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inTermlist (tl, t))
|
||||
{
|
||||
return termlistAdd (tl, t);
|
||||
}
|
||||
|
||||
}
|
||||
return tl;
|
||||
}
|
||||
|
||||
//! Append all basic terms in a termlist to another list.
|
||||
/**
|
||||
*@param tl The list to which to append to.
|
||||
*@param scan The termlist with terms containing basic terms.
|
||||
*@return The pointer to the extended list.
|
||||
*\sa termlistAddBasic()
|
||||
*/
|
||||
Termlist
|
||||
termlistAddBasics (Termlist tl, Termlist scan)
|
||||
{
|
||||
while (scan != NULL)
|
||||
{
|
||||
tl = termlistAddBasic (tl, scan->term);
|
||||
scan = scan->next;
|
||||
}
|
||||
return tl;
|
||||
}
|
||||
|
||||
//! Remove a term from a termlist.
|
||||
/**
|
||||
* Removes the first occurrence of the term.
|
||||
*@return A new termlist pointer.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//! Determine the length of a termlist.
|
||||
int
|
||||
termlistLength (Termlist tl)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (tl != NULL)
|
||||
{
|
||||
tl = tl->next;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//! Give the inverse key term of a term.
|
||||
/**
|
||||
* Gives a duplicate of 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...
|
||||
*@param inverses The list of inverses, typically from the knowledge.
|
||||
*@param key Any term of which the inverse will be determined.
|
||||
*@return A pointer to a duplicate of the inverse key term. Use termDelete to remove it.
|
||||
*\sa termDuplicate(), knowledge::inverses
|
||||
*/
|
||||
|
||||
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 (TermKey (key))
|
||||
&& inTermlist (deVar (TermKey (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 (TermOp (orig)),
|
||||
termDuplicate (newk));
|
||||
}
|
||||
while (inverses != NULL && inverses->next != NULL)
|
||||
{
|
||||
|
||||
if (isTermEqual (TermKey (key), inverses->term))
|
||||
return funKey (key, inverses->next->term);
|
||||
if (isTermEqual (TermKey (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 */
|
||||
}
|
||||
|
||||
//! Create 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 only hold real leaves.
|
||||
*
|
||||
* variable instantiations are not followed through.
|
||||
*
|
||||
*\sa termlistLocal()
|
||||
*/
|
||||
Term
|
||||
termLocal (const Term t, Termlist fromlist, Termlist tolist)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
Term newt = termNodeDuplicate (t);
|
||||
if (realTermTuple (t))
|
||||
{
|
||||
TermOp1 (newt) = termLocal (TermOp1 (t), fromlist, tolist);
|
||||
TermOp2 (newt) = termLocal (TermOp2 (t), fromlist, tolist);
|
||||
}
|
||||
else
|
||||
{
|
||||
TermOp (newt) = termLocal (TermOp (t), fromlist, tolist);
|
||||
TermKey (newt) = termLocal (TermKey (t), fromlist, tolist);
|
||||
}
|
||||
return newt;
|
||||
}
|
||||
}
|
||||
|
||||
//! Create a list of instance terms.
|
||||
/**
|
||||
* We expand the termlocal concept to termlists.
|
||||
*\sa termLocal()
|
||||
*/
|
||||
Termlist
|
||||
termlistLocal (Termlist tl, const Termlist fromlist, const Termlist tolist)
|
||||
{
|
||||
Termlist newtl = NULL;
|
||||
|
||||
while (tl != NULL)
|
||||
{
|
||||
newtl = termlistAdd (newtl, termLocal (tl->term, fromlist, tolist));
|
||||
tl = tl->next;
|
||||
}
|
||||
return newtl;
|
||||
}
|
||||
|
||||
//! Check whether a termlist is contained in another.
|
||||
/**
|
||||
*@param tlbig The big list.
|
||||
*@param tlsmall The list that is possibly contained in the big one.
|
||||
*@return True iff tlsmall is contained in tlbig.
|
||||
*/
|
||||
int
|
||||
termlistContained (const Termlist tlbig, Termlist tlsmall)
|
||||
{
|
||||
while (tlsmall != NULL)
|
||||
{
|
||||
if (!inTermlist (tlbig, tlsmall->term))
|
||||
return 0;
|
||||
tlsmall = tlsmall->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Check substitution validity
|
||||
/**
|
||||
* Determine whether a variable has been substituted with something with
|
||||
* the right type.
|
||||
*@param matchmode The system matching mode, typically system::match
|
||||
*@param term The closed variable term.
|
||||
*@return True iff the substitution is valid in the current mode.
|
||||
*\sa system::match
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Yield the result of f(x)
|
||||
/**
|
||||
* This function interpretes two termlists as the domain and range of a function,
|
||||
* and if the term occurs in the domain, returns the matching value from the range.
|
||||
* Note that these functions cannot have NULL in the domain or the range.
|
||||
*@param fromlist The domain list.
|
||||
*@param tolist The range list, in a one-to-one correspondence with the fromlist.
|
||||
*@param tx The point on which the function is to be evaluated.
|
||||
*@return The result of the function application or NULL if the point is not within the domain.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//! Yield the last node of a termlist.
|
||||
Termlist
|
||||
termlistForward (Termlist tl)
|
||||
{
|
||||
if (tl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (tl->next != NULL)
|
||||
{
|
||||
tl = tl->next;
|
||||
}
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two termlists containing only basic terms, and yield ordering.
|
||||
*/
|
||||
int
|
||||
termlistOrder (Termlist tl1, Termlist tl2)
|
||||
{
|
||||
int order;
|
||||
|
||||
order = 0;
|
||||
while (order == 0 && tl1 != NULL && tl2 != NULL)
|
||||
{
|
||||
order = termOrder (tl1->term, tl2->term);
|
||||
tl1 = tl1->next;
|
||||
tl2 = tl2->next;
|
||||
}
|
||||
if (order != 0)
|
||||
return order;
|
||||
if (tl1 == NULL && tl2 == NULL)
|
||||
return order;
|
||||
if (tl1 == NULL)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Iterate over terms in termlist
|
||||
/**
|
||||
* Function gets terms
|
||||
*/
|
||||
int
|
||||
termlist_iterate (Termlist tl, int (*func) ())
|
||||
{
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (!func (tl->term))
|
||||
return 0;
|
||||
tl = tl->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Create a tuple term from a termlist
|
||||
Term
|
||||
termlist_to_tuple (Termlist tl)
|
||||
{
|
||||
int width;
|
||||
|
||||
width = termlistLength (tl);
|
||||
if (width > 1)
|
||||
{
|
||||
// 2 parts
|
||||
// Make two termlists for each side.
|
||||
Term tresult;
|
||||
Termlist tl1, tl2;
|
||||
int split, i;
|
||||
|
||||
/**
|
||||
* This can be done much more efficiently by cutting
|
||||
* the list temporarily, and reconnecting it afterwards.
|
||||
*/
|
||||
tl1 = NULL;
|
||||
tl2 = NULL;
|
||||
split = width / 2;
|
||||
i = 0;
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (i < split)
|
||||
tl1 = termlistAdd (tl1, tl->term);
|
||||
else
|
||||
tl2 = termlistAdd (tl2, tl->term);
|
||||
tl = tl->next;
|
||||
i++;
|
||||
}
|
||||
tresult =
|
||||
makeTermTuple (termlist_to_tuple (tl1), termlist_to_tuple (tl2));
|
||||
termlistDelete (tl1);
|
||||
termlistDelete (tl2);
|
||||
return tresult;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tl == NULL)
|
||||
{
|
||||
// W00t! Wtf?
|
||||
error ("termlist_to_tuple called (internally?) with NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Single node, simple
|
||||
return termDuplicate (tl->term);
|
||||
}
|
||||
}
|
||||
// @TODO Should be considered an error
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! Split a tuple term into termlist components.
|
||||
Termlist
|
||||
tuple_to_termlist (Term t)
|
||||
{
|
||||
t = deVar (t);
|
||||
if (t == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (realTermTuple (t))
|
||||
{
|
||||
return termlistConcat (tuple_to_termlist (TermOp1 (t)),
|
||||
tuple_to_termlist (TermOp2 (t)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return termlistAdd (NULL, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Remove all items from tlbig that occur in tlsmall, and return the pointer to the new tlbig.
|
||||
Termlist
|
||||
termlistMinusTermlist (const Termlist tlbig, const Termlist tlsmall)
|
||||
{
|
||||
Termlist tl;
|
||||
Termlist tlnewstart;
|
||||
|
||||
tl = tlbig;
|
||||
tlnewstart = tlbig;
|
||||
while (tl != NULL)
|
||||
{
|
||||
if (inTermlist (tlsmall, tl->term))
|
||||
{
|
||||
Termlist tlnext;
|
||||
|
||||
// Remember next node.
|
||||
tlnext = tl->next;
|
||||
// This node should be removed.
|
||||
tlnewstart = termlistDelTerm (tl);
|
||||
// Skip to next.
|
||||
tl = tlnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This item will remain in the list.
|
||||
tl = tl->next;
|
||||
}
|
||||
}
|
||||
return tlnewstart;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
#ifndef TERMLISTS
|
||||
#define TERMLISTS
|
||||
|
||||
#include "term.h"
|
||||
|
||||
//! The list container for the term type.
|
||||
/**
|
||||
* Implemented as a double linked list to allow for element deletion.
|
||||
*\sa term
|
||||
*/
|
||||
struct termlist
|
||||
{
|
||||
//! The term element for this node.
|
||||
Term term;
|
||||
//! Next node pointer or NULL for the tail of the list.
|
||||
struct termlist *next;
|
||||
//! Previous node pointer or NULL for the head of the list.
|
||||
struct termlist *prev;
|
||||
};
|
||||
|
||||
//! Shorthand for termlist pointers.
|
||||
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);
|
||||
__inline__ int inTermlist (Termlist tl, const Term term);
|
||||
__inline__ Termlist termlistFind (Termlist tl, const Term term);
|
||||
int isTermlistEqual (Termlist tl1, Termlist tl2);
|
||||
Termlist termlistAdd (Termlist tl, Term term);
|
||||
#define termlistPrepend(tl,t) termlistAdd(tl,t)
|
||||
Termlist termlistAppend (const Termlist tl, const Term term);
|
||||
Termlist termlistAddNew (const Termlist tl, const Term t);
|
||||
Termlist termlistConcat (Termlist tl1, Termlist tl2);
|
||||
Termlist termlistConcatStatic (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);
|
||||
Termlist termlistLocal (Termlist tl, const Termlist fromlist,
|
||||
const Termlist tolist);
|
||||
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);
|
||||
int termlistOrder (Termlist tl1, Termlist tl2);
|
||||
int termlist_iterate (Termlist tl, int (*func) ());
|
||||
Term termlist_to_tuple (Termlist tl);
|
||||
Termlist tuple_to_termlist (Term t);
|
||||
Termlist termlistMinusTermlist (const Termlist tlbig, const Termlist tlsmall);
|
||||
|
||||
#define TERMLISTADD(l,t) l = termlistAdd (l,t)
|
||||
#define TERMLISTAPPEND(l,t) l = termlistAppend (l,t)
|
||||
|
||||
#endif
|
@ -1,123 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "termmap.h"
|
||||
#include "debug.h"
|
||||
|
||||
//! Open termmaps code.
|
||||
void
|
||||
termmapsInit (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//! Close termmaps code.
|
||||
void
|
||||
termmapsDone (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//! Allocate memory for a termmap node.
|
||||
/**
|
||||
*@return A pointer to uninitialised memory of the size of a termmap node.
|
||||
*/
|
||||
Termmap
|
||||
makeTermmap (void)
|
||||
{
|
||||
/* inline candidate */
|
||||
return (Termmap) malloc (sizeof (struct termmap));
|
||||
}
|
||||
|
||||
//! Get function result
|
||||
/**
|
||||
*@return Yields f(x), or -1 when it is not present.
|
||||
*/
|
||||
int
|
||||
termmapGet (Termmap f, const Term x)
|
||||
{
|
||||
while (f != NULL)
|
||||
{
|
||||
if (isTermEqual (x, f->term))
|
||||
return f->result;
|
||||
f = f->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! Add a value to a function.
|
||||
/**
|
||||
*@return Adds f(x)=y to an existing function f. If f is NULL, a function is created. If x is already in the domain, the value is replaced.
|
||||
*/
|
||||
Termmap
|
||||
termmapSet (const Termmap f, const Term x, const int y)
|
||||
{
|
||||
Termmap fscan;
|
||||
|
||||
//! Determine whether term already occurs
|
||||
fscan = f;
|
||||
while (fscan != NULL)
|
||||
{
|
||||
if (isTermEqual (x, fscan->term))
|
||||
{
|
||||
//! Is the result correct already?
|
||||
if (fscan->result != y)
|
||||
fscan->result = y;
|
||||
return f;
|
||||
}
|
||||
fscan = fscan->next;
|
||||
}
|
||||
//! Not occurred yet, make new node
|
||||
fscan = makeTermmap ();
|
||||
fscan->term = x;
|
||||
fscan->result = y;
|
||||
fscan->next = f;
|
||||
return fscan;
|
||||
}
|
||||
|
||||
//! Duplicate a function
|
||||
Termmap
|
||||
termmapDuplicate (const Termmap f)
|
||||
{
|
||||
if (f != NULL)
|
||||
{
|
||||
Termmap g;
|
||||
|
||||
g = makeTermmap ();
|
||||
g->term = f->term;
|
||||
g->result = f->result;
|
||||
g->next = termmapDuplicate (f->next);
|
||||
return g;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//! Delete a function
|
||||
void
|
||||
termmapDelete (const Termmap f)
|
||||
{
|
||||
if (f != NULL)
|
||||
{
|
||||
termmapDelete (f->next);
|
||||
free (f);
|
||||
}
|
||||
}
|
||||
|
||||
//! Print a function
|
||||
void
|
||||
termmapPrint (Termmap f)
|
||||
{
|
||||
if (f != NULL)
|
||||
{
|
||||
eprintf ("\"");
|
||||
termPrint (f->term);
|
||||
eprintf ("\" -> %i", f->result);
|
||||
if (f->next != NULL)
|
||||
{
|
||||
eprintf (", ");
|
||||
termmapPrint (f->next);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef TERMMAPS
|
||||
#define TERMMAPS
|
||||
|
||||
#include "term.h"
|
||||
|
||||
//! The function container for the term to integer function type.
|
||||
/**
|
||||
*\sa term
|
||||
*/
|
||||
struct termmap
|
||||
{
|
||||
//! The term element for this node.
|
||||
Term term;
|
||||
//! Next node pointer or NULL for the last element of the function.
|
||||
struct termmap *next;
|
||||
//! Function result
|
||||
int result;
|
||||
};
|
||||
|
||||
//! Shorthand for termmap pointers.
|
||||
typedef struct termmap *Termmap;
|
||||
|
||||
void termmapsInit (void);
|
||||
void termmapsDone (void);
|
||||
int termmapGet (Termmap f, const Term x);
|
||||
Termmap termmapSet (const Termmap f, const Term x, const int y);
|
||||
Termmap termmapDuplicate (const Termmap f);
|
||||
void termmapDelete (const Termmap f);
|
||||
void termmapPrint (Termmap f);
|
||||
|
||||
#endif
|
@ -1,69 +0,0 @@
|
||||
#include "timer.h"
|
||||
|
||||
/*
|
||||
* Timer functions
|
||||
*
|
||||
* Currently, this only works under linux (where the linux macro is defined by the compiler). Otherwise, it simply assumes the timer is never passed.
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
#include <time.h>
|
||||
#include <sys/times.h>
|
||||
static clock_t endwait = 0;
|
||||
#endif
|
||||
|
||||
static int time_max_seconds = 0;
|
||||
|
||||
//! Set initial time limit.
|
||||
/**
|
||||
* <= 0 means none.
|
||||
*/
|
||||
void
|
||||
set_time_limit (int seconds)
|
||||
{
|
||||
if (seconds > 0)
|
||||
{
|
||||
time_max_seconds = seconds;
|
||||
#ifdef linux
|
||||
endwait = seconds * CLOCKS_PER_SEC;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
time_max_seconds = 0;
|
||||
#ifdef linux
|
||||
endwait = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//! Retrieve time limit
|
||||
int
|
||||
get_time_limit ()
|
||||
{
|
||||
return time_max_seconds;
|
||||
}
|
||||
|
||||
//! Check whether time limit has passed.
|
||||
int
|
||||
passed_time_limit ()
|
||||
{
|
||||
#ifdef linux
|
||||
if (endwait <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct tms t;
|
||||
|
||||
times (&t);
|
||||
if (t.tms_utime > endwait)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef TIMER
|
||||
#define TIMER
|
||||
|
||||
void set_time_limit (int seconds);
|
||||
int get_time_limit ();
|
||||
int passed_time_limit ();
|
||||
|
||||
#endif
|
@ -1,51 +0,0 @@
|
||||
- Error should have an additional line number parameter (that might be
|
||||
-1 to ignore it) forcing people to use numbers :)
|
||||
Format: "error: [%i] %s\n"
|
||||
- Nested functions should be avoided: their implementation requires an
|
||||
executable stack, which is bad for security purposes. However, many of
|
||||
the iterator functions need to pass a function and possibly some
|
||||
variables. Currently, the variables are handled by the nested function
|
||||
mechanism (the iterated nested function and address variables of the
|
||||
function it is part of), which would not work anymore. A possible
|
||||
solution seems variable argument count functions, but this is fairly
|
||||
cumbersome and might impact on performance. Alternatively, iterators
|
||||
can be implemented as macros, which is probably the fastest, but maybe
|
||||
less readable.
|
||||
- --check is slightly f***ed up because there is no good semantics for
|
||||
the --disable intruder check. As a result, it is now too strict can
|
||||
cause correct protocols to fail. Fix.
|
||||
- When *not* asking for attack output, maybe we should default to
|
||||
--prune = 1. Then, if we ask for --xml output or --dot, we do:
|
||||
if --prune == 1 then --prune == 2 now :) unless otherwise specified.
|
||||
(This should be done after switch checking)
|
||||
- Old version enforced some extra orders:
|
||||
1. M_0 roles were ordered before any other roles.
|
||||
2. Local constants order: if a run has a local variable instantiated by
|
||||
somebody else's variable, that should occur then after the initial sending
|
||||
of that value...
|
||||
- Test 'sk(x)' in goals, somewhere before assessing a state (dus at the
|
||||
beginning of iterate), immediately reduce to 'sk(Eve)'. Test with
|
||||
--experimental. To that end, reintroduce a state-reporting switch.
|
||||
- It is currently not well-defined to define inversekeys within a role:
|
||||
this requires some work at instantiation, because instantiated term
|
||||
couples should be added to the inverses list, and removed at
|
||||
descruction.
|
||||
- Simple timestamps could be added by prefixing send message before the
|
||||
role, sending any timestamp constants out first to the intruder. These
|
||||
should of course be hidden in the output somehow.
|
||||
- Notes on the new attack group displays:
|
||||
* We want to group runs into consistent protocol runs.
|
||||
* Minimal req. for protocol run: equal \rho.
|
||||
* If two runs are candidates for a role in a protocol run,
|
||||
use a metric based on order and data. Maybe data is more important:
|
||||
if equal data, than order might be irrelevant.
|
||||
* Maybe we should refactor the xmlOut code first. In an extreme case,
|
||||
we first factor out all logic, and ranking, and grouping, in to a
|
||||
prepareAttackOutput structure; with a separate source file. Later we
|
||||
can convert this to either ASCII or DOT or XML or something.
|
||||
Now that I think of it; XML should be a plain state probably, and we
|
||||
could add a switch to also output more detailed attack things (is
|
||||
that relevant?)
|
||||
- SConstruct file should check whether ctags actually exists (avoiding
|
||||
errors)
|
||||
- Proof output should be XML, with an external converter to dot format.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user