implementing database and VM error handling

added crypt and pbkdf2 libraries for password hashing

--HG--
branch : mung
This commit is contained in:
cecilkorik 2015-10-27 14:50:59 -06:00
parent d1bc58452c
commit a70737f90f
15 changed files with 8467 additions and 24 deletions

File diff suppressed because it is too large Load diff

View file

@ -8,3 +8,5 @@ RETURN #0

View file

@ -5,7 +5,40 @@ class builtin_functions(object):
@staticmethod
def serverlog(vm, args):
print "serverlog: %s" % (args,)
print "server_log: %s" % (args,)
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
@staticmethod
def create(vm, args):
pass
bi = builtin_functions()

View file

@ -97,8 +97,10 @@ class NoOp(CodeOp):
class GetProperty(CodeOp):
def execute(self, vm):
prop, obj = vm.pop(2)
vm.push(vm.db.get_property(obj, prop))
obj, prop = vm.pop(2)
objstore = vm.db.get_obj(obj)
val = objstore.get_prop(prop)
vm.push(val)
@staticmethod
@tokenparser
@ -118,8 +120,10 @@ class SetProperty(CodeOp):
class GetFile(CodeOp):
def execute(self, vm):
prop, obj = vm.pop(2)
vm.push(vm.db.get_file(obj, prop))
obj, prop = vm.pop(2)
objstore = vm.db.get_obj(obj)
val = objstore.get_file(prop)
vm.push(val)
class SetFile(CodeOp):
def execute(self, vm):

View file

@ -1,5 +1,6 @@
from parse import static_parser
from language import ObjRef
import errors
class DBObject(object):
@ -21,7 +22,7 @@ class DBObject(object):
return None
def get_property(self, prop):
def get_prop(self, prop):
if prop in self.props:
rv = self.props[prop]
else:
@ -30,7 +31,6 @@ class DBObject(object):
def add_func(self, name):
self.funcs.append(DBFunc(self.obj, name))
class DBFunc(object):
def __init__(self, objref, name):
@ -40,6 +40,7 @@ class DBFunc(object):
self.flags = ""
self.bytecode = []
self.code = ""
self.index = None
def compile(self, code):
try:
@ -72,11 +73,11 @@ class Database(object):
self.objects = []
def load(self):
raise NotImplementedError, "This function should be overridden by a derived class"
raise NotImplementedError("This function should be overridden by a derived class")
def checkpoint(self):
raise NotImplementedError, "This function should be overridden by a derived class"
raise NotImplementedError("This function should be overridden by a derived class")
def save(self):
raise NotImplementedError, "This function should be overridden by a derived class"
raise NotImplementedError("This function should be overridden by a derived class")
def bootstrap_minimal(self):
so = DBObject(ObjRef(0))
@ -84,7 +85,7 @@ class Database(object):
def set_property(self, obj, prop, val):
def set_prop(self, obj, prop, val):
o = self.get(obj)
o.set_property(prop, val)
@ -92,7 +93,7 @@ class Database(object):
o = self.get(obj)
o.set_file(fn, val)
def get_property(self, obj, prop):
def get_prop(self, obj, prop):
o = self.get(obj)
return o.get_property(prop)
@ -113,11 +114,11 @@ class Database(object):
def destroy(self, ref):
if ref.objnum >= len(self.objects) or ref.objnum < 0:
raise ValueError, "Invalid object number"
raise ValueError("Invalid object number")
obj = self.objects[ref.objnum]
if obj == None:
raise ValueError, "Object already destroyed"
raise ValueError("Object already destroyed")
for child in obj.children:
child.parent = ObjRef(-1)
@ -132,10 +133,24 @@ class Database(object):
if self.objects[i] != None:
i += 1
break
def get_obj(self, objref):
i = objnum
if i < len(self.objects):
self.objects[i:] = []
if i < 0:
raise errors.VMRuntimeError(errors.enum.E_INVIND)
elif i >= len(self.objects):
raise errors.VMRuntimeError(errors.enum.E_INVIND)
else:
o = self.objects[i]
if o == None:
raise errors.VMRuntimeError(errors.enum.E_INVIND)
else:
return o
def get(self, objref):
return self.objects[objref.objnum]

92
errors.py Normal file
View file

@ -0,0 +1,92 @@
from pyenum import pyenum
enum = pyenum()
enum.E_NONE = 0
enum.E_PERM = 1
enum.E_PROPNF = 2
enum.E_FUNCNF = 3
enum.E_FILENF = 4
enum.E_VARNF = 5
enum.E_INVARG = 6
enum.E_TICKS = 7
enum.E_SECONDS = 8
enum.E_MEMORY = 9
enum.E_IOERR = 10
enum.E_TYPE = 11
enum.E_ARGS = 12
enum.E_FLOAT = 13
enum.E_DIV = 14
enum.E_SYNTAX = 15
enum.E_UNICODE = 16
enum.E_MAXREC = 17
enum.E_PARSE = 18
enum.E_RANGE = 19
enum.E_INVIND = 20
enum.E_RECMOVE = 21
enum.E_NACC = 22
enum.E_INVOBJ = 23
enum.E_CONN = 24
enum.E_USER = 200
enum.E_USER1 = 201
enum.E_USER2 = 202
enum.E_USER3 = 203
enum.E_USER4 = 204
enum.E_USER5 = 205
enum.E_USER6 = 206
enum.E_USER7 = 207
enum.E_USER8 = 208
enum.E_USER9 = 209
enum.E_USER10 = 210
msgs = {
enum.E_NONE: "No error",
enum.E_PERM: "Permission denied",
enum.E_PROPNF: "Property not found",
enum.E_FUNCNF: "Function not found",
enum.E_FILENF: "File not found",
enum.E_VARNF: "Variable not found",
enum.E_INVARG: "Invalid argument",
enum.E_TICKS: "Out of ticks",
enum.E_SECONDS: "Out of seconds",
enum.E_MEMORY: "Out of memory",
enum.E_IOERR: "I/O error",
enum.E_TYPE: "Type mismatch",
enum.E_ARGS: "Incorrect number of arguments",
enum.E_FLOAT: "Floating point error",
enum.E_DIV: "Division by zero",
enum.E_SYNTAX: "Syntax error",
enum.E_UNICODE: "Invalid unicode character",
enum.E_MAXREC: "Maximum recursion depth reached",
enum.E_PARSE: "Unable to parse command",
enum.E_RANGE: "Index out of range",
enum.E_INVIND: "Invalid indirection",
enum.E_RECMOVE: "Recursive move",
enum.E_NACC: "Move refused by destination",
enum.E_INVOBJ: "Invalid object",
enum.E_CONN: "Connection error",
enum.E_USER: "User-defined error",
enum.E_USER1: "User-defined error 1",
enum.E_USER2: "User-defined error 2",
enum.E_USER3: "User-defined error 3",
enum.E_USER4: "User-defined error 4",
enum.E_USER5: "User-defined error 5",
enum.E_USER6: "User-defined error 6",
enum.E_USER7: "User-defined error 7",
enum.E_USER8: "User-defined error 8",
enum.E_USER9: "User-defined error 9",
enum.E_USER10: "User-defined error 10",
}
class VMRuntimeError(Exception):
def __init__(self, code, msg=None):
if msg == None and code in msgs:
msg = msgs[code]
elif msg == None:
msg = "Unknown error code"
Exception.__init__(self, msg)
self.errorcode = code

615
fcrypt.py Normal file
View file

@ -0,0 +1,615 @@
# fcrypt.py
"""Unix crypt(3) password hash algorithm.
This is a port to Python of the standard Unix password crypt function.
It's a single self-contained source file that works with any version
of Python from version 1.5 or higher. The code is based on Eric
Young's optimised crypt in C.
Python fcrypt is intended for users whose Python installation has not
had the crypt module enabled, or whose C library doesn't include the
crypt function. See the documentation for the Python crypt module for
more information:
http://www.python.org/doc/current/lib/module-crypt.html
An alternative Python crypt module that uses the MD5 algorithm and is
more secure than fcrypt is available from michal j wallace at:
http://www.sabren.net/code/python/crypt/index.php3
The crypt() function is a one-way hash function, intended to hide a
password such that the only way to find out the original password is
to guess values until you get a match. If you need to encrypt and
decrypt data, this is not the module for you.
There are at least two packages providing Python cryptography support:
M2Crypto at <http://www.pobox.org.sg/home/ngps/m2/>, and amkCrypto at
<http://www.amk.ca/python/code/crypto.html>.
Functions:
crypt() -- return hashed password
"""
__author__ = 'Carey Evans <careye@spamcop.net>'
__version__ = '1.3.1'
__date__ = '21 February 2004'
__credits__ = '''michal j wallace for inspiring me to write this.
Eric Young for the C code this module was copied from.'''
__all__ = ['crypt']
# Copyright (C) 2000, 2001, 2004 Carey Evans <careye@spamcop.net>
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear in
# supporting documentation.
#
# CAREY EVANS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
# EVENT SHALL CAREY EVANS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# Based on C code by Eric Young (eay@mincom.oz.au), which has the
# following copyright. Especially note condition 3, which imposes
# extra restrictions on top of the standard Python license used above.
#
# The fcrypt.c source is available from:
# ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/
# ----- BEGIN fcrypt.c LICENSE -----
#
# This library is free for commercial and non-commercial use as long as
# the following conditions are aheared to. The following conditions
# apply to all code found in this distribution, be it the RC4, RSA,
# lhash, DES, etc., code; not just the SSL code. The SSL documentation
# included with this distribution is covered by the same copyright terms
# except that the holder is Tim Hudson (tjh@mincom.oz.au).
#
# Copyright remains Eric Young's, and as such any Copyright notices in
# the code are not to be removed.
# If this package is used in a product, Eric Young should be given attribution
# as the author of the parts of the library used.
# This can be in the form of a textual message at program startup or
# in documentation (online or textual) provided with the package.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# "This product includes cryptographic software written by
# Eric Young (eay@mincom.oz.au)"
# The word 'cryptographic' can be left out if the rouines from the library
# being used are not cryptographic related :-).
# 4. If you include any Windows specific code (or a derivative thereof) from
# the apps directory (application code) you must include an acknowledgement:
# "This product includes software written by Tim Hudson (tjh@mincom.oz.au)"
#
# THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# The licence and distribution terms for any publically available version or
# derivative of this code cannot be changed. i.e. this code cannot simply be
# copied and put under another distribution licence
# [including the GNU Public Licence.]
#
# ----- END fcrypt.c LICENSE -----
import string, struct
_ITERATIONS = 16
_SPtrans = (
# nibble 0
[ 0x00820200, 0x00020000, 0x80800000, 0x80820200,
0x00800000, 0x80020200, 0x80020000, 0x80800000,
0x80020200, 0x00820200, 0x00820000, 0x80000200,
0x80800200, 0x00800000, 0x00000000, 0x80020000,
0x00020000, 0x80000000, 0x00800200, 0x00020200,
0x80820200, 0x00820000, 0x80000200, 0x00800200,
0x80000000, 0x00000200, 0x00020200, 0x80820000,
0x00000200, 0x80800200, 0x80820000, 0x00000000,
0x00000000, 0x80820200, 0x00800200, 0x80020000,
0x00820200, 0x00020000, 0x80000200, 0x00800200,
0x80820000, 0x00000200, 0x00020200, 0x80800000,
0x80020200, 0x80000000, 0x80800000, 0x00820000,
0x80820200, 0x00020200, 0x00820000, 0x80800200,
0x00800000, 0x80000200, 0x80020000, 0x00000000,
0x00020000, 0x00800000, 0x80800200, 0x00820200,
0x80000000, 0x80820000, 0x00000200, 0x80020200 ],
# nibble 1
[ 0x10042004, 0x00000000, 0x00042000, 0x10040000,
0x10000004, 0x00002004, 0x10002000, 0x00042000,
0x00002000, 0x10040004, 0x00000004, 0x10002000,
0x00040004, 0x10042000, 0x10040000, 0x00000004,
0x00040000, 0x10002004, 0x10040004, 0x00002000,
0x00042004, 0x10000000, 0x00000000, 0x00040004,
0x10002004, 0x00042004, 0x10042000, 0x10000004,
0x10000000, 0x00040000, 0x00002004, 0x10042004,
0x00040004, 0x10042000, 0x10002000, 0x00042004,
0x10042004, 0x00040004, 0x10000004, 0x00000000,
0x10000000, 0x00002004, 0x00040000, 0x10040004,
0x00002000, 0x10000000, 0x00042004, 0x10002004,
0x10042000, 0x00002000, 0x00000000, 0x10000004,
0x00000004, 0x10042004, 0x00042000, 0x10040000,
0x10040004, 0x00040000, 0x00002004, 0x10002000,
0x10002004, 0x00000004, 0x10040000, 0x00042000 ],
# nibble 2
[ 0x41000000, 0x01010040, 0x00000040, 0x41000040,
0x40010000, 0x01000000, 0x41000040, 0x00010040,
0x01000040, 0x00010000, 0x01010000, 0x40000000,
0x41010040, 0x40000040, 0x40000000, 0x41010000,
0x00000000, 0x40010000, 0x01010040, 0x00000040,
0x40000040, 0x41010040, 0x00010000, 0x41000000,
0x41010000, 0x01000040, 0x40010040, 0x01010000,
0x00010040, 0x00000000, 0x01000000, 0x40010040,
0x01010040, 0x00000040, 0x40000000, 0x00010000,
0x40000040, 0x40010000, 0x01010000, 0x41000040,
0x00000000, 0x01010040, 0x00010040, 0x41010000,
0x40010000, 0x01000000, 0x41010040, 0x40000000,
0x40010040, 0x41000000, 0x01000000, 0x41010040,
0x00010000, 0x01000040, 0x41000040, 0x00010040,
0x01000040, 0x00000000, 0x41010000, 0x40000040,
0x41000000, 0x40010040, 0x00000040, 0x01010000 ],
# nibble 3
[ 0x00100402, 0x04000400, 0x00000002, 0x04100402,
0x00000000, 0x04100000, 0x04000402, 0x00100002,
0x04100400, 0x04000002, 0x04000000, 0x00000402,
0x04000002, 0x00100402, 0x00100000, 0x04000000,
0x04100002, 0x00100400, 0x00000400, 0x00000002,
0x00100400, 0x04000402, 0x04100000, 0x00000400,
0x00000402, 0x00000000, 0x00100002, 0x04100400,
0x04000400, 0x04100002, 0x04100402, 0x00100000,
0x04100002, 0x00000402, 0x00100000, 0x04000002,
0x00100400, 0x04000400, 0x00000002, 0x04100000,
0x04000402, 0x00000000, 0x00000400, 0x00100002,
0x00000000, 0x04100002, 0x04100400, 0x00000400,
0x04000000, 0x04100402, 0x00100402, 0x00100000,
0x04100402, 0x00000002, 0x04000400, 0x00100402,
0x00100002, 0x00100400, 0x04100000, 0x04000402,
0x00000402, 0x04000000, 0x04000002, 0x04100400 ],
# nibble 4
[ 0x02000000, 0x00004000, 0x00000100, 0x02004108,
0x02004008, 0x02000100, 0x00004108, 0x02004000,
0x00004000, 0x00000008, 0x02000008, 0x00004100,
0x02000108, 0x02004008, 0x02004100, 0x00000000,
0x00004100, 0x02000000, 0x00004008, 0x00000108,
0x02000100, 0x00004108, 0x00000000, 0x02000008,
0x00000008, 0x02000108, 0x02004108, 0x00004008,
0x02004000, 0x00000100, 0x00000108, 0x02004100,
0x02004100, 0x02000108, 0x00004008, 0x02004000,
0x00004000, 0x00000008, 0x02000008, 0x02000100,
0x02000000, 0x00004100, 0x02004108, 0x00000000,
0x00004108, 0x02000000, 0x00000100, 0x00004008,
0x02000108, 0x00000100, 0x00000000, 0x02004108,
0x02004008, 0x02004100, 0x00000108, 0x00004000,
0x00004100, 0x02004008, 0x02000100, 0x00000108,
0x00000008, 0x00004108, 0x02004000, 0x02000008 ],
# nibble 5
[ 0x20000010, 0x00080010, 0x00000000, 0x20080800,
0x00080010, 0x00000800, 0x20000810, 0x00080000,
0x00000810, 0x20080810, 0x00080800, 0x20000000,
0x20000800, 0x20000010, 0x20080000, 0x00080810,
0x00080000, 0x20000810, 0x20080010, 0x00000000,
0x00000800, 0x00000010, 0x20080800, 0x20080010,
0x20080810, 0x20080000, 0x20000000, 0x00000810,
0x00000010, 0x00080800, 0x00080810, 0x20000800,
0x00000810, 0x20000000, 0x20000800, 0x00080810,
0x20080800, 0x00080010, 0x00000000, 0x20000800,
0x20000000, 0x00000800, 0x20080010, 0x00080000,
0x00080010, 0x20080810, 0x00080800, 0x00000010,
0x20080810, 0x00080800, 0x00080000, 0x20000810,
0x20000010, 0x20080000, 0x00080810, 0x00000000,
0x00000800, 0x20000010, 0x20000810, 0x20080800,
0x20080000, 0x00000810, 0x00000010, 0x20080010 ],
# nibble 6
[ 0x00001000, 0x00000080, 0x00400080, 0x00400001,
0x00401081, 0x00001001, 0x00001080, 0x00000000,
0x00400000, 0x00400081, 0x00000081, 0x00401000,
0x00000001, 0x00401080, 0x00401000, 0x00000081,
0x00400081, 0x00001000, 0x00001001, 0x00401081,
0x00000000, 0x00400080, 0x00400001, 0x00001080,
0x00401001, 0x00001081, 0x00401080, 0x00000001,
0x00001081, 0x00401001, 0x00000080, 0x00400000,
0x00001081, 0x00401000, 0x00401001, 0x00000081,
0x00001000, 0x00000080, 0x00400000, 0x00401001,
0x00400081, 0x00001081, 0x00001080, 0x00000000,
0x00000080, 0x00400001, 0x00000001, 0x00400080,
0x00000000, 0x00400081, 0x00400080, 0x00001080,
0x00000081, 0x00001000, 0x00401081, 0x00400000,
0x00401080, 0x00000001, 0x00001001, 0x00401081,
0x00400001, 0x00401080, 0x00401000, 0x00001001 ],
# nibble 7
[ 0x08200020, 0x08208000, 0x00008020, 0x00000000,
0x08008000, 0x00200020, 0x08200000, 0x08208020,
0x00000020, 0x08000000, 0x00208000, 0x00008020,
0x00208020, 0x08008020, 0x08000020, 0x08200000,
0x00008000, 0x00208020, 0x00200020, 0x08008000,
0x08208020, 0x08000020, 0x00000000, 0x00208000,
0x08000000, 0x00200000, 0x08008020, 0x08200020,
0x00200000, 0x00008000, 0x08208000, 0x00000020,
0x00200000, 0x00008000, 0x08000020, 0x08208020,
0x00008020, 0x08000000, 0x00000000, 0x00208000,
0x08200020, 0x08008020, 0x08008000, 0x00200020,
0x08208000, 0x00000020, 0x00200020, 0x08008000,
0x08208020, 0x00200000, 0x08200000, 0x08000020,
0x00208000, 0x00008020, 0x08008020, 0x08200000,
0x00000020, 0x08208000, 0x00208020, 0x00000000,
0x08000000, 0x08200020, 0x00008000, 0x00208020 ] )
_skb = (
# for C bits (numbered as per FIPS 46) 1 2 3 4 5 6
[ 0x00000000, 0x00000010, 0x20000000, 0x20000010,
0x00010000, 0x00010010, 0x20010000, 0x20010010,
0x00000800, 0x00000810, 0x20000800, 0x20000810,
0x00010800, 0x00010810, 0x20010800, 0x20010810,
0x00000020, 0x00000030, 0x20000020, 0x20000030,
0x00010020, 0x00010030, 0x20010020, 0x20010030,
0x00000820, 0x00000830, 0x20000820, 0x20000830,
0x00010820, 0x00010830, 0x20010820, 0x20010830,
0x00080000, 0x00080010, 0x20080000, 0x20080010,
0x00090000, 0x00090010, 0x20090000, 0x20090010,
0x00080800, 0x00080810, 0x20080800, 0x20080810,
0x00090800, 0x00090810, 0x20090800, 0x20090810,
0x00080020, 0x00080030, 0x20080020, 0x20080030,
0x00090020, 0x00090030, 0x20090020, 0x20090030,
0x00080820, 0x00080830, 0x20080820, 0x20080830,
0x00090820, 0x00090830, 0x20090820, 0x20090830 ],
# for C bits (numbered as per FIPS 46) 7 8 10 11 12 13
[ 0x00000000, 0x02000000, 0x00002000, 0x02002000,
0x00200000, 0x02200000, 0x00202000, 0x02202000,
0x00000004, 0x02000004, 0x00002004, 0x02002004,
0x00200004, 0x02200004, 0x00202004, 0x02202004,
0x00000400, 0x02000400, 0x00002400, 0x02002400,
0x00200400, 0x02200400, 0x00202400, 0x02202400,
0x00000404, 0x02000404, 0x00002404, 0x02002404,
0x00200404, 0x02200404, 0x00202404, 0x02202404,
0x10000000, 0x12000000, 0x10002000, 0x12002000,
0x10200000, 0x12200000, 0x10202000, 0x12202000,
0x10000004, 0x12000004, 0x10002004, 0x12002004,
0x10200004, 0x12200004, 0x10202004, 0x12202004,
0x10000400, 0x12000400, 0x10002400, 0x12002400,
0x10200400, 0x12200400, 0x10202400, 0x12202400,
0x10000404, 0x12000404, 0x10002404, 0x12002404,
0x10200404, 0x12200404, 0x10202404, 0x12202404 ],
# for C bits (numbered as per FIPS 46) 14 15 16 17 19 20
[ 0x00000000, 0x00000001, 0x00040000, 0x00040001,
0x01000000, 0x01000001, 0x01040000, 0x01040001,
0x00000002, 0x00000003, 0x00040002, 0x00040003,
0x01000002, 0x01000003, 0x01040002, 0x01040003,
0x00000200, 0x00000201, 0x00040200, 0x00040201,
0x01000200, 0x01000201, 0x01040200, 0x01040201,
0x00000202, 0x00000203, 0x00040202, 0x00040203,
0x01000202, 0x01000203, 0x01040202, 0x01040203,
0x08000000, 0x08000001, 0x08040000, 0x08040001,
0x09000000, 0x09000001, 0x09040000, 0x09040001,
0x08000002, 0x08000003, 0x08040002, 0x08040003,
0x09000002, 0x09000003, 0x09040002, 0x09040003,
0x08000200, 0x08000201, 0x08040200, 0x08040201,
0x09000200, 0x09000201, 0x09040200, 0x09040201,
0x08000202, 0x08000203, 0x08040202, 0x08040203,
0x09000202, 0x09000203, 0x09040202, 0x09040203 ],
# for C bits (numbered as per FIPS 46) 21 23 24 26 27 28
[ 0x00000000, 0x00100000, 0x00000100, 0x00100100,
0x00000008, 0x00100008, 0x00000108, 0x00100108,
0x00001000, 0x00101000, 0x00001100, 0x00101100,
0x00001008, 0x00101008, 0x00001108, 0x00101108,
0x04000000, 0x04100000, 0x04000100, 0x04100100,
0x04000008, 0x04100008, 0x04000108, 0x04100108,
0x04001000, 0x04101000, 0x04001100, 0x04101100,
0x04001008, 0x04101008, 0x04001108, 0x04101108,
0x00020000, 0x00120000, 0x00020100, 0x00120100,
0x00020008, 0x00120008, 0x00020108, 0x00120108,
0x00021000, 0x00121000, 0x00021100, 0x00121100,
0x00021008, 0x00121008, 0x00021108, 0x00121108,
0x04020000, 0x04120000, 0x04020100, 0x04120100,
0x04020008, 0x04120008, 0x04020108, 0x04120108,
0x04021000, 0x04121000, 0x04021100, 0x04121100,
0x04021008, 0x04121008, 0x04021108, 0x04121108 ],
# for D bits (numbered as per FIPS 46) 1 2 3 4 5 6
[ 0x00000000, 0x10000000, 0x00010000, 0x10010000,
0x00000004, 0x10000004, 0x00010004, 0x10010004,
0x20000000, 0x30000000, 0x20010000, 0x30010000,
0x20000004, 0x30000004, 0x20010004, 0x30010004,
0x00100000, 0x10100000, 0x00110000, 0x10110000,
0x00100004, 0x10100004, 0x00110004, 0x10110004,
0x20100000, 0x30100000, 0x20110000, 0x30110000,
0x20100004, 0x30100004, 0x20110004, 0x30110004,
0x00001000, 0x10001000, 0x00011000, 0x10011000,
0x00001004, 0x10001004, 0x00011004, 0x10011004,
0x20001000, 0x30001000, 0x20011000, 0x30011000,
0x20001004, 0x30001004, 0x20011004, 0x30011004,
0x00101000, 0x10101000, 0x00111000, 0x10111000,
0x00101004, 0x10101004, 0x00111004, 0x10111004,
0x20101000, 0x30101000, 0x20111000, 0x30111000,
0x20101004, 0x30101004, 0x20111004, 0x30111004 ],
# for D bits (numbered as per FIPS 46) 8 9 11 12 13 14
[ 0x00000000, 0x08000000, 0x00000008, 0x08000008,
0x00000400, 0x08000400, 0x00000408, 0x08000408,
0x00020000, 0x08020000, 0x00020008, 0x08020008,
0x00020400, 0x08020400, 0x00020408, 0x08020408,
0x00000001, 0x08000001, 0x00000009, 0x08000009,
0x00000401, 0x08000401, 0x00000409, 0x08000409,
0x00020001, 0x08020001, 0x00020009, 0x08020009,
0x00020401, 0x08020401, 0x00020409, 0x08020409,
0x02000000, 0x0A000000, 0x02000008, 0x0A000008,
0x02000400, 0x0A000400, 0x02000408, 0x0A000408,
0x02020000, 0x0A020000, 0x02020008, 0x0A020008,
0x02020400, 0x0A020400, 0x02020408, 0x0A020408,
0x02000001, 0x0A000001, 0x02000009, 0x0A000009,
0x02000401, 0x0A000401, 0x02000409, 0x0A000409,
0x02020001, 0x0A020001, 0x02020009, 0x0A020009,
0x02020401, 0x0A020401, 0x02020409, 0x0A020409 ],
# for D bits (numbered as per FIPS 46) 16 17 18 19 20 21
[ 0x00000000, 0x00000100, 0x00080000, 0x00080100,
0x01000000, 0x01000100, 0x01080000, 0x01080100,
0x00000010, 0x00000110, 0x00080010, 0x00080110,
0x01000010, 0x01000110, 0x01080010, 0x01080110,
0x00200000, 0x00200100, 0x00280000, 0x00280100,
0x01200000, 0x01200100, 0x01280000, 0x01280100,
0x00200010, 0x00200110, 0x00280010, 0x00280110,
0x01200010, 0x01200110, 0x01280010, 0x01280110,
0x00000200, 0x00000300, 0x00080200, 0x00080300,
0x01000200, 0x01000300, 0x01080200, 0x01080300,
0x00000210, 0x00000310, 0x00080210, 0x00080310,
0x01000210, 0x01000310, 0x01080210, 0x01080310,
0x00200200, 0x00200300, 0x00280200, 0x00280300,
0x01200200, 0x01200300, 0x01280200, 0x01280300,
0x00200210, 0x00200310, 0x00280210, 0x00280310,
0x01200210, 0x01200310, 0x01280210, 0x01280310 ],
# for D bits (numbered as per FIPS 46) 22 23 24 25 27 28
[ 0x00000000, 0x04000000, 0x00040000, 0x04040000,
0x00000002, 0x04000002, 0x00040002, 0x04040002,
0x00002000, 0x04002000, 0x00042000, 0x04042000,
0x00002002, 0x04002002, 0x00042002, 0x04042002,
0x00000020, 0x04000020, 0x00040020, 0x04040020,
0x00000022, 0x04000022, 0x00040022, 0x04040022,
0x00002020, 0x04002020, 0x00042020, 0x04042020,
0x00002022, 0x04002022, 0x00042022, 0x04042022,
0x00000800, 0x04000800, 0x00040800, 0x04040800,
0x00000802, 0x04000802, 0x00040802, 0x04040802,
0x00002800, 0x04002800, 0x00042800, 0x04042800,
0x00002802, 0x04002802, 0x00042802, 0x04042802,
0x00000820, 0x04000820, 0x00040820, 0x04040820,
0x00000822, 0x04000822, 0x00040822, 0x04040822,
0x00002820, 0x04002820, 0x00042820, 0x04042820,
0x00002822, 0x04002822, 0x00042822, 0x04042822 ] )
_shifts2 = (0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0)
_con_salt = [
0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,
0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,
0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,
0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01,
0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A,
0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,
0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,
0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,
0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24,
0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,
0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,
0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,
0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44 ]
_cov_2char = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
def _HPERM_OP(a):
"""Clever bit manipulation."""
t = ((a << 18) ^ a) & 0xcccc0000
return a ^ t ^ ((t >> 18) & 0x3fff)
def _PERM_OP(a,b,n,m):
"""Cleverer bit manipulation."""
t = ((a >> n) ^ b) & m
b = b ^ t
a = a ^ (t << n)
return a,b
def _set_key(password):
"""Generate DES key schedule from ASCII password."""
c,d = struct.unpack('<ii', password)
c = (c & 0x7f7f7f7f) << 1
d = (d & 0x7f7f7f7f) << 1
d,c = _PERM_OP(d,c,4,0x0f0f0f0f)
c = _HPERM_OP(c)
d = _HPERM_OP(d)
d,c = _PERM_OP(d,c,1,0x55555555)
c,d = _PERM_OP(c,d,8,0x00ff00ff)
d,c = _PERM_OP(d,c,1,0x55555555)
# Any sign-extended bits are masked off.
d = (((d & 0x000000ff) << 16) | (d & 0x0000ff00) |
((d & 0x00ff0000) >> 16) | ((c >> 4) & 0x0f000000))
c = c & 0x0fffffff
# Copy globals into local variables for loop.
shifts2 = _shifts2
skbc0, skbc1, skbc2, skbc3, skbd0, skbd1, skbd2, skbd3 = _skb
k = [0] * (_ITERATIONS * 2)
for i in range(_ITERATIONS):
# Only operates on top 28 bits.
if shifts2[i]:
c = (c >> 2) | (c << 26)
d = (d >> 2) | (d << 26)
else:
c = (c >> 1) | (c << 27)
d = (d >> 1) | (d << 27)
c = c & 0x0fffffff
d = d & 0x0fffffff
s = ( skbc0[ c & 0x3f ] |
skbc1[((c>> 6) & 0x03) | ((c>> 7) & 0x3c)] |
skbc2[((c>>13) & 0x0f) | ((c>>14) & 0x30)] |
skbc3[((c>>20) & 0x01) |
((c>>21) & 0x06) | ((c>>22) & 0x38)] )
t = ( skbd0[ d & 0x3f ] |
skbd1[((d>> 7) & 0x03) | ((d>> 8) & 0x3c)] |
skbd2[((d>>15) & 0x3f) ] |
skbd3[((d>>21) & 0x0f) | ((d>>22) & 0x30)] )
k[2*i] = ((t << 16) | (s & 0x0000ffff)) & 0xffffffff
s = (s >> 16) | (t & 0xffff0000)
# Top bit of s may be 1.
s = (s << 4) | ((s >> 28) & 0x0f)
k[2*i + 1] = s & 0xffffffff
return k
def _body(ks, E0, E1):
"""Use the key schedule ks and salt E0, E1 to create the password hash."""
# Copy global variable into locals for loop.
SP0, SP1, SP2, SP3, SP4, SP5, SP6, SP7 = _SPtrans
inner = range(0, _ITERATIONS*2, 2)
l = r = 0
for j in range(25):
l,r = r,l
for i in inner:
t = r ^ ((r >> 16) & 0xffff)
u = t & E0
t = t & E1
u = u ^ (u << 16) ^ r ^ ks[i]
t = t ^ (t << 16) ^ r ^ ks[i+1]
t = ((t >> 4) & 0x0fffffff) | (t << 28)
l,r = r,(SP1[(t ) & 0x3f] ^ SP3[(t>> 8) & 0x3f] ^
SP5[(t>>16) & 0x3f] ^ SP7[(t>>24) & 0x3f] ^
SP0[(u ) & 0x3f] ^ SP2[(u>> 8) & 0x3f] ^
SP4[(u>>16) & 0x3f] ^ SP6[(u>>24) & 0x3f] ^ l)
l = ((l >> 1) & 0x7fffffff) | ((l & 0x1) << 31)
r = ((r >> 1) & 0x7fffffff) | ((r & 0x1) << 31)
r,l = _PERM_OP(r, l, 1, 0x55555555)
l,r = _PERM_OP(l, r, 8, 0x00ff00ff)
r,l = _PERM_OP(r, l, 2, 0x33333333)
l,r = _PERM_OP(l, r, 16, 0x0000ffff)
r,l = _PERM_OP(r, l, 4, 0x0f0f0f0f)
return l,r
def crypt(password, salt):
"""Generate an encrypted hash from the passed password. If the password
is longer than eight characters, only the first eight will be used.
The first two characters of the salt are used to modify the encryption
algorithm used to generate in the hash in one of 4096 different ways.
The characters for the salt should be upper- and lower-case letters A
to Z, digits 0 to 9, '.' and '/'.
The returned hash begins with the two characters of the salt, and
should be passed as the salt to verify the password.
Example:
>>> from fcrypt import crypt
>>> password = 'AlOtBsOl'
>>> salt = 'cE'
>>> hash = crypt(password, salt)
>>> hash
'cEpWz5IUCShqM'
>>> crypt(password, hash) == hash
1
>>> crypt('IaLaIoK', hash) == hash
0
In practice, you would read the password using something like the
getpass module, and generate the salt randomly:
>>> import random, string
>>> saltchars = string.letters + string.digits + './'
>>> salt = random.choice(saltchars) + random.choice(saltchars)
Note that other ASCII characters are accepted in the salt, but the
results may not be the same as other versions of crypt. In
particular, '_', '$1' and '$2' do not select alternative hash
algorithms such as the extended passwords, MD5 crypt and Blowfish
crypt supported by the OpenBSD C library.
"""
# Extract the salt.
if len(salt) == 0:
salt = 'AA'
elif len(salt) == 1:
salt = salt + 'A'
Eswap0 = _con_salt[ord(salt[0]) & 0x7f]
Eswap1 = _con_salt[ord(salt[1]) & 0x7f] << 4
# Generate the key and use it to apply the encryption.
ks = _set_key((password + '\0\0\0\0\0\0\0\0')[:8])
o1, o2 = _body(ks, Eswap0, Eswap1)
# Extract 24-bit subsets of result with bytes reversed.
t1 = (o1 << 16 & 0xff0000) | (o1 & 0xff00) | (o1 >> 16 & 0xff)
t2 = (o1 >> 8 & 0xff0000) | (o2 << 8 & 0xff00) | (o2 >> 8 & 0xff)
t3 = (o2 & 0xff0000) | (o2 >> 16 & 0xff00)
# Extract 6-bit subsets.
r = [ t1 >> 18 & 0x3f, t1 >> 12 & 0x3f, t1 >> 6 & 0x3f, t1 & 0x3f,
t2 >> 18 & 0x3f, t2 >> 12 & 0x3f, t2 >> 6 & 0x3f, t2 & 0x3f,
t3 >> 18 & 0x3f, t3 >> 12 & 0x3f, t3 >> 6 & 0x3f ]
# Convert to characters.
for i in range(len(r)):
r[i] = _cov_2char[r[i]]
return salt[:2] + string.join(r, '')
def _test():
"""Run doctest on fcrypt module."""
import doctest, fcrypt
return doctest.testmod(fcrypt)
if __name__ == '__main__':
_test()

View file

@ -1,3 +1,272 @@
DIFFERENCES FROM LAMBDAMOO
~~~~~~~~~~~~~~~~~~~~~~~~~~
The idea is that most things should be marginally similar, but there is no guarantee of backwards
compatibility. In fact, it is intended that some of MOO's most adorable anachronisms will be
updated to more modern techniques and terminology. This will by neccessity break compatibility in
many situations.
It is likely that the only way to port code or objects from LambdaMOO will involve an intermediate
translation step, which is beyond the scope of this project right now. The best I can offer is that
said translation step SHOULD BE possible, and hopefully allows nearly 100% of code to be portable,
at least in theory...
Key differences from LambdaMOO include:
* The list of built-in functions has changed; some renamed, some new, some removed.
* "Verbs" will be referred to as "functions", or "func" when an abbreviated form is required.
(yes, I know this is sad. I have fond memories of "programming verbs" too)
* "Permissions" in the sense of +r or "rxd" have been renamed to "flags", as their
meaning and usage has expanded significantly.
* The "+w" world-writable flag has been removed, because it is absolutely stupid and should
never be used anyway. In exchange, there is now a "+e" flag supporting extended permissions
which allows permissions to be extended to larger groups.
* Pre-emptive multitasking is now a plausible, albeit unimplemented, option.
* Various functionality that was provided through patches and extensions to the LambdaMOO
server will now have functional equivalents made available through built-ins.
* Files are now a built-in, first-class feature that works similarly to properties, however
they allow data to be stored on disk, rather than in memory.
* Binary data (raw bytes) will be a separate and distinct datatype from regular strings.
* Strings will be assumed to be UTF-8 at all times. To index or manage them as raw byte
strings, they will need to be converted to the bytes datatype.
* UTF-8 strings will be permitted for pretty much everything, including property and function
names, output to users, and it will be expected as user input as well.
* notify, tell, and announce will quite possibly be given more contemporary names.
* Memory usage will be monitored on a task, user, and property basis and reasonable limits
will be enforced, in the same way that object quotas are limited for users, and in the same
way that seconds/tick usage are limited for tasks. However avoiding the task memory limit
will not be as simple as calling suspend(0) :)
* The meaning of +r has been reversed. It now means "restricted". Globally readable is the
default state for all objects, properties, files and functions.
* Built-in properties like "wizard" are gone, replaced by various built-in functions.
* The characters " : and ; are no longer hardcoded to say, emote, and eval respectively.
OBJECT FLAGS
~~~~~~~~~~~~
f = fertile
Fertile objects can have children created by anyone. Normally, only the owner (or a wizard)
can use this object as a parent for another object. +f extends this ability to everyone.
If desired, more granular control can be achieved through the +e extended permissions.
e = extended permissions
Normally, an object has 1 owner, no more. The owner (and any wizards) are able to modify
the object and all its attributes. This is adequate in most cases, however, an extended
permissions system can be enabled through this flag that allows a more complicated but
robust way of assigning more granular permissions across multiple users. The owner (and any
wizards) will still maintain full access however.
This is not enabled by default because it's generally unnecessary and can be confusing.
r = restricted
This restricts the visibility of several of the object's attributes to be limited to the
owner and wizards. The meaning of restriction in this case is actually quite limited.
Other users are only prevented from viewing the lists of locally-defined properties,
functions, and files, or any of the attributes of those properties, functions, and files.
It ONLY applies to the lists, flags and attributes however. Notably, it does NOT prevent
access to the CONTENT. The value of a property, the contents of a file, or the source code
of a function are all fully accessible on a restricted object, provided the property, file
or function are themselves not restricted. Additionally, some flags and attributes can be
inferred by various methods of probing, especially if the object has children which are not
+r. Functions defined on this object can also still be called simply by guessing their
names, unless the function is flagged +y. One countermeasure provided to prevent users from
simply brute-force fishing for valid names is that any attempt to access an unknown name
on a +r object will result in E_PERM instead of E_PROPNF, E_FUNCNF, etc. This makes it
impossible for a fisher to know whether the name is actually valid and restricted by its
own +r flag, or whether the name is simply invalid.
PROPERTY FLAGS
~~~~~~~~~~~~~~
c = copy value to children
Normally a child object has a "cleared" property, which means the value is inherited from
the parent. If the value on the parent changes, so do all the "cleared" properties on the
children. However, with the +c flag, the value will be copied to the child object at the
time of creation. Further changes to the parent's value will have no effect on the child.
It is possible to "clear" a +c property, however all this will do is re-copy the parent's
value at that moment. Even once "cleared", further changes on the parent will still not
propagate to the child's properties. +c properties are essentially "copy-on-create"
instead of the default "copy-on-write".
Mutually exclusive with +s and completely irrelevant with +h
d = direct access / dynamic
This property is excluded from the the usual behavior of getter/setter functions.
Normally, if an appropriate getter/setter function is available, a call to that function
will be transparently substituted instead of a direct assignment. The +d flag overriddes
that behavior.
h = hidden / private
This property ONLY exists on the object itself, children will not contain this property.
The same property can be added to the children as if it doesn't exist, because it doesn't.
Setting this flag makes +c and +s meaningless, as no such child property exists.
s = shared / static
With this flag, the property inherited by children will all share the same value with the
parent. Setting the value on the parent will also cause the value to change on all the
children. Less obviously, setting the value on one of the children will also change the
value on all other children and on the parent as well. The same value is shared among all.
Note that in combination with the +o flag, this can allow the property to be freely
modified by users other than the owner, which may or may not be the expected behavior and
should be approached with caution. Also note that the +s and +o flags, in combination with
any object or child that has the +f flag is essentially allowing a world-writable property.
This should be approached with even more extreme caution, and is a great reason to avoid
ever setting +s in combination with +o in the first place.
o = transfer ownership
Normally, the property inherited by an object's children will still be owned by the same
user that owns the property on the parent. If the +o flag is set, the inherited property
will instead be owned by the same user that owns the child object.
e = extended permissions
Normally, a function has 1 owner, no more. The owner (and any wizards) are able to modify
the property and all its attributes. This is adequate in most cases, however, an extended
permissions system can be enabled through this flag that allows a more complicated but
robust way of assigning more granular permissions across multiple users. The owner (and any
wizards) will still maintain full access however.
This is not enabled by default because it's generally unnecessary and can be confusing.
FUNCTION FLAGS
~~~~~~~~~~
a = access restricted
Functions with this flag cannot be overridden on child objects, even by the owner of the
child object. This is checked and enforced on creation, as well as on chparent. Notable
exceptions are:
* The function can be overridden if the creator can also edit the code on the
a-flagged parent function
* Wizards are obviously exempt for the above reason
* Once created, the function can be chowned freely, even if the new owner does not have
the neccessary privileges to create such a function.
* Additionally, if the overriding function does not ALSO have an +a flag, then children
of THAT object can also freely override the function without restriction.
r = public readable
Functions with this flag have public source code that is visible to everyone
x = function-callable execution allowed
If this function is called from another function, the interpreter will ensure this flag
is set. If not, an E_FUNCNF exception will be raised.
c = command-line execution allowed
The command-line processor will include this function in its search as it attempts to match
the input with an appropriate command-line function.
e = extended permissions
Normally, a function has 1 owner, no more. The owner (and any wizards) are able to modify
the function and all its attributes. This is adequate in most cases, however, an extended
permissions system can be enabled through this flag that allows a more complicated but
robust way of assigning more granular permissions across multiple users. The owner (and any
wizards) will still maintain full access however.
This is not enabled by default because it's generally unnecessary and can be confusing.
m = legacy command-line argument matching (dobj/prepstr/iobj, etc)
This uses the LambdaMOO-style argument matching.
y = owner-only
This function can only be called by the owner (or a wizard) or by someone entitled to do so
through +e. Attempts to call the function by other players will fail with E_PERM.
p = pre-emptive multitasking
This is a placeholder for future plans to allow pre-emptive multitasking on an opt-in
basis. This will allow the virtual machine to decide (based on resource availability) when
the function can be paused, instead of relying on a specific tick limit and expecting the
process to cooperatively decide to suspend itself before that limit is reached.
s = set permissions (WIZARD ONLY)
Normally, a function executes with the permissions of the person who wrote the code. This
flag specifies that the code should instead execute with the permissions of the player
who initiated the command. This is an alternative to using set_task_perms boilerplate.
u = unlimited execution time (WIZARD ONLY)
This flag allows a function (and all functions it calls) to run continuously, without any
risk of the function being pre-empted by other processes or any need to suspend, no matter
how long it takes to run. This flag should be enabled with EXTREME caution, as a badly-
behaved process running +u can completely monopolize the server, preventing all input or
new connections from being processed.
The main purpose of this flag is to allow "absolutely critical" functions to run without
interruption. Such functions should be few and far between, and very specific and limited
in what they actually do. It is imperative that the +u function takes abundant care with
the inputs it accepts and the functions it calls, as abuse can be very easy. For example by
repeatedly calling the function in a loop and passing an enormous list as an argument.
f = fail silently
Exceptions are suppressed and supplied as the return value (if callable.)
Command-line functions will simply exit silently if an exception is encountered.
FILE FLAGS
~~~~~~~~~~
Files are a first-class data storage feature that can be used similarly to properties in many
respects. However they do not use inheritance, and they may be very slightly slower. Their main
advantage is mostly that they are not stored in memory, making them suitable for storing very
large data. They also support additional features for partial, incremental loading and random
access that properties do not.
At their simplest and most straightforward, files can be accessed with an exclamation mark "!"
using the syntax #789!filename
More specific methods of accessing file data are documented in the built-in functions.
b = binary mode
A file in binary mode may only contain the bytes datatype, and will always provide a bytes
datatype when read. The actual file stored on disk will match the exact bytes written to
or read from the file, which can be useful when the file either comes from or is intended
to be used by another program.
A file must be flagged for binary mode in order to enable several types of file operations,
such as random access.
Note that setting a file +b will delete all existing content, UNLESS the content is already
of type "bytes". If the existing content was already bytes, then it is populated into the
file as-is. All other datatypes (even strings or lists containing only bytes) will be
deleted and the new +b file will be empty. When setting a file +b, the data it contains
should be converted to bytes explicitly first if you wish to keep it.
Conversely, -b will cause the contents of the file on disk to change, as the bytes data is
converted into the internal storage format, but doing so will always preserve the content.
And because the stored data retains the "bytes" datatype, it can be converted directly back
to +b without data loss. Although you should avoid frequent switching of this flag, as the
entire file needs to be completely re-written to disk whenever the flag is changed.
r = readable
Files flagged +r will be readable by any user, otherwise they will be private and readable
only by the owner.
d = direct access / dynamic
Similar to properties, this flag exempts the file from being transparently intercepted by
getter/setter functions. However, it's important to note that getter/setters on files can
already be easily bypassed simply by using the raw file access functions provided as
built-ins. This flag only applies when files are accessed by the "!" syntax.
l = large file
Files flagged with this are considered to be too large to access all at once using the "!"
syntax or by any functions that read the whole file into memory at once. Attempts to do so
will cause the error E_IDUNNO to be raised.
TASK ATTRIBUTES
~~~~~~~~~~~~~~~
A task has a number of important attributes, mostly read-only, which can be accessed through
built-in functions. These persist throughout the entire task,
CHICKENSCRATCH
~~~~~~~~~~~~~~
simple program:
while (1)

View file

@ -7,6 +7,32 @@ from pyparsing import ParseException
from language_types import *
from bytecode import *
class PropertyStorage(object):
def __init__(self):
self.name = None
self.flags = ""
self.owner = None
self.value = None
class FileStorage(object):
def __init__(self):
self.name = None
self.flags = ""
self.owner = None
self.filepath = None
class FunctionStorage(object):
def __init__(self):
self.name = None
self.flags = ""
self.owner = None
self.bytecode = []
class ObjectStorage(object):
def __init__(self):
self.props = []
self.files = []
self.funcs = []

View file

@ -117,7 +117,7 @@ class VMObjRef(VMType):
if isinstance(value, ObjRef):
self.value = value
elif isinstance(value, (float, int)):
self.value = ObjRef(int(value))
self.value = int(value)
else:
raise TypeError, "Attempted to create VMObjRef with invalid object reference: %r" % (value,)
@ -127,7 +127,7 @@ class VMObjRef(VMType):
return StackLiteral(VMObjRef(int(tokens[1])))
def __repr__(self):
return "#%s" % (self.value.objnum,)
return "#%s" % (self.value,)
class VMRef(VMBaseObject):
pass

130
pbkdf2.py Normal file
View file

@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
"""
pbkdf2
~~~~~~
This module implements pbkdf2 for Python. It also has some basic
tests that ensure that it works. The implementation is straightforward
and uses stdlib only stuff and can be easily be copy/pasted into
your favourite application.
Use this as replacement for bcrypt that does not need a c implementation
of a modified blowfish crypto algo.
Example usage:
>>> pbkdf2_hex('what i want to hash', 'the random salt')
'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9'
How to use this:
1. Use a constant time string compare function to compare the stored hash
with the one you're generating::
def safe_str_cmp(a, b):
if len(a) != len(b):
return False
rv = 0
for x, y in izip(a, b):
rv |= ord(x) ^ ord(y)
return rv == 0
2. Use `os.urandom` to generate a proper salt of at least 8 byte.
Use a unique salt per hashed password.
3. Store ``algorithm$salt:costfactor$hash`` in the database so that
you can upgrade later easily to a different algorithm if you need
one. For instance ``PBKDF2-256$thesalt:10000$deadbeef...``.
:copyright: (c) Copyright 2011 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import hmac
import hashlib
from struct import Struct
from operator import xor
from itertools import izip, starmap
_pack_int = Struct('>I').pack
def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
"""Like :func:`pbkdf2_bin` but returns a hex encoded string."""
return pbkdf2_bin(data, salt, iterations, keylen, hashfunc).encode('hex')
def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
"""Returns a binary digest for the PBKDF2 hash algorithm of `data`
with the given `salt`. It iterates `iterations` time and produces a
key of `keylen` bytes. By default SHA-256 is used as hash function,
a different hashlib `hashfunc` can be provided.
"""
hashfunc = hashfunc or hashlib.sha256
mac = hmac.new(data, None, hashfunc)
def _pseudorandom(x, mac=mac):
h = mac.copy()
h.update(x)
return map(ord, h.digest())
buf = []
for block in xrange(1, -(-keylen // mac.digest_size) + 1):
rv = u = _pseudorandom(salt + _pack_int(block))
for i in xrange(iterations - 1):
u = _pseudorandom(''.join(map(chr, u)))
rv = starmap(xor, izip(rv, u))
buf.extend(rv)
return ''.join(map(chr, buf))[:keylen]
def test():
failed = []
def check(data, salt, iterations, keylen, expected):
rv = pbkdf2_hex(data, salt, iterations, keylen)
if rv != expected:
print 'Test failed:'
print ' Expected: %s' % expected
print ' Got: %s' % rv
print ' Parameters:'
print ' data=%s' % data
print ' salt=%s' % salt
print ' iterations=%d' % iterations
print
failed.append(1)
# From RFC 6070
check('password', 'salt', 1, 20,
'0c60c80f961f0e71f3a9b524af6012062fe037a6')
check('password', 'salt', 2, 20,
'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957')
check('password', 'salt', 4096, 20,
'4b007901b765489abead49d926f721d065a429c1')
check('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
4096, 25, '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038')
check('pass\x00word', 'sa\x00lt', 4096, 16,
'56fa6aa75548099dcc37d7f03425e0c3')
# This one is from the RFC but it just takes for ages
##check('password', 'salt', 16777216, 20,
## 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')
# From Crypt-PBKDF2
check('password', 'ATHENA.MIT.EDUraeburn', 1, 16,
'cdedb5281bb2f801565a1122b2563515')
check('password', 'ATHENA.MIT.EDUraeburn', 1, 32,
'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837')
check('password', 'ATHENA.MIT.EDUraeburn', 2, 16,
'01dbee7f4a9e243e988b62c73cda935d')
check('password', 'ATHENA.MIT.EDUraeburn', 2, 32,
'01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86')
check('password', 'ATHENA.MIT.EDUraeburn', 1200, 32,
'5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13')
check('X' * 64, 'pass phrase equals block size', 1200, 32,
'139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1')
check('X' * 65, 'pass phrase exceeds block size', 1200, 32,
'9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a')
raise SystemExit(bool(failed))
if __name__ == '__main__':
test()

17
pyenum.py Normal file
View file

@ -0,0 +1,17 @@
class pyenum(object):
def __setattr__(self, name, val):
global enum_reversals
object.__setattr__(self, name, val)
if not self in enum_reversals:
enum_reversals[self] = {}
enum_reversals[self][val] = name
enum_reversals = {}
def reverse_enum(e, v):
global enum_reversals
if e in enum_reversals:
return enum_reversals[e][v]
return None

View file

@ -6,4 +6,6 @@ vxx = "abc";
else
vvv = #-1; vvx = $nothing;
endif
serverlog(vvv);
serverlog(vvv);
serverlog(#0.test);
serverlog("what");

15
tt.py
View file

@ -1,9 +1,18 @@
from virtualmachine import VirtualMachine
from virtualmachine import VirtualMachine, static_vm
from parse import Parser
from database import *
db = Database("test")
p = Parser()
vm = VirtualMachine(None)
bytecode = p.parse("""serverlog("hello"); var1 = var2;""")
vm = static_vm
vm.db = db
bytecode = p.parse("""serverlog("hello"); var2 = "7"; var1 = var2; serverlog(var1);""")
vm.spawn_cmd_task(bytecode, {})
bytecode = p.test()
vm.spawn_cmd_task(bytecode, {})
vm.run()
vm.run()
vm.run()

View file

@ -1,7 +1,46 @@
import random, heapq
from parse import Parser
from language import *
import errors
"""
class VMMemory(object):
def __init__(self):
self.objects = []
def create(self, i):
self.objects[i] = None
def create_new(self):
self.objects.append(abc)
def destroy(self, i):
self.objects[i] = None
def renumber(self, i, j):
self.objects[j], self.objects[i] = self.objects[i], self.objects[j]
def trim(self):
newmax = None
for i in xrange(len(self.objects)-1, -1, -1):
if self.objects[i] != None:
newmax = i
break
if newmax != None:
self.objects = self.objects[:newmax+1]
def get_obj(self, i):
if i < 0:
raise errors.VMRuntimeError(errors.enum.E_INVIND)
elif i >= len(self.objects):
raise errors.VMRuntimeError(errors.enum.E_INVIND)
else:
o = self.objects[i]
if o == None:
raise errors.VMRuntimeError(errors.enum.E_INVIND)
else:
return o
"""
class VMContext(object):
def __init__(self, vars):
@ -36,7 +75,7 @@ class VirtualMachine(object):
def generate_task_id(self):
rv = random.randint(1,self.max_tasks)
if len(self.tasks) >= self.max_tasks:
raise RangeError, "Maximum number of tasks exceeded"
raise RangeError("Maximum number of tasks exceeded")
while rv in self.tasks:
rv += 1
if rv > self.max_tasks:
@ -194,7 +233,8 @@ class VirtualMachine(object):
self.ticks_used += op.ticks()
if self.ticks_used > self.max_ticks:
"ran out of ticks"
self.exc_push("out of ticks exception")
"resource exceptions cannot be caught, so stop execution immediately"
self.exc_push(errors.E_TICKS)
self.uncaught_exception()
self.finished_start_next()
else: