- Big catchup commit to make sure we are up to beta7.
This includes a number of single patches, ranging from the vista fix with the buffers, to the start of many new minor features.
This commit is contained in:
@@ -11,6 +11,8 @@ import os.path
|
||||
|
||||
""" Import scyther-gui components """
|
||||
|
||||
import Scyther
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
""" Globals """
|
||||
@@ -19,9 +21,17 @@ basedir = ""
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def setBaseDir(mybasedir):
|
||||
global basedir
|
||||
|
||||
basedir = mybasedir
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class AboutScyther(wx.Dialog):
|
||||
def __init__(self,parent,mybasedir=None):
|
||||
|
||||
from Version import SCYTHER_GUI_VERSION
|
||||
global basedir
|
||||
|
||||
self.text = '''
|
||||
@@ -29,6 +39,7 @@ class AboutScyther(wx.Dialog):
|
||||
<body bgcolor="#ffffff">
|
||||
<img src="$SPLASH">
|
||||
<p align="right"><b>Scyther : $VERSION</b></p>
|
||||
<small>
|
||||
<p>
|
||||
<b>Scyther</b> is an automatic tool for the verification and
|
||||
falsification of security protocols.
|
||||
@@ -42,21 +53,31 @@ class AboutScyther(wx.Dialog):
|
||||
<a target="_blank" href="http://people.inf.ethz.ch/cremersc/scyther/index.html">
|
||||
http://people.inf.ethz.ch/cremersc/scyther/index.html</a>
|
||||
</p>
|
||||
<p>
|
||||
$DETAILS
|
||||
</p>
|
||||
<p>
|
||||
Credits: Cas Cremers (Scyther theory, backend, and main GUI
|
||||
code), Gijs Hollestelle (Python parser for Scyther XML output).
|
||||
</p>
|
||||
</small>
|
||||
'''
|
||||
|
||||
if mybasedir:
|
||||
basedir = mybasedir
|
||||
|
||||
# Debugging output of some parameters
|
||||
|
||||
splashdir = os.path.join(basedir,"Images")
|
||||
splashimage = os.path.join(splashdir,"scyther-splash.png")
|
||||
details_html = "Base directory: %s<br>\n" % (basedir)
|
||||
details_html += Scyther.Scyther.GetInfo(html=True)
|
||||
|
||||
self.text = self.text.replace("$SPLASH",splashimage)
|
||||
self.text = self.text.replace("$DETAILS",details_html)
|
||||
|
||||
# version information
|
||||
self.text = self.text.replace("$VERSION", "1.0-beta6")
|
||||
self.text = self.text.replace("$VERSION", SCYTHER_GUI_VERSION)
|
||||
|
||||
wx.Dialog.__init__(self, parent, -1, 'About Scyther',
|
||||
size=(660,620))
|
||||
|
||||
@@ -183,6 +183,7 @@ class AttackWindow(wx.Frame):
|
||||
# Add attacks (possible with tabs)
|
||||
self.displays=[]
|
||||
attacks = self.claim.attacks
|
||||
|
||||
n = len(attacks)
|
||||
if n <= 1:
|
||||
# Just a single window
|
||||
|
||||
@@ -71,10 +71,35 @@ class Editor(object):
|
||||
def __init__(self, parent):
|
||||
# Empty start
|
||||
self.SetText("")
|
||||
self.SetChanged(False)
|
||||
|
||||
def SetText(self):
|
||||
pass
|
||||
|
||||
def SetErrors(self,errors):
|
||||
pass
|
||||
|
||||
def GetChanged(self):
|
||||
"""
|
||||
Return true if file was changed
|
||||
"""
|
||||
return self.savedtext != self.GetText()
|
||||
|
||||
def SetChanged(self,nowchanged=False):
|
||||
"""
|
||||
Set changed status
|
||||
"""
|
||||
if nowchanged:
|
||||
self.savedtext = ""
|
||||
else:
|
||||
self.SetSaved()
|
||||
|
||||
def SetSaved(self):
|
||||
self.savedtext = self.GetText()
|
||||
|
||||
def SetOpened(self):
|
||||
self.SetSaved()
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class EditorNormal(Editor):
|
||||
|
||||
@@ -20,7 +20,7 @@ import Editor
|
||||
""" Some constants """
|
||||
ID_VERIFY = 100
|
||||
ID_AUTOVERIFY = 101
|
||||
ID_STATESPACE = 102
|
||||
ID_CHARACTERIZE = 102
|
||||
ID_CHECK = 103
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -47,7 +47,7 @@ class MainWindow(wx.Frame):
|
||||
if len(args) > 0:
|
||||
filename = args[0]
|
||||
if filename != '' and os.path.isfile(filename):
|
||||
self.filename = filename
|
||||
(self.dirname,self.filename) = os.path.split(filename)
|
||||
self.load = True
|
||||
|
||||
Icon.ScytherIcon(self)
|
||||
@@ -60,7 +60,7 @@ class MainWindow(wx.Frame):
|
||||
(wx.ACCEL_NORMAL, wx.WXK_F1,
|
||||
ID_VERIFY),
|
||||
(wx.ACCEL_NORMAL, wx.WXK_F2,
|
||||
ID_STATESPACE),
|
||||
ID_CHARACTERIZE),
|
||||
(wx.ACCEL_NORMAL, wx.WXK_F5,
|
||||
ID_CHECK),
|
||||
(wx.ACCEL_NORMAL, wx.WXK_F6,
|
||||
@@ -85,9 +85,9 @@ class MainWindow(wx.Frame):
|
||||
#bt = wx.Button(self,ID_VERIFY)
|
||||
#buttons.Add(bt,0)
|
||||
#self.Bind(wx.EVT_BUTTON, self.OnVerify, bt)
|
||||
#bt = wx.Button(self,ID_STATESPACE)
|
||||
#bt = wx.Button(self,ID_CHARACTERIZE)
|
||||
#buttons.Add(bt,0)
|
||||
#self.Bind(wx.EVT_BUTTON, self.OnStatespace, bt)
|
||||
#self.Bind(wx.EVT_BUTTON, self.OnCharacterize, bt)
|
||||
#sizer.Add(buttons, 0, wx.ALIGN_LEFT)
|
||||
|
||||
# Top: input
|
||||
@@ -98,8 +98,11 @@ class MainWindow(wx.Frame):
|
||||
if self.load:
|
||||
textfile = open(os.path.join(self.dirname, self.filename), 'r')
|
||||
self.editor.SetText(textfile.read())
|
||||
os.chdir(self.dirname)
|
||||
if self.dirname != "":
|
||||
os.chdir(self.dirname)
|
||||
textfile.close()
|
||||
self.editor.SetOpened()
|
||||
|
||||
self.top.AddPage(self.editor.control,"Protocol description")
|
||||
self.settings = Settingswindow.SettingsWindow(self.top,self)
|
||||
self.top.AddPage(self.settings,"Settings")
|
||||
@@ -138,8 +141,8 @@ class MainWindow(wx.Frame):
|
||||
self.CreateMenu(menuBar, '&Verify',
|
||||
[(ID_VERIFY, '&Verify protocol\tF1','Verify the protocol in the buffer using Scyther',
|
||||
self.OnVerify) ,
|
||||
(ID_STATESPACE, 'Generate &statespace\tF2','TODO' ,
|
||||
self.OnStatespace) ,
|
||||
(ID_CHARACTERIZE, '&Characterize roles\tF2','TODO' ,
|
||||
self.OnCharacterize) ,
|
||||
(None, None, None, None),
|
||||
### Disabled for now (given that it is not reliable enough yet)
|
||||
#(ID_CHECK, '&Check protocol\tF5','TODO',
|
||||
@@ -179,7 +182,49 @@ class MainWindow(wx.Frame):
|
||||
dialog.Destroy()
|
||||
return userProvidedFilename
|
||||
|
||||
# Event handlers:
|
||||
# Are we dropping a changed file?
|
||||
|
||||
def ConfirmLoss(self,text=None):
|
||||
"""
|
||||
Try to drop the current file. If it was changed, try to save
|
||||
(as)
|
||||
|
||||
Returns true after the user seems to be happy either way, false
|
||||
if we need to cancel this.
|
||||
"""
|
||||
if self.editor.GetChanged():
|
||||
# File changed, we need to confirm this
|
||||
title = "Unsaved changes"
|
||||
if text:
|
||||
title = "%s - " + title
|
||||
txt = "The protocol file '%s' has been modified.\n\n" % (self.filename)
|
||||
txt = txt + "Do you want to"
|
||||
txt = txt + " save your changes (Yes)"
|
||||
txt = txt + " or"
|
||||
txt = txt + " discard them (No)"
|
||||
txt = txt + "?"
|
||||
dialog = wx.MessageDialog(self,txt,title,wx.YES_NO | wx.CANCEL | wx.ICON_EXCLAMATION)
|
||||
result = dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
if result == wx.ID_NO:
|
||||
# Drop changes
|
||||
return True
|
||||
elif result == wx.ID_YES:
|
||||
# First save(as)!
|
||||
if self.OnSaveAs(None):
|
||||
# Succeeded, we can continue with the operation
|
||||
return True
|
||||
else:
|
||||
# Save did not succeed
|
||||
return False
|
||||
else:
|
||||
# Assume cancel (wx.ID_CANCEL) otherwise
|
||||
return False
|
||||
else:
|
||||
# File was not changed, so we can just proceed
|
||||
return True
|
||||
|
||||
# Event handlers
|
||||
|
||||
def OnAbout(self, event):
|
||||
dlg = About.AboutScyther(self)
|
||||
@@ -187,25 +232,36 @@ class MainWindow(wx.Frame):
|
||||
dlg.Destroy()
|
||||
|
||||
def OnExit(self, event):
|
||||
self.Close() # Close the main window.
|
||||
if self.ConfirmLoss("Exit"):
|
||||
self.Close() # Close the main window.
|
||||
return True
|
||||
return False
|
||||
|
||||
def OnSave(self, event):
|
||||
textfile = open(os.path.join(self.dirname, self.filename), 'w')
|
||||
textfile.write(self.editor.GetText())
|
||||
textfile.close()
|
||||
self.editor.SetSaved()
|
||||
return True
|
||||
|
||||
def OnOpen(self, event):
|
||||
if self.askUserForFilename(style=wx.OPEN,
|
||||
**self.defaultFileDialogOptions()):
|
||||
textfile = open(os.path.join(self.dirname, self.filename), 'r')
|
||||
self.editor.SetText(textfile.read())
|
||||
textfile.close()
|
||||
if self.ConfirmLoss("Open"):
|
||||
if self.askUserForFilename(style=wx.OPEN,
|
||||
**self.defaultFileDialogOptions()):
|
||||
textfile = open(os.path.join(self.dirname, self.filename), 'r')
|
||||
self.editor.SetText(textfile.read())
|
||||
textfile.close()
|
||||
self.editor.SetOpened()
|
||||
return True
|
||||
return False
|
||||
|
||||
def OnSaveAs(self, event):
|
||||
if self.askUserForFilename(defaultFile=self.filename, style=wx.SAVE,
|
||||
**self.defaultFileDialogOptions()):
|
||||
self.OnSave(event)
|
||||
os.chdir(self.dirname)
|
||||
return True
|
||||
return False
|
||||
|
||||
def RunScyther(self, mode):
|
||||
# Clear errors before verification
|
||||
@@ -220,8 +276,8 @@ class MainWindow(wx.Frame):
|
||||
def OnAutoVerify(self, event):
|
||||
self.RunScyther("autoverify")
|
||||
|
||||
def OnStatespace(self, event):
|
||||
self.RunScyther("statespace")
|
||||
def OnCharacterize(self, event):
|
||||
self.RunScyther("characterize")
|
||||
|
||||
def OnCheck(self, event):
|
||||
self.RunScyther("check")
|
||||
|
||||
@@ -34,11 +34,12 @@ class ScytherThread(threading.Thread):
|
||||
"""
|
||||
|
||||
# Override Thread's __init__ method to accept the parameters needed:
|
||||
def __init__ ( self, spdl, options="", callback=None ):
|
||||
def __init__ ( self, spdl, options="", callback=None, mode=None ):
|
||||
|
||||
self.spdl = spdl
|
||||
self.options = options
|
||||
self.callback = callback
|
||||
self.mode = mode
|
||||
threading.Thread.__init__ ( self )
|
||||
|
||||
def run(self):
|
||||
@@ -49,6 +50,17 @@ class ScytherThread(threading.Thread):
|
||||
if self.callback:
|
||||
wx.CallAfter(self.callback, scyther, claims, summary)
|
||||
|
||||
def claimFixViewOne(self,claims):
|
||||
if claims:
|
||||
for cl in claims:
|
||||
if len(cl.attacks) > 1:
|
||||
# Fix it such that by default, only the best attack is
|
||||
# shown, unless we are in characterize or check mode
|
||||
# TODO [X] [CC] make switch-dependant.
|
||||
if not self.mode in ["characterize","check"]:
|
||||
cl.attacks = [cl.attacks[-1]]
|
||||
|
||||
return claims
|
||||
|
||||
def claimResults(self):
|
||||
""" Convert spdl to result (using Scyther)
|
||||
@@ -68,6 +80,8 @@ class ScytherThread(threading.Thread):
|
||||
|
||||
summary = str(scyther)
|
||||
|
||||
claims = self.claimFixViewOne(claims)
|
||||
|
||||
return (scyther, claims, summary)
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -123,6 +137,7 @@ class AttackThread(threading.Thread):
|
||||
|
||||
def graphLine(txt):
|
||||
fp.write("\t%s;\n" % (txt))
|
||||
print txt # DEBUG ONLY
|
||||
|
||||
def setAttr(atxt,EdgeNodeDefAll=ALL):
|
||||
if EdgeNodeDefAll == ALL:
|
||||
@@ -139,6 +154,13 @@ class AttackThread(threading.Thread):
|
||||
return
|
||||
graphLine("%s [%s]" % (edge,atxt))
|
||||
|
||||
# Precompute font name
|
||||
# Set a font with sans
|
||||
# We only retrieve the name, so the size '9' here is
|
||||
# irrelevant.
|
||||
font = wx.Font(9,wx.SWISS,wx.NORMAL,wx.NORMAL)
|
||||
self.fontname = font.GetFaceName()
|
||||
|
||||
# write all graph lines but add layout modifiers
|
||||
for l in txt.splitlines():
|
||||
fp.write(l)
|
||||
@@ -151,23 +173,22 @@ class AttackThread(threading.Thread):
|
||||
#graphLine("nodesep=0.1")
|
||||
#graphLine("ranksep=0.001")
|
||||
#graphLine("mindist=0.1")
|
||||
if sys.platform.startswith("lin"):
|
||||
# For Linux, choose Helvetica
|
||||
# TODO
|
||||
# This is really a Mac font so it might not be
|
||||
# available. Still, it works better on my Ubuntu
|
||||
# than Verdana, and finding a good sans default for
|
||||
# linux seems problematic.
|
||||
setAttr("fontname=\"Helvetica\"")
|
||||
if sys.platform.startswith("mac"):
|
||||
# For Mac choose Helvetica
|
||||
setAttr("fontname=\"Helvetica\"")
|
||||
if sys.platform.startswith("win"):
|
||||
# For Windows choose Verdana
|
||||
setAttr("fontname=\"Verdana\"")
|
||||
|
||||
# Set fontname
|
||||
fontstring = "fontname=%s" % (self.fontname)
|
||||
setAttr(fontstring,EDGE)
|
||||
|
||||
# Stupid Mac <> Graphviz bug fix
|
||||
if (sys.platform.startswith("mac")) or (sys.platform.startswith("darwin")):
|
||||
# Note that dot on Mac cannot find the fonts by default,
|
||||
# and we have to set them accordingly.
|
||||
os.environ["DOTFONTPATH"]="~/Library/Fonts:/Library/Fonts:/System/Library/Fonts"
|
||||
|
||||
# Select font size
|
||||
if self.parent and self.parent.mainwin:
|
||||
fontsize = self.parent.mainwin.settings.fontsize
|
||||
setAttr("fontsize=%s" % fontsize)
|
||||
|
||||
#setAttr("height=\"0.1\"",NODE)
|
||||
#setAttr("width=\"1.0\"",NODE)
|
||||
#setAttr("margin=\"0.3,0.03\"",NODE)
|
||||
@@ -188,25 +209,29 @@ class AttackThread(threading.Thread):
|
||||
(fd2,fpname2) = Tempfile.tempcleaned(ext)
|
||||
f = os.fdopen(fd2,'w')
|
||||
|
||||
cmd = "dot -T%s" % (type)
|
||||
cmd = "dot -T%s >%s" % (type,fpname2)
|
||||
|
||||
# execute command
|
||||
cin,cout = os.popen2(cmd,'b')
|
||||
|
||||
self.writeGraph(attack.scytherDot,cin)
|
||||
cin.flush()
|
||||
cin.close()
|
||||
|
||||
for l in cout.read():
|
||||
f.write(l)
|
||||
|
||||
cout.close()
|
||||
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
# Print
|
||||
print fpname2
|
||||
raw_input()
|
||||
|
||||
# if this is done, store and report
|
||||
attack.filetype = type
|
||||
attack.file = fpname2 # this is where the file name is stored
|
||||
|
||||
# Maybe we should remove the temporary file... TODO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class VerificationWindow(wx.Dialog):
|
||||
@@ -344,7 +369,7 @@ class ResultWindow(wx.Frame):
|
||||
views += self.BuildClaim(grid,claims[index],index+1)
|
||||
|
||||
if views > 0:
|
||||
titlebar(7,"Classes",1)
|
||||
titlebar(7,"Patterns",1)
|
||||
|
||||
self.SetSizer(grid)
|
||||
self.Fit()
|
||||
@@ -480,7 +505,7 @@ class ScytherRun(object):
|
||||
# start the thread
|
||||
|
||||
self.verifywin.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
|
||||
t = ScytherThread(self.spdl, self.options, self.verificationDone)
|
||||
t = ScytherThread(self.spdl, self.options, self.verificationDone, self.mode)
|
||||
t.start()
|
||||
|
||||
# after verification, we proceed to the callback below...
|
||||
|
||||
@@ -150,13 +150,13 @@ class SettingsWindow(wx.Panel):
|
||||
tstr += "--check "
|
||||
elif mode == "autoverify":
|
||||
tstr += "--auto-claims "
|
||||
elif mode == "statespace":
|
||||
elif mode == "characterize":
|
||||
tstr += "--state-space "
|
||||
|
||||
# Anything else?
|
||||
if self.misc != "":
|
||||
tstr += " " + self.misc + " "
|
||||
|
||||
return tstr
|
||||
return str(tstr) # turn it into a str (might have been unicode weirdness)
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user