""" Limit unauthorized replay attacks by authenticating that any given nonce is only used once in a specified period of time. The caller of this function is expected to implement any policies on duration. """ # directory where nonces are to be retained from config import directory noncedir = directory.spam + "nonce/" def xmlchars(text): for i in range(len(text)-1,-1,-1): if not ord(text[i]) in range(32,128): text = '%s&#x%X;%s' % (text[:i], ord(text[i]), text[i+1:]) return text def generate(expires=None, data=''): "Generate a new nonce, guaranteed to be unique" import base64,random while True: nonce=base64.encodestring(str(random.randint(0,999999999))).strip() if unique(nonce, expires, data): return nonce def gen_escaped(expires=None, data=''): nonce = generate(expires, data) return ''.join(['&#%d;'%ord(c) for c in nonce]) def update(id, value, stat=None): "Update the data associated with a nonce" import md5, os filename=os.path.join(noncedir,md5.new(id).hexdigest()) stat = None if os.path.exists(filename) and not stat: stat = os.stat(filename) file = open(filename,'wb') file.write(value) file.close() if stat: try: os.utime(filename,(stat.st_atime,stat.st_mtime)) except OSError: update(id, value, stat) def retrieve(id): "Retrieve the data associated with a nonce" import md5, os.path filename=os.path.join(noncedir,md5.new(id).hexdigest()) if not os.path.exists(filename): return try: file = open(filename,'r') data = file.read() file.close() return data except: import sys,traceback,time tb = ''.join(apply(traceback.format_exception, sys.exc_info())) tb = tb + '\nid: %s' % id generate(time.time()+86400, tb) def remove(id): "Remove a nonce, if it exists" import md5, os, os.path # produce a legal file name from the id filename=os.path.join(noncedir,md5.new(id).hexdigest()) if os.path.exists(filename): os.remove(filename) def unique(id, expires=None, data=''): """Authenticate a nonce. Optional parameters include an expiration date and data to be logged with the nonce.""" import glob, time, md5, os, os.path # default expiration to five minutes from now if not expires: expires = int(time.time()+300) # produce a legal file name from the id filename=os.path.join(noncedir,md5.new(id).hexdigest()) # remove any expired nonces for name in glob.glob(os.path.join(noncedir,'*')): try: if os.stat(name).st_mtime