- Big restructuring of the directories
31
AUTHORS
@ -1,31 +0,0 @@
|
||||
==================
|
||||
# Scyther README #
|
||||
==================
|
||||
|
||||
----------------
|
||||
1. About Scyther
|
||||
----------------
|
||||
|
||||
Scyther bla Cas andsoforth, bla Lutger, yada yada yada.
|
||||
|
||||
---------------
|
||||
2. Requirements
|
||||
---------------
|
||||
|
||||
Scyther compilation depends on a few external items:
|
||||
|
||||
- A C compiler (gcc or anything modern *nixy will do)
|
||||
- The Flex and Bison scanner/compiler generation tools.
|
||||
|
||||
These two requirements are usually met by default by any modern *nix
|
||||
variant, such as GNU/Linux.
|
||||
|
||||
If you want LaTeX output we need
|
||||
|
||||
- LaTeX
|
||||
- The MSC macro package msc.sty
|
||||
|
||||
For the documentation generation, optionally with graphs.
|
||||
- Doxygen: http://www.doxygen.org/
|
||||
- Dot: http://www.research.att.com/sw/tools/graphviz/
|
||||
|
@ -1,13 +0,0 @@
|
||||
Mac
|
||||
|
||||
MacPorts (Martijn)
|
||||
|
||||
- Easy
|
||||
|
||||
Fink (Christoph)
|
||||
|
||||
- Lots of stuff problematic, probably easiest to install elementtree locally into the Scyther directory. (package-rev/elementtree into Scyther)
|
||||
|
||||
- Leave Python version as is, install dot/graphviz, wx seems to be there already.
|
||||
|
||||
- pythonw needed to start for screen access
|
Before Width: | Height: | Size: 592 KiB After Width: | Height: | Size: 592 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 807 KiB After Width: | Height: | Size: 807 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
8
gui/src/BuildMacIntel-MacPPC.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
################################################################
|
||||
# Name: BuildMacIntel-MacPPC.cmake
|
||||
# Purpose: Build MacPPC binary on MacIntel
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
include (BuildMacPPC.cmake)
|
||||
|
11
gui/src/BuildMacIntel.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
################################################################
|
||||
# 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")
|
||||
|
8
gui/src/BuildMacPPC-MacIntel.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
################################################################
|
||||
# Name: BuildMacPPC-MacIntel.cmake
|
||||
# Purpose: Build MacIntel binary on MacPPC
|
||||
# Author: Cas Cremers
|
||||
################################################################
|
||||
|
||||
include (BuildMacIntel.cmake)
|
||||
|
11
gui/src/BuildMacPPC.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
################################################################
|
||||
# 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")
|
||||
|
36
gui/src/BuildPlatform.cmake
Normal file
@ -0,0 +1,36 @@
|
||||
################################################################
|
||||
# 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})
|
||||
|
15
gui/src/BuildUnix-Win32.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
################################################################
|
||||
# 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})
|
||||
|
12
gui/src/BuildUnix.cmake
Normal file
@ -0,0 +1,12 @@
|
||||
################################################################
|
||||
# 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})
|
||||
|
37
gui/src/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
################################################################
|
||||
# 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)
|
||||
|
33
gui/src/FindBISON.cmake
Normal file
@ -0,0 +1,33 @@
|
||||
# - 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)
|
||||
|
33
gui/src/FindFLEX.cmake
Normal file
@ -0,0 +1,33 @@
|
||||
# - 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)
|
||||
|
43
gui/src/GetOS.cmake
Normal file
@ -0,0 +1,43 @@
|
||||
################################################################
|
||||
# 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}")
|
||||
|
86
gui/src/Makefile-fallback
Normal file
@ -0,0 +1,86 @@
|
||||
#
|
||||
# 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
|
||||
|
58
gui/src/SVNVersion.cmake
Normal file
@ -0,0 +1,58 @@
|
||||
################################################################
|
||||
# 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)
|
||||
|
41
gui/src/ScannerParser.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
################################################################
|
||||
# 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)
|
||||
|
||||
|
789
gui/src/Scyther.dev
Normal file
@ -0,0 +1,789 @@
|
||||
[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=
|
||||
|
42
gui/src/UniversalBinary.cmake
Normal file
@ -0,0 +1,42 @@
|
||||
################################################################
|
||||
# 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
Normal file
20
gui/src/arachne.h
Normal file
@ -0,0 +1,20 @@
|
||||
#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
|
61
gui/src/attacktemplate.tex
Normal file
@ -0,0 +1,61 @@
|
||||
\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}
|
617
gui/src/binding.c
Normal file
@ -0,0 +1,617 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
53
gui/src/binding.h
Normal file
@ -0,0 +1,53 @@
|
||||
#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
Normal file
@ -0,0 +1,119 @@
|
||||
--+++ 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.
|
||||
|
16
gui/src/build.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/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
Normal file
18
gui/src/claim.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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
|
39
gui/src/color.c
Normal file
@ -0,0 +1,39 @@
|
||||
/** @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)
|
||||
{
|
||||
}
|
12
gui/src/color.h
Normal file
@ -0,0 +1,12 @@
|
||||
#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
|
18
gui/src/compile.txt
Normal file
@ -0,0 +1,18 @@
|
||||
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
Normal file
26
gui/src/compiler.h
Normal file
@ -0,0 +1,26 @@
|
||||
#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
|
11
gui/src/copy2gui.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/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
|
||||
|
74
gui/src/cost.c
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
*
|
||||
*@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;
|
||||
}
|
6
gui/src/cost.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef COST
|
||||
#define COST
|
||||
|
||||
int attackCost (const System sys);
|
||||
|
||||
#endif
|
52
gui/src/debug.c
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
*@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
|
||||
}
|
10
gui/src/debug.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
void debugSet (int level);
|
||||
int debugCond (int level);
|
||||
void debug (int level, char *string);
|
||||
|
||||
#define DEBUGL(a) debugCond(a)
|
||||
|
||||
#endif
|
569
gui/src/depend.c
Normal file
@ -0,0 +1,569 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
44
gui/src/depend.h
Normal file
@ -0,0 +1,44 @@
|
||||
#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
|
47
gui/src/design.txt
Normal file
@ -0,0 +1,47 @@
|
||||
Design Issues for the Model Checker
|
||||
-----------------------------------
|
||||
|
||||
- For secrecy, we can trigger all sends at once. For synchronisation,
|
||||
this is not the case.
|
||||
|
||||
- Modules have to be split up sensibly.
|
||||
|
||||
- Although 'knowledge' and 'term matching' seem to different items,
|
||||
their intertwined workings suggest that they should be implemented
|
||||
in parallel.
|
||||
|
||||
- State generation (as in creating instances) might already allow for
|
||||
a lot of static analysis.
|
||||
|
||||
- We should make a list of required operations. Ingmar's work can serve
|
||||
as a starting point.
|
||||
|
||||
- For now, there will be no parser, and test cases will be input by
|
||||
hand.
|
||||
|
||||
- Synchronisation is more difficult to test, so we focus on secrecy
|
||||
first. I've got some good ideas on Synchronisation testing though
|
||||
(with narrowing sets of possible partners). Synchronisation is very
|
||||
hard to prune, I presume. I have to prove that though ;)
|
||||
|
||||
Sketch for secrecy:
|
||||
|
||||
SimulateStep(F,M,constraints):
|
||||
if Empty(F):
|
||||
return
|
||||
else:
|
||||
for (s in PossibleSends):
|
||||
add s.message to M
|
||||
if (secrecy violated):
|
||||
halt
|
||||
remove s from F
|
||||
ReadSets = supersetTransitions(F)
|
||||
for (ReadSet in ReadSets):
|
||||
for (s in ReadSet):
|
||||
// dit is vaag
|
||||
if NonMatch goto next ReadSet
|
||||
constraint = F,M,match()
|
||||
SimulateStep(F \ s,M,constraints)
|
||||
|
||||
|
||||
|
1814
gui/src/dotout.c
Normal file
6
gui/src/dotout.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef DOTOUTPUT
|
||||
#define DOTOUTPUT
|
||||
|
||||
void dotSemiState (const System sys);
|
||||
|
||||
#endif
|
94
gui/src/error.c
Normal file
@ -0,0 +1,94 @@
|
||||
#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);
|
||||
}
|
19
gui/src/error.h
Normal file
@ -0,0 +1,19 @@
|
||||
#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
|
4
gui/src/git-test.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Test file to see whether it works.
|
||||
Wow.
|
||||
New line.
|
||||
And a better conflict should start here.
|
399
gui/src/heuristic.c
Normal file
@ -0,0 +1,399 @@
|
||||
/**
|
||||
*
|
||||
*@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;
|
||||
}
|
9
gui/src/heuristic.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef HEURISTIC
|
||||
#define HEURISTIC
|
||||
|
||||
#include "system.h"
|
||||
#include "binding.h"
|
||||
|
||||
Binding select_goal (const System sys);
|
||||
|
||||
#endif
|
261
gui/src/hidelevel.c
Normal file
@ -0,0 +1,261 @@
|
||||
/** @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;
|
||||
}
|
27
gui/src/hidelevel.h
Normal file
@ -0,0 +1,27 @@
|
||||
#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
|
31
gui/src/hidelevel.txt
Normal file
@ -0,0 +1,31 @@
|
||||
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
|
197
gui/src/intruderknowledge.c
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
9
gui/src/intruderknowledge.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef INTRUDERKNOWLEDGE
|
||||
#define INTRUDERKNOWLEDGE
|
||||
|
||||
#include "system.h"
|
||||
#include "switches.h"
|
||||
|
||||
void initialIntruderKnowledge (const System sys);
|
||||
|
||||
#endif
|
550
gui/src/knowledge.c
Normal file
@ -0,0 +1,550 @@
|
||||
/**
|
||||
*@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;
|
||||
}
|
75
gui/src/knowledge.h
Normal file
@ -0,0 +1,75 @@
|
||||
#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
|
86
gui/src/label.c
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
26
gui/src/label.h
Normal file
@ -0,0 +1,26 @@
|
||||
#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
|
46
gui/src/language.txt
Normal file
@ -0,0 +1,46 @@
|
||||
Language
|
||||
--------
|
||||
|
||||
language := (<def>)*
|
||||
def := (<directive> | <protocol> | <rundef> | <unstrusted>)
|
||||
|
||||
//directive := <dir_require>
|
||||
//dir_require := require <filename>;
|
||||
|
||||
protocol := protocol <protocolname> ( <rolelist> ) { <roledef>* } optsc
|
||||
protocolname := <id>
|
||||
|
||||
intruderknow := public <termlist>;
|
||||
roledef := role <rolename> { <actions> } optsc
|
||||
rolename := <id>
|
||||
actions := (<action>;)+
|
||||
action := (<read> | <send> | <claim>)
|
||||
decl := (<const> | <var>)+
|
||||
const := const <termlist> [ : <typeterm> ];
|
||||
var := var <termlist> [ : <typelist> ];
|
||||
|
||||
read := read [_<label>] (<term>,<term>,<term>);
|
||||
send := send [_<label>] (<term>,<term>,<term>);
|
||||
claim := claim [_<label>] (<term>,<termlist>);
|
||||
label := <id>;
|
||||
|
||||
rundef := <protocolname>.<rolename> ( <instancelist> ) ;
|
||||
instancelist := (<agent>|<typeterm>)*
|
||||
|
||||
agent := <term>
|
||||
typeterm := <term>
|
||||
typelist := <termlist>
|
||||
|
||||
untrusted := untrusted <termlist>;
|
||||
|
||||
termlist := <term> [, <termlist>]
|
||||
term := (<baseterm> | <encterm> | <tupleterm> | <function>)
|
||||
encterm := { <term> } <term>
|
||||
function := <term> ( <term> )
|
||||
baseterm := (<variable> | <const>)
|
||||
variable := <id>
|
||||
const := <id>
|
||||
|
||||
optsc := [ ; ]
|
||||
id := (<digit>|<uppercase>|<lowercase>)+
|
||||
|
3
gui/src/license.txt
Normal file
@ -0,0 +1,3 @@
|
||||
- GNU getopt
|
||||
- GNU bison/flex
|
||||
- de rest (c) Cas
|
272
gui/src/list.c
Normal file
@ -0,0 +1,272 @@
|
||||
/**
|
||||
*@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;
|
||||
}
|
28
gui/src/list.h
Normal file
@ -0,0 +1,28 @@
|
||||
#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
Normal file
@ -0,0 +1,260 @@
|
||||
/**
|
||||
*@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
Normal file
@ -0,0 +1,624 @@
|
||||
#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;
|
||||
}
|
||||
}
|
30
gui/src/mgu.h
Normal file
@ -0,0 +1,30 @@
|
||||
#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
|
17
gui/src/notes.txt
Normal file
@ -0,0 +1,17 @@
|
||||
- (!!) 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.
|
1012
gui/src/obsolete-switches.txt
Normal file
325
gui/src/parser.y
Normal file
@ -0,0 +1,325 @@
|
||||
%{
|
||||
#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;
|
||||
}
|
||||
|
||||
|
13
gui/src/pheading.h
Normal file
@ -0,0 +1,13 @@
|
||||
#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
|
25
gui/src/problem.spdl
Normal file
@ -0,0 +1,25 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
265
gui/src/prune_bounds.c
Normal file
@ -0,0 +1,265 @@
|
||||
/**
|
||||
*
|
||||
*@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;
|
||||
}
|
6
gui/src/prune_bounds.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PRUNEBOUNDS
|
||||
#define PRUNEBOUNDS
|
||||
|
||||
int prune_bounds (const System sys);
|
||||
|
||||
#endif
|
484
gui/src/prune_theorems.c
Normal file
@ -0,0 +1,484 @@
|
||||
/**
|
||||
*
|
||||
*@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;
|
||||
}
|
6
gui/src/prune_theorems.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PRUNETHEOREMS
|
||||
#define PRUNETHEOREMS
|
||||
|
||||
int prune_theorems (const System sys);
|
||||
|
||||
#endif
|
5
gui/src/reindent.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Indent any changed files, ending in .c or .h
|
||||
#
|
||||
svn st | grep "^[MA].*\.[ch]$"| awk '{print $2}' | xargs indent
|
33
gui/src/releases.txt
Normal file
@ -0,0 +1,33 @@
|
||||
? bonk
|
||||
- New partial order reduction method.
|
||||
Maybe CLP/t4
|
||||
maybe MSC stuff
|
||||
|
||||
2004-02-19 billionaire
|
||||
- replace substitutions with implicit substitutions.
|
||||
- many syntax updates.
|
||||
- many speed improvements.
|
||||
|
||||
2004-01-20 alpha1
|
||||
teehee_valley with a couple of minor bugfixes.
|
||||
- Shows error line correctly on parse.
|
||||
- Allows for multi-line comments.
|
||||
|
||||
2004-01-20 teehee_valley
|
||||
Nicely working role-based release, can test stdin scenario files.
|
||||
- Preliminary untrusted support.
|
||||
- Public, inversekeys are working.
|
||||
- No tickets yet.
|
||||
|
||||
2004-01-19 amoxicillin
|
||||
Preliminary compiler test release.
|
||||
- Compiler works in ptest, now we can integrate it into the main
|
||||
part, and throw out the scenarios.
|
||||
|
||||
2003 dead_ringers
|
||||
A first working release.
|
||||
- -t0 through -t2 implemented.
|
||||
- Typed matching matches all basic terms.
|
||||
- CLP matching works (-m2), but is not compatible with -t2.
|
||||
- Hard coded protocols, inclusion through Makefile.
|
||||
|
515
gui/src/role.c
Normal file
@ -0,0 +1,515 @@
|
||||
/**
|
||||
* @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
Normal file
@ -0,0 +1,174 @@
|
||||
#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
|
227
gui/src/scanner.l
Normal file
@ -0,0 +1,227 @@
|
||||
%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:
|
119
gui/src/scantags.py
Executable file
@ -0,0 +1,119 @@
|
||||
#!/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()
|
||||
|
97
gui/src/specialterm.c
Normal file
@ -0,0 +1,97 @@
|
||||
#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;
|
||||
}
|
33
gui/src/specialterm.h
Normal file
@ -0,0 +1,33 @@
|
||||
#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
|
38
gui/src/states.c
Normal file
@ -0,0 +1,38 @@
|
||||
#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);
|
||||
}
|
21
gui/src/states.h
Normal file
@ -0,0 +1,21 @@
|
||||
#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
|
21
gui/src/subbuild-mac-universal.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/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 "---------------------------------------------------------"
|
||||
|
24
gui/src/subbuild-unix-both.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/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 "---------------------------------------------------------"
|
||||
|
19
gui/src/subbuild-version-information.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/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
|
||||
|
||||
|