Update of /cvsroot/tmda/tmda/TMDA
In directory sc8-pr-cvs1:/tmp/cvs-serv30602/TMDA

Modified Files:
        Cookie.py Errors.py 
Added Files:
        Address.py 
Log Message:
Stripped down tmda-address and tmda-check-address, used Tim Legant's
Address.py module.

Seems to have the same behavior as before. Need testing though.



--- NEW FILE ---
# -*- python -*-
#
# Copyright (C) 2001,2002 Jason R. Mastaler <[EMAIL PROTECTED]>
#
# Author: Tim Legant <[EMAIL PROTECTED]>
#
# This file is part of TMDA.
#
# TMDA is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  A copy of this license should
# be included in the file COPYING.
#
# TMDA is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with TMDA; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

"""TMDA Address objects."""

import re
import time

import email

import Cookie
import Defaults
from Errors import *


# Private helper functions
def _split(address):
    local_parts = []
    local = ''
    domain = ''
    if address:
        at = address.rindex('@')
        local = address[:at].lower()
        domain = address[at+1:].lower()
        local_parts = local.split(Defaults.RECIPIENT_DELIMITER)
    return local_parts, local, domain


# Address classes

class Address:
    def __init__(self, address=''):
        self.address = address

    def base(self):
        return Defaults.USERNAME + '@' + Defaults.HOSTNAME
                        
    def create(self, base):
        self.address = base or self.base()

    def verify(self):
        raise BadCryptoError, "No cryptographic information in address."

    def split(self):
        (dummy, local, domain) = _split(self.address)
        return local, domain

    def tag(self):
        return ''

    def __str__(self):
        return self.address


class TaggedAddress(Address):
    def __init__(self, address):
        Address.__init__(self, address)
        (self.local_parts, dummy, dummy) = _split(address)

    def tag(self):
        return self.local_parts[1]


class ConfirmAddress(TaggedAddress):
    def __init__(self, address=''):
        TaggedAddress.__init__(self, address)

    def create(self, base, timestamp, pid, keyword):
        if Defaults.CONFIRM_ADDRESS:
            base = Defaults.CONFIRM_ADDRESS
        elif not base:
            base = self.base()
        (dummy, local, domain) = _split(str(base))
        cookie = Cookie.make_confirm_cookie(int(timestamp), pid, keyword)
        self.local_parts = [ local, 'confirm', keyword + '.' + cookie ]
        tagged_local = Defaults.RECIPIENT_DELIMITER.join(self.local_parts)
        self.address = tagged_local + '@' + domain
        return self

    def verify(self, dummy=''):
        try:
            (keyword, timestamp, pid, hmac) = self.local_parts[-1].split('.')
            try_hmac = Cookie.confirmationmac(timestamp, pid, keyword)
            if try_hmac != hmac:
                raise BadCryptoError, "Invalid cryptographic tag."
        except ValueError:
            raise BadCryptoError, "Invalid cryptographic tag format."

    def keyword(self):
        return self.local_parts[-1].split('.')[0]

    def timestamp(self):
        return self.local_parts[-1].split('.')[1]

    def pid(self):
        return self.local_parts[-1].split('.')[2]

    def hmac(self):
        return self.local_parts[-1].split('.')[3]


class DatedAddress(TaggedAddress):
    def __init__(self, address=''):
        TaggedAddress.__init__(self, address)

    def create(self, base, timeout=None):
        if not base:
            base = self.base()
        (dummy, local, domain) = _split(str(base))
        cookie = Cookie.make_dated_cookie(int(time.time()), timeout)
        self.local_parts = [ local, 'dated', cookie ]
        tagged_local = Defaults.RECIPIENT_DELIMITER.join(self.local_parts)
        self.address = tagged_local + '@' + domain
        return self

    def verify(self, dummy=''):
        try:
            (timestamp, hmac) = self.local_parts[-1].split('.')
            try_hmac = Cookie.datemac(timestamp)
            if int(time.time()) > int(timestamp):
                raise ExpiredAddressError, "Dated address has expired."
            if try_hmac != hmac:
                raise BadCryptoError, "Invalid cryptographic tag."
        except ValueError:
            raise BadCryptoError, "Invalid cryptographic tag format."

    def timestamp(self, prettyprint = 0, localtime = 0):
        expires = self.local_parts[-1].split('.')[0]

        if not prettyprint:
            return expires

        expires = int(expires)
        if localtime:
            local_tz = time.strftime("%Z", time.localtime(expires))
            expires_str = time.asctime(time.localtime(expires)) + ' ' + local_tz
        else:
            expires_str = time.asctime(time.gmtime(expires)) + ' UTC'
        return expires_str

    def hmac(self):
        return self.local_parts[-1].split('.')[1]


class KeywordAddress(TaggedAddress):
    def __init__(self, address=''):
        TaggedAddress.__init__(self, address)

    def create(self, base, keyword):
        if not base:
            base = self.base()
        (dummy, local, domain) = _split(str(base))
        cookie = Cookie.make_keyword_cookie(keyword)
        self.local_parts = [ local, 'keyword', cookie ]
        tagged_local = Defaults.RECIPIENT_DELIMITER.join(self.local_parts)
        self.address = tagged_local + '@' + domain
        return self

    def verify(self, dummy=''):
        parts = self.local_parts[-1].split('.')
        keyword = '.'.join(parts[:-1])
        if not keyword:
            raise BadCryptoError, "Invalid cryptographic tag format."
        hmac = parts[-1]
        try_hmac = Cookie.make_keywordmac(keyword)
        if try_hmac != hmac:
            raise BadCryptoError, "Invalid cryptographic tag."

    def tag(self):
        return 'keyword'

    def keyword(self):
        return '.'.join(self.local_parts[-1].split('.')[:-1])

    def hmac(self):
        return self.local_parts[-1].split('.')[-1]


class SenderAddress(TaggedAddress):
    def __init__(self, address=''):
        TaggedAddress.__init__(self, address)

    def create(self, base, sender):
        if not base:
            base = self.base()
        (dummy, local, domain) = _split(str(base))
        cookie = Cookie.make_sender_cookie(str(sender))
        self.local_parts = [ local, 'sender', cookie ]
        tagged_local = Defaults.RECIPIENT_DELIMITER.join(self.local_parts)
        self.address = tagged_local + '@' + domain
        return self

    def verify(self, sender):
        hmac = self.local_parts[-1]
        try_hmac = Cookie.make_sender_cookie(str(sender).lower())
        if try_hmac != hmac:
            raise BadCryptoError, "Invalid cryptographic tag."

    def hmac(self):
        return self.local_parts[-1]



def Factory(address = None, tag = None):
    """Create an address object of the appropriate class."""
    if tag:
        pass
    elif address:
        address = email.Utils.parseaddr(address)[1]
        (local_parts, dummy, dummy) = _split(address)
    else:    
        return Address(address)
    try:
        cookie_type = tag or local_parts[-2]
        if cookie_type == 'confirm':
            addr_obj = ConfirmAddress(address)
        elif cookie_type == 'dated':
            addr_obj = DatedAddress(address)
        elif cookie_type == 'sender':
            addr_obj = SenderAddress(address)
        else:
            addr_obj = KeywordAddress(address)
    except (AddressError, IndexError):
        addr_obj = Address(address)
    return addr_obj

Index: Cookie.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Cookie.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- Cookie.py   16 Jun 2002 02:58:17 -0000      1.23
+++ Cookie.py   26 Nov 2002 01:05:06 -0000      1.24
@@ -71,9 +71,9 @@
     return binascii.hexlify(datemac)
 
 
-def make_dated_cookie(time):
+def make_dated_cookie(time, timeout = None):
     """Return a dated-style cookie (expire date + HMAC)."""
-    tmda_timeout = os.environ.get('TMDA_TIMEOUT')
+    tmda_timeout = timeout or os.environ.get('TMDA_TIMEOUT')
     if not tmda_timeout:tmda_timeout = Defaults.TIMEOUT
     expire_time = str(int(time) + Util.seconds(tmda_timeout))
     datedmac = datemac(expire_time)

Index: Errors.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Errors.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Errors.py   27 Feb 2002 22:01:42 -0000      1.6
+++ Errors.py   26 Nov 2002 01:05:06 -0000      1.7
@@ -41,3 +41,20 @@
         TMDAError.__init__(self)
         self.varname = varname
         print 'Missing environment variable:', self.varname
+
+class AddressError(TMDAError):
+    """Address errors."""
+    def __init__(self, errmsg = ''):
+        self.args = errmsg
+
+    def __repr__(self):
+        return self.args
+
+class BadCryptoError(AddressError):
+    """Bad (or no) cryptographic information in address."""
+    pass
+
+class ExpiredAddressError(AddressError):
+    """Expired 'dated' address."""
+    pass
+

_______________________________________
tmda-cvs mailing list
http://tmda.net/lists/listinfo/tmda-cvs

Reply via email to