M2Crypto-0.22.6rc4/0000775000175000017500000000000012613362233014116 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/M2Crypto/0000775000175000017500000000000012613362233015575 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/M2Crypto/PGP/0000775000175000017500000000000012613362233016223 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/M2Crypto/PGP/PublicKey.py0000664000175000017500000000315612607370517020500 0ustar matejmatej00000000000000"""M2Crypto PGP2. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from constants import * from packet import * import RSA class PublicKey: def __init__(self, pubkey_pkt): import warnings warnings.warn('Deprecated. No maintainer for PGP. If you use this, please inform M2Crypto maintainer.', DeprecationWarning) self._pubkey_pkt = pubkey_pkt self._pubkey = RSA.new_pub_key((pubkey_pkt._e, pubkey_pkt._n)) self._userid = {} self._signature = {} def keyid(self): return self._pubkey.n[-8:] def add_userid(self, u_pkt): assert isinstance(u_pkt, userid_packet) self._userid[u_pkt.userid()] = u_pkt def remove_userid(self, userid): del self._userid[userid] def add_signature(self, userid, s_pkt): assert isinstance(s_pkt, signature_packet) assert self._userid.has_key(userid) if self._signature.has_key(userid): self._signature.append(s_pkt) else: self._signature = [s_pkt] def __getitem__(self, id): return self._userid[id] def __setitem__(self, *args): raise NotImplementedError def __delitem__(self, id): del self._userid[id] if self._signature[id]: del self._signature[id] def write(self, stream): pass def encrypt(self, ptxt): # XXX Munge ptxt into pgp format. return self._pubkey.public_encrypt(ptxt, RSA.pkcs1_padding) def decrypt(self, ctxt): # XXX Munge ctxt into pgp format. return self._pubkey.public_encrypt(ctxt, RSA.pkcs1_padding) M2Crypto-0.22.6rc4/M2Crypto/PGP/PublicKeyRing.py0000664000175000017500000000417312607370517021320 0ustar matejmatej00000000000000"""M2Crypto PGP2. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from constants import * from packet import * from PublicKey import * class PublicKeyRing: def __init__(self, keyring): import warnings warnings.warn('Deprecated. No maintainer for PGP. If you use this, please inform M2Crypto maintainer.', DeprecationWarning) self._keyring = keyring self._userid = {} self._keyid = {} self._spurious = [] self._pubkey = [] def load(self): curr_pub = None curr_index = -1 ps = packet_stream(self._keyring) while 1: pkt = ps.read() if pkt is None: break elif isinstance(pkt, public_key_packet): curr_index = curr_index + 1 curr_pub = PublicKey(pkt) self._pubkey.append(curr_pub) #self._keyid[curr_pub.keyid()] = (curr_pub, curr_index) elif isinstance(pkt, userid_packet): if curr_pub is None: self._spurious.append(pkt) else: curr_pub.add_userid(pkt) self._userid[pkt.userid()] = (curr_pub, curr_index) elif isinstance(pkt, signature_packet): if curr_pub is None: self._spurious.append(pkt) else: curr_pub.add_signature(pkt) else: self._spurious.append(pkt) ps.close() def __getitem__(self, id): return self._userid[id][0] def __setitem__(self, *args): raise NotImplementedError def __delitem__(self, id): pkt, idx = self._userid[id] del self._pubkey[idx] del self._userid[idx] pkt, idx = self._keyid[id] del self._keyid[idx] def spurious(self): return tuple(self._spurious) def save(self, keyring): for p in self._pubkey: pp = p.pack() keyring.write(pp) def load_pubring(filename='pubring.pgp'): pkr = PublicKeyRing(open(filename, 'rb')) pkr.load() return pkr M2Crypto-0.22.6rc4/M2Crypto/PGP/RSA.py0000664000175000017500000000152112607370517017230 0ustar matejmatej00000000000000"""M2Crypto PGP2 RSA. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import sys from M2Crypto import m2, RSA _RSA = RSA del RSA class RSA(_RSA.RSA): pass class RSA_pub(_RSA.RSA_pub): pass def new_pub_key((e, n)): """ Factory function that instantiates an RSA_pub object from a (e, n) tuple. 'e' is the RSA public exponent; it is a string in OpenSSL's binary format, i.e., a number of bytes in big-endian. 'n' is the RSA composite of primes; it is a string in OpenSSL's binary format, i.e., a number of bytes in big-endian. """ import warnings warnings.warn('Deprecated. No maintainer for PGP. If you use this, please inform M2Crypto maintainer.', DeprecationWarning) rsa = m2.rsa_new() m2.rsa_set_e_bin(rsa, e) m2.rsa_set_n_bin(rsa, n) return RSA_pub(rsa, 1) M2Crypto-0.22.6rc4/M2Crypto/PGP/__init__.py0000664000175000017500000000053512607370517020346 0ustar matejmatej00000000000000"""M2Crypto PGP2. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from constants import * from packet import public_key_packet, trust_packet, userid_packet,\ comment_packet, signature_packet, private_key_packet, cke_packet,\ pke_packet, literal_packet, packet_stream from PublicKey import * from PublicKeyRing import * M2Crypto-0.22.6rc4/M2Crypto/PGP/constants.py0000664000175000017500000000057512605255257020630 0ustar matejmatej00000000000000"""M2Crypto PGP2. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" CTB_TAG = 128 CTB_PKE = 1 CTB_SIGNATURE = 2 CTB_MESSAGE_DIGETS = 3 CTB_PRIVATE_KEY = 5 CTB_PUBLIC_KEY = 6 CTB_COMPRESSED_DATA = 8 CTB_CKE = 9 CTB_LITERAL_DATA = 11 CTB_TRUST = 12 CTB_USERID = 13 CTB_COMMENT = 14 M2Crypto-0.22.6rc4/M2Crypto/PGP/packet.py0000664000175000017500000002573512607370517020067 0ustar matejmatej00000000000000"""M2Crypto PGP2. This module implements PGP packets per RFC1991 and various source distributions. Each packet type is represented by a class; packet classes derive from the abstract 'packet' class. The 'message digest' packet type, mentioned but not documented in RFC1991, is not implemented. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # XXX Work-in-progress. # Be liberal in what you accept. # Be conservative in what you send. # Be lazy in what you eval. import struct, time try: from cStringIO import StringIO except ImportError: from StringIO import StringIO from M2Crypto import EVP, RSA from M2Crypto.util import octx_to_num from constants import * _OK_VERSION = ('\002', '\003') _OK_VALIDITY = ('\000',) _OK_PKC = ('\001',) class packet: def __init__(self, ctb, body=None): import warnings warnings.warn('Deprecated. No maintainer for PGP. If you use this, please inform M2Crypto maintainer.', DeprecationWarning) self.ctb = ctb if body is not None: self.body = StringIO(body) else: self.body = None def validate(self): return 1 def pack(self): raise NotImplementedError, '%s.pack(): abstract method' % (self.__class__,) def version(self): if hasattr(self, '_version'): return ord(self._version) else: return None def timestamp(self): if hasattr(self, '_timestamp'): return struct.unpack('>L', self._timestamp)[0] else: return None def validity(self): if hasattr(self, '_validity'): return struct.unpack('>H', self._validity)[0] else: return None def pkc(self): if hasattr(self, '_pkc'): return self._pkc else: return None def _llf(self, lenf): if lenf < 256: return (0, chr(lenf)) elif lenf < 65536: return (1, struct.pack('>H', lenf)) else: assert lenf < 2L**32 return (2, struct.pack('>L', lenf)) def _ctb(self, llf): ctbv = _FACTORY[self.__class__] return chr((1 << 7) | (ctbv << 2) | llf) class public_key_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if self.body is not None: self._version = self.body.read(1) self._timestamp = self.body.read(4) self._validity = self.body.read(2) self._pkc = self.body.read(1) self._nlen = self.body.read(2) nlen = (struct.unpack('>H', self._nlen)[0] + 7) / 8 self._n = self.body.read(nlen) self._elen = self.body.read(2) elen = (struct.unpack('>H', self._elen)[0] + 7) / 8 self._e = self.body.read(elen) def pack(self): if self.body is None: self.body = StringIO() self.body.write(self._version) self.body.write(self._timestamp) self.body.write(self._validity) self.body.write(self._pkc) self.body.write(self._nlen) self.body.write(self._n) self.body.write(self._elen) self.body.write(self._e) self.body = self.body.getvalue() llf, lenf = self._llf(len(self.body)) ctb = self._ctb(llf) return '%s%s%s' % (ctb, lenf, self.body) def pubkey(self): return self._pubkey.pub() class trust_packet(packet): # This implementation neither interprets nor emits trust packets. def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self.trust = self.body.read(1) class userid_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self._userid = body def pack(self): if self.body is None: self.body = StringIO() self.body.write(chr(len(self._userid))) self.body.write(self._userid) self.body = self.body.getvalue() return self.ctb + self.body def userid(self): return self._userid class comment_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self.comment = self.body.getvalue() def pack(self): if self.body is None: self.body = StringIO() self.body.write(chr(len(self.comment))) self.body.write(self.comment) self.body = self.body.getvalue() return self.ctb + self.body class signature_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self._version = self.body.read(1) self._len_md_stuff = self.body.read(1) self._classification = self.body.read(1) self._timestamp = self.body.read(4) self._keyid = self.body.read(8) self._pkc = self.body.read(1) self._md_algo = self.body.read(1) self._md_chksum = self.body.read(2) self._sig = self.body.read() def pack(self): if self.body is None: self.body = StringIO() self.body.write(self._version) self.body.write(self._len_md_stuff) self.body.write(self._classification) self.body.write(self._timestamp) self.body.write(self._keyid) self.body.write(self._pkc) self.body.write(self._md_algo) self.body.write(self._md_chksum) self.body.write(self._sig) self.body = self.body.getvalue() llf, lenf = self._llf(len(body)) self.ctb = self.ctb | llf return '%s%s%s' % (self.ctb, lenf, self.body) def validate(self): if self._version not in _OK_VERSION: return None if self._len_md_stuff != '\005': return None class private_key_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self._version = self.body.read(1) self._timestamp = self.body.read(4) self._validity = self.body.read(2) self._pkc = self.body.read(1) self._nlen = self.body.read(2) nlen = (struct.unpack('>H', self._nlen)[0] + 7) / 8 self._n = self.body.read(nlen) self._elen = self.body.read(2) elen = (struct.unpack('>H', self._elen)[0] + 7) / 8 self._e = self.body.read(elen) self._cipher = self.body.read(1) if self._cipher == '\001': self._iv = self.body.read(8) else: self._iv = None for param in ['d', 'p', 'q', 'u']: _plen = self.body.read(2) setattr(self, '_'+param+'len', _plen) plen = (struct.unpack('>H', _plen)[0] + 7) / 8 setattr(self, '_'+param, self.body.read(plen)) self._cksum = self.body.read(2) def is_encrypted(self): return ord(self._cipher) class cke_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self._iv = self.body.read(8) self._cksum = self.body.read(2) self._ctxt = self.body.read() class pke_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self._version = self.body.read(1) self._keyid = self.body.read(8) self._pkc = ord(self.body.read(1)) deklen = (struct.unpack('>H', self.body.read(2))[0] + 7 ) / 8 self._dek = octx_to_num(self.body.read(deklen)) class literal_packet(packet): def __init__(self, ctb, body=None): packet.__init__(self, ctb, body) if body is not None: self.fmode = self.body.read(1) fnlen = self.body.read(1) self.fname = self.body.read(fnlen) self.ftime = self.body.read(4) #self.data = self.body.read() class compressed_packet(packet): def __init__(self, ctb, stream): packet.__init__(self, ctb, '') if body is not None: self.algo = stream.read(1) # This reads the entire stream into memory. self.data = stream.read() def validate(self): return (self.algo == '\001') def uncompress(self): import zlib decomp = zlib.decompressobj(-13) # RFC 2440, pg 61. # This doubles the memory usage. stream = StringIO(decomp.decompress(self.data)) return stream _FACTORY = { 1 : pke_packet, 2 : signature_packet, #3 : message_digest_packet, # XXX not implemented 5 : private_key_packet, 6 : public_key_packet, #8 : compressed_packet, # special case 9 : cke_packet, 11 : literal_packet, 12 : trust_packet, 13 : userid_packet, 14 : comment_packet, pke_packet : 1, signature_packet : 2, #3 : message_digest_packet, private_key_packet : 5, public_key_packet : 6, #8 : compressed_packet, cke_packet : 9, literal_packet : 11, trust_packet : 12, userid_packet : 13, comment_packet : 14 } class packet_stream: def __init__(self, input): self.stream = input self.under_current = None self._count = 0 def close(self): self.stream.close() if self.under_current is not None: self.under_current.close() def read(self, keep_trying=0): while 1: ctb0 = self.stream.read(1) if not ctb0: return None ctb = ord(ctb0) if is_ctb(ctb): break elif keep_trying: continue else: raise XXXError ctbt = (ctb & 0x3c) >> 2 if ctbt == CTB_COMPRESSED_DATA: self.under_current = self.stream cp = compressed_packet(ctb0, self.stream) self.stream = cp.uncompress() return self.read() # Decode the length of following data. See RFC for details. llf = ctb & 3 if llf == 0: lenf = ord(self.stream.read(1)) elif llf == 1: lenf = struct.unpack('>H', self.stream.read(2))[0] elif llf == 2: lenf = struct.unpack('>L', self.stream.read(4))[0] else: # llf == 3 raise XXXError, 'impossible case' body = self.stream.read(lenf) if not body or (len(body) != lenf): raise XXXError, 'corrupted packet' self._count = self.stream.tell() try: return _FACTORY[ctbt](ctb0, body) except KeyError: return packet(ctb0, body) def count(self): return self._count def is_ctb(ctb): return ctb & 0xc0 def make_ctb(value, llf): return chr((1 << 7) | (value << 2) | llf) M2Crypto-0.22.6rc4/M2Crypto/SSL/0000775000175000017500000000000012613362233016236 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/M2Crypto/SSL/Checker.py0000664000175000017500000002311512611255457020165 0ustar matejmatej00000000000000""" SSL peer certificate checking routines Copyright (c) 2004-2007 Open Source Applications Foundation. All rights reserved. Copyright 2008 Heikki Toivonen. All rights reserved. """ __all__ = ['SSLVerificationError', 'NoCertificate', 'WrongCertificate', 'WrongHost', 'Checker'] from M2Crypto import util, EVP, m2 import socket import re class SSLVerificationError(Exception): pass class NoCertificate(SSLVerificationError): pass class WrongCertificate(SSLVerificationError): pass class WrongHost(SSLVerificationError): def __init__(self, expectedHost, actualHost, fieldName='commonName'): """ This exception will be raised if the certificate returned by the peer was issued for a different host than we tried to connect to. This could be due to a server misconfiguration or an active attack. @param expectedHost: The name of the host we expected to find in the certificate. @param actualHost: The name of the host we actually found in the certificate. @param fieldName: The field name where we noticed the error. This should be either 'commonName' or 'subjectAltName'. """ if fieldName not in ('commonName', 'subjectAltName'): raise ValueError('Unknown fieldName, should be either commonName or subjectAltName') SSLVerificationError.__init__(self) self.expectedHost = expectedHost self.actualHost = actualHost self.fieldName = fieldName def __str__(self): s = 'Peer certificate %s does not match host, expected %s, got %s' \ % (self.fieldName, self.expectedHost, self.actualHost) if isinstance(s, unicode): s = s.encode('utf8') return s class Checker: numericIpMatch = re.compile('^[0-9]+(\.[0-9]+)*$') def __init__(self, host=None, peerCertHash=None, peerCertDigest='sha1'): self.host = host self.fingerprint = peerCertHash self.digest = peerCertDigest def __call__(self, peerCert, host=None): if peerCert is None: raise NoCertificate('peer did not return certificate') if host is not None: self.host = host if self.fingerprint: if self.digest not in ('sha1', 'md5'): raise ValueError('unsupported digest "%s"' %(self.digest)) if (self.digest == 'sha1' and len(self.fingerprint) != 40) or \ (self.digest == 'md5' and len(self.fingerprint) != 32): raise WrongCertificate('peer certificate fingerprint length does not match') der = peerCert.as_der() md = EVP.MessageDigest(self.digest) md.update(der) digest = md.final() if util.octx_to_num(digest) != int(self.fingerprint, 16): raise WrongCertificate('peer certificate fingerprint does not match') if self.host: hostValidationPassed = False self.useSubjectAltNameOnly = False # subjectAltName=DNS:somehost[, ...]* try: subjectAltName = peerCert.get_ext('subjectAltName').get_value() if self._splitSubjectAltName(self.host, subjectAltName): hostValidationPassed = True elif self.useSubjectAltNameOnly: raise WrongHost(expectedHost=self.host, actualHost=subjectAltName, fieldName='subjectAltName') except LookupError: pass # commonName=somehost[, ...]* if not hostValidationPassed: hasCommonName = False commonNames = '' for entry in peerCert.get_subject().get_entries_by_nid(m2.NID_commonName): hasCommonName = True commonName = entry.get_data().as_text() if not commonNames: commonNames = commonName else: commonNames += ',' + commonName if self._match(self.host, commonName): hostValidationPassed = True break if not hasCommonName: raise WrongCertificate('no commonName in peer certificate') if not hostValidationPassed: raise WrongHost(expectedHost=self.host, actualHost=commonNames, fieldName='commonName') return True def _splitSubjectAltName(self, host, subjectAltName): """ >>> check = Checker() >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:my.example.com') True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:*.example.com') True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:m*.example.com') True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:m*ample.com') False >>> check.useSubjectAltNameOnly True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:m*ample.com, othername:') False >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:m*ample.com, DNS:my.example.org') False >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:m*ample.com, DNS:my.example.com') True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='DNS:my.example.com, DNS:my.example.org') True >>> check.useSubjectAltNameOnly True >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='') False >>> check._splitSubjectAltName(host='my.example.com', subjectAltName='othername:') False >>> check.useSubjectAltNameOnly False """ self.useSubjectAltNameOnly = False for certHost in subjectAltName.split(','): certHost = certHost.lower().strip() if certHost[:4] == 'dns:': self.useSubjectAltNameOnly = True if self._match(host, certHost[4:]): return True elif certHost[:11] == 'ip address:': self.useSubjectAltNameOnly = True if self._matchIPAddress(host, certHost[11:]): return True return False def _match(self, host, certHost): """ >>> check = Checker() >>> check._match(host='my.example.com', certHost='my.example.com') True >>> check._match(host='my.example.com', certHost='*.example.com') True >>> check._match(host='my.example.com', certHost='m*.example.com') True >>> check._match(host='my.example.com', certHost='m*.EXAMPLE.com') True >>> check._match(host='my.example.com', certHost='m*ample.com') False >>> check._match(host='my.example.com', certHost='*.*.com') False >>> check._match(host='1.2.3.4', certHost='1.2.3.4') True >>> check._match(host='1.2.3.4', certHost='*.2.3.4') False >>> check._match(host='1234', certHost='1234') True """ # XXX See RFC 2818 and 3280 for matching rules, this is may not # XXX yet be complete. host = host.lower() certHost = certHost.lower() if host == certHost: return True if certHost.count('*') > 1: # Not sure about this, but being conservative return False if self.numericIpMatch.match(host) or \ self.numericIpMatch.match(certHost.replace('*', '')): # Not sure if * allowed in numeric IP, but think not. return False if certHost.find('\\') > -1: # Not sure about this, maybe some encoding might have these. # But being conservative for now, because regex below relies # on this. return False # Massage certHost so that it can be used in regex certHost = certHost.replace('.', '\.') certHost = certHost.replace('*', '[^\.]*') if re.compile('^%s$' %(certHost)).match(host): return True return False def _matchIPAddress(self, host, certHost): """ >>> check = Checker() >>> check._matchIPAddress(host='my.example.com', certHost='my.example.com') False >>> check._matchIPAddress(host='1.2.3.4', certHost='1.2.3.4') True >>> check._matchIPAddress(host='1.2.3.4', certHost='*.2.3.4') False >>> check._matchIPAddress(host='1.2.3.4', certHost='1.2.3.40') False >>> check._matchIPAddress(host='::1', certHost='::1') True >>> check._matchIPAddress(host='::1', certHost='0:0:0:0:0:0:0:1') True >>> check._matchIPAddress(host='::1', certHost='::2') False """ try: canonical = socket.getaddrinfo(host, 0, 0, socket.SOCK_STREAM, 0, socket.AI_NUMERICHOST) certCanonical = socket.getaddrinfo(certHost, 0, 0, socket.SOCK_STREAM, 0, socket.AI_NUMERICHOST) except: return False return canonical == certCanonical if __name__ == '__main__': import doctest doctest.testmod() M2Crypto-0.22.6rc4/M2Crypto/SSL/Cipher.py0000664000175000017500000000205612607370517020034 0ustar matejmatej00000000000000"""SSL Ciphers Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" __all__ = ['Cipher', 'Cipher_Stack'] from M2Crypto import m2 class Cipher: def __init__(self, cipher): self.cipher=cipher def __len__(self): return m2.ssl_cipher_get_bits(self.cipher) def __repr__(self): return "%s-%s" % (self.name(), len(self)) def __str__(self): return "%s-%s" % (self.name(), len(self)) def version(self): return m2.ssl_cipher_get_version(self.cipher) def name(self): return m2.ssl_cipher_get_name(self.cipher) class Cipher_Stack: def __init__(self, stack): self.stack=stack def __len__(self): return m2.sk_ssl_cipher_num(self.stack) def __getitem__(self, idx): if not 0 <= idx < m2.sk_ssl_cipher_num(self.stack): raise IndexError('index out of range') v=m2.sk_ssl_cipher_value(self.stack, idx) return Cipher(v) def __iter__(self): for i in xrange(m2.sk_ssl_cipher_num(self.stack)): yield self[i] M2Crypto-0.22.6rc4/M2Crypto/SSL/Connection.py0000664000175000017500000003011312611255457020714 0ustar matejmatej00000000000000"""SSL Connection aka socket Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004-2007 OSAF. All Rights Reserved. Copyright 2008 Heikki Toivonen. All rights reserved. """ __all__ = ['Connection', 'timeout', # XXX Not really, but for documentation purposes ] # Python import socket # M2Crypto import Checker import timeout from Cipher import Cipher, Cipher_Stack from M2Crypto import X509, m2 from M2Crypto.SSL import SSLError from Session import Session #SSLError = getattr(__import__('M2Crypto.SSL', globals(), locals(), # 'SSLError'), 'SSLError') def _serverPostConnectionCheck(*args, **kw): return 1 class Connection: """An SSL connection.""" clientPostConnectionCheck = Checker.Checker() serverPostConnectionCheck = _serverPostConnectionCheck m2_bio_free = m2.bio_free m2_ssl_free = m2.ssl_free def __init__(self, ctx, sock=None, family=socket.AF_INET): self.ctx = ctx self.ssl = m2.ssl_new(self.ctx.ctx) if sock is not None: self.socket = sock else: self.socket = socket.socket(family, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._fileno = self.socket.fileno() self._timeout = self.socket.gettimeout() if self._timeout is None: self._timeout = -1.0 self.ssl_close_flag = m2.bio_noclose if self.ctx.post_connection_check is not None: self.set_post_connection_check_callback \ (self.ctx.post_connection_check) def __del__(self): if getattr(self, 'sslbio', None): self.m2_bio_free(self.sslbio) if getattr(self, 'sockbio', None): self.m2_bio_free(self.sockbio) if self.ssl_close_flag == m2.bio_noclose and \ getattr(self, 'ssl', None): self.m2_ssl_free(self.ssl) self.socket.close() def close(self): m2.ssl_shutdown(self.ssl) def clear(self): """ If there were errors in this connection, call clear() rather than close() to end it, so that bad sessions will be cleared from cache. """ return m2.ssl_clear(self.ssl) def set_shutdown(self, mode): m2.ssl_set_shutdown1(self.ssl, mode) def get_shutdown(self): return m2.ssl_get_shutdown(self.ssl) def bind(self, addr): self.socket.bind(addr) def listen(self, qlen=5): self.socket.listen(qlen) def ssl_get_error(self, ret): return m2.ssl_get_error(self.ssl, ret) def set_bio(self, readbio, writebio): """ Explicitly set read and write bios """ m2.ssl_set_bio(self.ssl, readbio._ptr(), writebio._ptr()) def set_client_CA_list_from_file(self, cafile): """ Set the acceptable client CA list. If the client returns a certificate, it must have been issued by one of the CAs listed in cafile. Makes sense only for servers. @param cafile: Filename from which to load the CA list. """ m2.ssl_set_client_CA_list_from_file(self.ssl, cafile) def set_client_CA_list_from_context(self): """ Set the acceptable client CA list. If the client returns a certificate, it must have been issued by one of the CAs listed in context. Makes sense only for servers. """ m2.ssl_set_client_CA_list_from_context(self.ssl, self.ctx.ctx) def setup_addr(self, addr): self.addr = addr def set_ssl_close_flag(self, flag): """ By default, SSL struct will be freed in __del__. Call with m2.bio_close to override this default. """ if flag not in (m2.bio_close, m2.bio_noclose): raise ValueError("flag must be m2.bio_close or m2.bio_noclose") self.ssl_close_flag = flag def setup_ssl(self): # Make a BIO_s_socket. self.sockbio = m2.bio_new_socket(self.socket.fileno(), 0) # Link SSL struct with the BIO_socket. m2.ssl_set_bio(self.ssl, self.sockbio, self.sockbio) # Make a BIO_f_ssl. self.sslbio = m2.bio_new(m2.bio_f_ssl()) # Link BIO_f_ssl with the SSL struct. m2.bio_set_ssl(self.sslbio, self.ssl, m2.bio_noclose) def _setup_ssl(self, addr): """Deprecated""" self.setup_addr(addr) self.setup_ssl() def set_accept_state(self): m2.ssl_set_accept_state(self.ssl) def accept_ssl(self): return m2.ssl_accept(self.ssl, self._timeout) def accept(self): """Accept an SSL connection. The return value is a pair (ssl, addr) where ssl is a new SSL connection object and addr is the address bound to the other end of the SSL connection.""" sock, addr = self.socket.accept() ssl = Connection(self.ctx, sock) ssl.addr = addr ssl.setup_ssl() ssl.set_accept_state() ssl.accept_ssl() check = getattr(self, 'postConnectionCheck', self.serverPostConnectionCheck) if check is not None: if not check(ssl.get_peer_cert(), ssl.addr[0]): raise Checker.SSLVerificationError, 'post connection check failed' return ssl, addr def set_connect_state(self): m2.ssl_set_connect_state(self.ssl) def connect_ssl(self): return m2.ssl_connect(self.ssl, self._timeout) def connect(self, addr): self.socket.connect(addr) self.addr = addr self.setup_ssl() self.set_connect_state() ret = self.connect_ssl() check = getattr(self, 'postConnectionCheck', self.clientPostConnectionCheck) if check is not None: if not check(self.get_peer_cert(), self.addr[0]): raise Checker.SSLVerificationError, 'post connection check failed' return ret def shutdown(self, how): m2.ssl_set_shutdown(self.ssl, how) def renegotiate(self): """Renegotiate this connection's SSL parameters.""" return m2.ssl_renegotiate(self.ssl) def pending(self): """Return the numbers of octets that can be read from the connection.""" return m2.ssl_pending(self.ssl) def _write_bio(self, data): return m2.ssl_write(self.ssl, data, self._timeout) def _write_nbio(self, data): return m2.ssl_write_nbio(self.ssl, data) def _read_bio(self, size=1024): if size <= 0: raise ValueError, 'size <= 0' return m2.ssl_read(self.ssl, size, self._timeout) def _read_nbio(self, size=1024): if size <= 0: raise ValueError, 'size <= 0' return m2.ssl_read_nbio(self.ssl, size) def write(self, data): if self._timeout != 0.0: return self._write_bio(data) return self._write_nbio(data) sendall = send = write def read(self, size=1024): if self._timeout != 0.0: return self._read_bio(size) return self._read_nbio(size) recv = read def setblocking(self, mode): """Set this connection's underlying socket to _mode_.""" self.socket.setblocking(mode) if mode: self._timeout = -1.0 else: self._timeout = 0.0 def settimeout(self, timeout): """Set this connection's underlying socket's timeout to _timeout_.""" self.socket.settimeout(timeout) self._timeout = timeout if self._timeout is None: self._timeout = -1.0 def fileno(self): return self.socket.fileno() def getsockopt(self, *args): return apply(self.socket.getsockopt, args) def setsockopt(self, *args): return apply(self.socket.setsockopt, args) def get_context(self): """Return the SSL.Context object associated with this connection.""" return m2.ssl_get_ssl_ctx(self.ssl) def get_state(self): """Return the SSL state of this connection.""" return m2.ssl_get_state(self.ssl) def verify_ok(self): return (m2.ssl_get_verify_result(self.ssl) == m2.X509_V_OK) def get_verify_mode(self): """Return the peer certificate verification mode.""" return m2.ssl_get_verify_mode(self.ssl) def get_verify_depth(self): """Return the peer certificate verification depth.""" return m2.ssl_get_verify_depth(self.ssl) def get_verify_result(self): """Return the peer certificate verification result.""" return m2.ssl_get_verify_result(self.ssl) def get_peer_cert(self): """Return the peer certificate; if the peer did not provide a certificate, return None.""" c=m2.ssl_get_peer_cert(self.ssl) if c is None: return None # Need to free the pointer coz OpenSSL doesn't. return X509.X509(c, 1) def get_peer_cert_chain(self): """Return the peer certificate chain; if the peer did not provide a certificate chain, return None. @warning: The returned chain will be valid only for as long as the connection object is alive. Once the connection object gets freed, the chain will be freed as well. """ c=m2.ssl_get_peer_cert_chain(self.ssl) if c is None: return None # No need to free the pointer coz OpenSSL does. return X509.X509_Stack(c) def get_cipher(self): """Return an M2Crypto.SSL.Cipher object for this connection; if the connection has not been initialised with a cipher suite, return None.""" c=m2.ssl_get_current_cipher(self.ssl) if c is None: return None return Cipher(c) def get_ciphers(self): """Return an M2Crypto.SSL.Cipher_Stack object for this connection; if the connection has not been initialised with cipher suites, return None.""" c=m2.ssl_get_ciphers(self.ssl) if c is None: return None return Cipher_Stack(c) def get_cipher_list(self, idx=0): """Return the cipher suites for this connection as a string object.""" return m2.ssl_get_cipher_list(self.ssl, idx) def set_cipher_list(self, cipher_list): """Set the cipher suites for this connection.""" return m2.ssl_set_cipher_list(self.ssl, cipher_list) def makefile(self, mode='rb', bufsize=-1): return socket._fileobject(self, mode, bufsize) def getsockname(self): return self.socket.getsockname() def getpeername(self): return self.socket.getpeername() def set_session_id_ctx(self, id): ret = m2.ssl_set_session_id_context(self.ssl, id) if not ret: raise SSLError(m2.err_reason_error_string(m2.err_get_error())) def get_session(self): sess = m2.ssl_get_session(self.ssl) return Session(sess) def set_session(self, session): m2.ssl_set_session(self.ssl, session._ptr()) def get_default_session_timeout(self): return m2.ssl_get_default_session_timeout(self.ssl) def get_socket_read_timeout(self): return timeout.struct_to_timeout(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeout.struct_size())) def get_socket_write_timeout(self): return timeout.struct_to_timeout(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, timeout.struct_size())) def set_socket_read_timeout(self, timeo): assert isinstance(timeo, timeout.timeout) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeo.pack()) def set_socket_write_timeout(self, timeo): assert isinstance(timeo, timeout.timeout) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, timeo.pack()) def get_version(self): "Return the TLS/SSL protocol version for this connection." return m2.ssl_get_version(self.ssl) def set_post_connection_check_callback(self, postConnectionCheck): self.postConnectionCheck = postConnectionCheck def set_tlsext_host_name(self, name): "Set the requested hostname for the SNI (Server Name Indication) extension" m2.ssl_set_tlsext_host_name(self.ssl, name) M2Crypto-0.22.6rc4/M2Crypto/SSL/Context.py0000664000175000017500000002237012611255457020247 0ustar matejmatej00000000000000"""SSL Context Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" __all__ = ['map', 'Context'] # M2Crypto import cb from M2Crypto import BIO, Err, RSA, X509, m2, util from weakref import WeakValueDictionary class _ctxmap: # noqa singleton = None def __init__(self): self.map = WeakValueDictionary() def __getitem__(self, key): return self.map[key] def __setitem__(self, key, value): self.map[key] = value def __delitem__(self, key): del self.map[key] def map(): if _ctxmap.singleton is None: _ctxmap.singleton = _ctxmap() return _ctxmap.singleton class Context: """'Context' for SSL connections.""" m2_ssl_ctx_free = m2.ssl_ctx_free def __init__(self, protocol='sslv23', weak_crypto=None, post_connection_check=None): proto = getattr(m2, protocol + '_method', None) if proto is None: raise ValueError("no such protocol '%s'" % protocol) self.ctx = m2.ssl_ctx_new(proto()) self.allow_unknown_ca = 0 self.post_connection_check = post_connection_check map()[long(self.ctx)] = self m2.ssl_ctx_set_cache_size(self.ctx, 128L) if weak_crypto is None: if protocol == 'sslv23': self.set_options(m2.SSL_OP_ALL | m2.SSL_OP_NO_SSLv2) self.set_cipher_list('ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH') def __del__(self): if getattr(self, 'ctx', None): self.m2_ssl_ctx_free(self.ctx) def close(self): del map()[long(self.ctx)] def load_cert(self, certfile, keyfile=None, callback=util.passphrase_callback): """Load certificate and private key into the context. @param certfile: File that contains the PEM-encoded certificate. @type certfile: str @param keyfile: File that contains the PEM-encoded private key. Default value of None indicates that the private key is to be found in 'certfile'. @type keyfile: str @param callback: Callable object to be invoked if the private key is passphrase-protected. Default callback provides a simple terminal-style input for the passphrase. """ m2.ssl_ctx_passphrase_callback(self.ctx, callback) m2.ssl_ctx_use_cert(self.ctx, certfile) if not keyfile: keyfile = certfile m2.ssl_ctx_use_privkey(self.ctx, keyfile) if not m2.ssl_ctx_check_privkey(self.ctx): raise ValueError('public/private key mismatch') def load_cert_chain(self, certchainfile, keyfile=None, callback=util.passphrase_callback): """Load certificate chain and private key into the context. @param certchainfile: File object containing the PEM-encoded certificate chain. @type certchainfile: str @param keyfile: File object containing the PEM-encoded private key. Default value of None indicates that the private key is to be found in 'certchainfile'. @type keyfile: str @param callback: Callable object to be invoked if the private key is passphrase-protected. Default callback provides a simple terminal-style input for the passphrase. """ m2.ssl_ctx_passphrase_callback(self.ctx, callback) m2.ssl_ctx_use_cert_chain(self.ctx, certchainfile) if not keyfile: keyfile = certchainfile m2.ssl_ctx_use_privkey(self.ctx, keyfile) if not m2.ssl_ctx_check_privkey(self.ctx): raise ValueError('public/private key mismatch') def set_client_CA_list_from_file(self, cafile): """Load CA certs into the context. These CA certs are sent to the peer during *SSLv3 certificate request*. @param cafile: File object containing one or more PEM-encoded CA certificates concatenated together. @type cafile: str """ m2.ssl_ctx_set_client_CA_list_from_file(self.ctx, cafile) # Deprecated. load_client_CA = load_client_ca = set_client_CA_list_from_file def load_verify_locations(self, cafile=None, capath=None): """Load CA certs into the context. These CA certs are used during verification of the peer's certificate. @param cafile: File containing one or more PEM-encoded CA certificates concatenated together. @type cafile: str @param capath: Directory containing PEM-encoded CA certificates (one certificate per file). @type capath: str """ if cafile is None and capath is None: raise ValueError("cafile and capath can not both be None.") return m2.ssl_ctx_load_verify_locations(self.ctx, cafile, capath) # Deprecated. load_verify_info = load_verify_locations def set_session_id_ctx(self, id): ret = m2.ssl_ctx_set_session_id_context(self.ctx, id) if not ret: raise Err.SSLError(Err.get_error_code(), '') def set_allow_unknown_ca(self, ok): """Set the context to accept/reject a peer certificate if the certificate's CA is unknown. @param ok: True to accept, False to reject. @type ok: boolean """ self.allow_unknown_ca = ok def get_allow_unknown_ca(self): """Get the context's setting that accepts/rejects a peer certificate if the certificate's CA is unknown. """ return self.allow_unknown_ca def set_verify(self, mode, depth, callback=None): """ Set verify options. Most applications will need to call this method with the right options to make a secure SSL connection. @param mode: The verification mode to use. Typically at least SSL.verify_peer is used. Clients would also typically add SSL.verify_fail_if_no_peer_cert. @type mode: int @param depth: The maximum allowed depth of the certificate chain returned by the peer. @type depth: int @param callback: Callable that can be used to specify custom verification checks. """ if callback is None: m2.ssl_ctx_set_verify_default(self.ctx, mode) else: m2.ssl_ctx_set_verify(self.ctx, mode, callback) m2.ssl_ctx_set_verify_depth(self.ctx, depth) def get_verify_mode(self): return m2.ssl_ctx_get_verify_mode(self.ctx) def get_verify_depth(self): return m2.ssl_ctx_get_verify_depth(self.ctx) def set_tmp_dh(self, dhpfile): """Load ephemeral DH parameters into the context. @param dhpfile: File object containing the PEM-encoded DH parameters. @type dhpfile: str """ f = BIO.openfile(dhpfile) dhp = m2.dh_read_parameters(f.bio_ptr()) return m2.ssl_ctx_set_tmp_dh(self.ctx, dhp) def set_tmp_dh_callback(self, callback=None): if callback is not None: m2.ssl_ctx_set_tmp_dh_callback(self.ctx, callback) def set_tmp_rsa(self, rsa): """Load ephemeral RSA key into the context. @param rsa: M2Crypto.RSA.RSA instance. """ if isinstance(rsa, RSA.RSA): return m2.ssl_ctx_set_tmp_rsa(self.ctx, rsa.rsa) else: raise TypeError("Expected an instance of RSA.RSA, got %s." % rsa) def set_tmp_rsa_callback(self, callback=None): if callback is not None: m2.ssl_ctx_set_tmp_rsa_callback(self.ctx, callback) def set_info_callback(self, callback=cb.ssl_info_callback): """ Set a callback function that can be used to get state information about the SSL connections that are created from this context. @param callback: Callback function. The default prints information to stderr. """ m2.ssl_ctx_set_info_callback(self.ctx, callback) def set_cipher_list(self, cipher_list): return m2.ssl_ctx_set_cipher_list(self.ctx, cipher_list) def add_session(self, session): return m2.ssl_ctx_add_session(self.ctx, session._ptr()) def remove_session(self, session): return m2.ssl_ctx_remove_session(self.ctx, session._ptr()) def get_session_timeout(self): return m2.ssl_ctx_get_session_timeout(self.ctx) def set_session_timeout(self, timeout): return m2.ssl_ctx_set_session_timeout(self.ctx, timeout) def set_session_cache_mode(self, mode): return m2.ssl_ctx_set_session_cache_mode(self.ctx, mode) def get_session_cache_mode(self): return m2.ssl_ctx_get_session_cache_mode(self.ctx) def set_options(self, op): return m2.ssl_ctx_set_options(self.ctx, op) def get_cert_store(self): """ Get the certificate store associated with this context. @warning: The store is NOT refcounted, and as such can not be relied to be valid once the context goes away or is changed. """ return X509.X509_Store(m2.ssl_ctx_get_cert_store(self.ctx)) M2Crypto-0.22.6rc4/M2Crypto/SSL/SSLServer.py0000664000175000017500000000271412607370517020453 0ustar matejmatej00000000000000"""SSLServer Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" __all__ = ['SSLServer', 'ForkingSSLServer', 'ThreadingSSLServer'] # Python import socket, SocketServer # M2Crypto from Connection import Connection from M2Crypto.SSL import SSLError from M2Crypto import m2 class SSLServer(SocketServer.TCPServer): def __init__(self, server_address, RequestHandlerClass, ssl_context, bind_and_activate=True): """ Superclass says: Constructor. May be extended, do not override. This class says: Ho-hum. """ SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass) self.ssl_ctx=ssl_context self.socket=Connection(self.ssl_ctx) if bind_and_activate: self.server_bind() self.server_activate() def handle_request(self): request = None client_address = None try: request, client_address = self.get_request() if self.verify_request(request, client_address): self.process_request(request, client_address) except SSLError: self.handle_error(request, client_address) def handle_error(self, request, client_address): print '-'*40 import traceback traceback.print_exc() print '-'*40 class ForkingSSLServer(SocketServer.ForkingMixIn, SSLServer): pass class ThreadingSSLServer(SocketServer.ThreadingMixIn, SSLServer): pass M2Crypto-0.22.6rc4/M2Crypto/SSL/Session.py0000664000175000017500000000274212607370517020247 0ustar matejmatej00000000000000"""SSL Session Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" __all__ = ['Session', 'load_session'] from M2Crypto import BIO, Err, m2 class Session: m2_ssl_session_free = m2.ssl_session_free def __init__(self, session, _pyfree=0): assert session is not None self.session = session self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_ssl_session_free(self.session) def _ptr(self): return self.session def as_text(self): buf = BIO.MemoryBuffer() m2.ssl_session_print(buf.bio_ptr(), self.session) return buf.read_all() def as_der(self): buf = BIO.MemoryBuffer() m2.i2d_ssl_session(buf.bio_ptr(), self.session) return buf.read_all() def write_bio(self, bio): return m2.ssl_session_write_bio(bio.bio_ptr(), self.session) def get_time(self): return m2.ssl_session_get_time(self.session) def set_time(self, t): return m2.ssl_session_set_time(self.session, t) def get_timeout(self): return m2.ssl_session_get_timeout(self.session) def set_timeout(self, t): return m2.ssl_session_set_timeout(self.session, t) def load_session(pemfile): f = BIO.openfile(pemfile) cptr = m2.ssl_session_read_pem(f.bio_ptr()) f.close() if cptr is None: from M2Crypto.SSL import SSLError raise SSLError(Err.get_error()) return Session(cptr, 1) M2Crypto-0.22.6rc4/M2Crypto/SSL/TwistedProtocolWrapper.py0000664000175000017500000003600612607370517023332 0ustar matejmatej00000000000000""" Make Twisted use M2Crypto for SSL Copyright (c) 2004-2007 Open Source Applications Foundation. All rights reserved. """ __all__ = ['connectSSL', 'connectTCP', 'listenSSL', 'listenTCP', 'TLSProtocolWrapper'] import twisted.protocols.policies as policies import twisted.internet.reactor from twisted.protocols.policies import ProtocolWrapper from twisted.internet.interfaces import ITLSTransport from zope.interface import implements import M2Crypto # for M2Crypto.BIO.BIOError from M2Crypto import m2, X509 from M2Crypto.SSL import Checker def _alwaysSucceedsPostConnectionCheck(peerX509, expectedHost): return 1 def connectSSL(host, port, factory, contextFactory, timeout=30, bindAddress=None, reactor=twisted.internet.reactor, postConnectionCheck=Checker.Checker()): """ A convenience function to start an SSL/TLS connection using Twisted. See IReactorSSL interface in Twisted. """ wrappingFactory = policies.WrappingFactory(factory) wrappingFactory.protocol = lambda factory, wrappedProtocol: \ TLSProtocolWrapper(factory, wrappedProtocol, startPassThrough=0, client=1, contextFactory=contextFactory, postConnectionCheck=postConnectionCheck) return reactor.connectTCP(host, port, wrappingFactory, timeout, bindAddress) def connectTCP(host, port, factory, timeout=30, bindAddress=None, reactor=twisted.internet.reactor, postConnectionCheck=Checker.Checker()): """ A convenience function to start a TCP connection using Twisted. NOTE: You must call startTLS(ctx) to go into SSL/TLS mode. See IReactorTCP interface in Twisted. """ wrappingFactory = policies.WrappingFactory(factory) wrappingFactory.protocol = lambda factory, wrappedProtocol: \ TLSProtocolWrapper(factory, wrappedProtocol, startPassThrough=1, client=1, contextFactory=None, postConnectionCheck=postConnectionCheck) return reactor.connectTCP(host, port, wrappingFactory, timeout, bindAddress) def listenSSL(port, factory, contextFactory, backlog=5, interface='', reactor=twisted.internet.reactor, postConnectionCheck=_alwaysSucceedsPostConnectionCheck): """ A convenience function to listen for SSL/TLS connections using Twisted. See IReactorSSL interface in Twisted. """ wrappingFactory = policies.WrappingFactory(factory) wrappingFactory.protocol = lambda factory, wrappedProtocol: \ TLSProtocolWrapper(factory, wrappedProtocol, startPassThrough=0, client=0, contextFactory=contextFactory, postConnectionCheck=postConnectionCheck) return reactor.listenTCP(port, wrappingFactory, backlog, interface) def listenTCP(port, factory, backlog=5, interface='', reactor=twisted.internet.reactor, postConnectionCheck=None): """ A convenience function to listen for TCP connections using Twisted. NOTE: You must call startTLS(ctx) to go into SSL/TLS mode. See IReactorTCP interface in Twisted. """ wrappingFactory = policies.WrappingFactory(factory) wrappingFactory.protocol = lambda factory, wrappedProtocol: \ TLSProtocolWrapper(factory, wrappedProtocol, startPassThrough=1, client=0, contextFactory=None, postConnectionCheck=postConnectionCheck) return reactor.listenTCP(port, wrappingFactory, backlog, interface) class _BioProxy: """ The purpose of this class is to eliminate the __del__ method from TLSProtocolWrapper, and thus letting it be garbage collected. """ m2_bio_free_all = m2.bio_free_all def __init__(self, bio): self.bio = bio def _ptr(self): return self.bio def __del__(self): if self.bio is not None: self.m2_bio_free_all(self.bio) class _SSLProxy: """ The purpose of this class is to eliminate the __del__ method from TLSProtocolWrapper, and thus letting it be garbage collected. """ m2_ssl_free = m2.ssl_free def __init__(self, ssl): self.ssl = ssl def _ptr(self): return self.ssl def __del__(self): if self.ssl is not None: self.m2_ssl_free(self.ssl) class TLSProtocolWrapper(ProtocolWrapper): """ A SSL/TLS protocol wrapper to be used with Twisted. Typically you would not use this class directly. Use connectTCP, connectSSL, listenTCP, listenSSL functions defined above, which will hook in this class. """ implements(ITLSTransport) def __init__(self, factory, wrappedProtocol, startPassThrough, client, contextFactory, postConnectionCheck): """ @param factory: @param wrappedProtocol: @param startPassThrough: If true we won't encrypt at all. Need to call startTLS() later to switch to SSL/TLS. @param client: True if this should be a client protocol. @param contextFactory: Factory that creates SSL.Context objects. The called function is getContext(). @param postConnectionCheck: The post connection check callback that will be called just after connection has been established but before any real data has been exchanged. The first argument to this function is an X509 object, the second is the expected host name string. """ #ProtocolWrapper.__init__(self, factory, wrappedProtocol) #XXX: Twisted 2.0 has a new addition where the wrappingFactory is # set as the factory of the wrappedProtocol. This is an issue # as the wrap should be transparent. What we want is # the factory of the wrappedProtocol to be the wrappedFactory and # not the outer wrappingFactory. This is how it was implemented in # Twisted 1.3 self.factory = factory self.wrappedProtocol = wrappedProtocol # wrappedProtocol == client/server instance # factory.wrappedFactory == client/server factory self.data = '' # Clear text to encrypt and send self.encrypted = '' # Encrypted data we need to decrypt and pass on self.tlsStarted = 0 # SSL/TLS mode or pass through self.checked = 0 # Post connection check done or not self.isClient = client self.helloDone = 0 # True when hello has been sent if postConnectionCheck is None: self.postConnectionCheck = _alwaysSucceedsPostConnectionCheck else: self.postConnectionCheck = postConnectionCheck if not startPassThrough: self.startTLS(contextFactory.getContext()) def clear(self): """ Clear this instance, after which it is ready for reuse. """ if getattr(self, 'tlsStarted', 0): self.sslBio = None self.ssl = None self.internalBio = None self.networkBio = None self.data = '' self.encrypted = '' self.tlsStarted = 0 self.checked = 0 self.isClient = 1 self.helloDone = 0 # We can reuse self.ctx and it will be deleted automatically # when this instance dies def startTLS(self, ctx): """ Start SSL/TLS. If this is not called, this instance just passes data through untouched. """ # NOTE: This method signature must match the startTLS() method Twisted # expects transports to have. This will be called automatically # by Twisted in STARTTLS situations, for example with SMTP. if self.tlsStarted: raise Exception, 'TLS already started' self.ctx = ctx self.internalBio = m2.bio_new(m2.bio_s_bio()) m2.bio_set_write_buf_size(self.internalBio, 0) self.networkBio = _BioProxy(m2.bio_new(m2.bio_s_bio())) m2.bio_set_write_buf_size(self.networkBio._ptr(), 0) m2.bio_make_bio_pair(self.internalBio, self.networkBio._ptr()) self.sslBio = _BioProxy(m2.bio_new(m2.bio_f_ssl())) self.ssl = _SSLProxy(m2.ssl_new(self.ctx.ctx)) if self.isClient: m2.ssl_set_connect_state(self.ssl._ptr()) else: m2.ssl_set_accept_state(self.ssl._ptr()) m2.ssl_set_bio(self.ssl._ptr(), self.internalBio, self.internalBio) m2.bio_set_ssl(self.sslBio._ptr(), self.ssl._ptr(), m2.bio_noclose) # Need this for writes that are larger than BIO pair buffers mode = m2.ssl_get_mode(self.ssl._ptr()) m2.ssl_set_mode(self.ssl._ptr(), mode | m2.SSL_MODE_ENABLE_PARTIAL_WRITE | m2.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) self.tlsStarted = 1 def write(self, data): if not self.tlsStarted: ProtocolWrapper.write(self, data) return try: encryptedData = self._encrypt(data) ProtocolWrapper.write(self, encryptedData) self.helloDone = 1 except M2Crypto.BIO.BIOError, e: # See http://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS # for the error codes returned by SSL_get_verify_result. e.args = (m2.ssl_get_verify_result(self.ssl._ptr()), e.args[0]) raise e def writeSequence(self, data): if not self.tlsStarted: ProtocolWrapper.writeSequence(self, ''.join(data)) return self.write(''.join(data)) def loseConnection(self): # XXX Do we need to do m2.ssl_shutdown(self.ssl._ptr())? ProtocolWrapper.loseConnection(self) def connectionMade(self): ProtocolWrapper.connectionMade(self) if self.tlsStarted and self.isClient and not self.helloDone: self._clientHello() def dataReceived(self, data): if not self.tlsStarted: ProtocolWrapper.dataReceived(self, data) return self.encrypted += data try: while 1: decryptedData = self._decrypt() self._check() encryptedData = self._encrypt() ProtocolWrapper.write(self, encryptedData) ProtocolWrapper.dataReceived(self, decryptedData) if decryptedData == '' and encryptedData == '': break except M2Crypto.BIO.BIOError, e: # See http://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS # for the error codes returned by SSL_get_verify_result. e.args = (m2.ssl_get_verify_result(self.ssl._ptr()), e.args[0]) raise e def connectionLost(self, reason): self.clear() ProtocolWrapper.connectionLost(self, reason) def _check(self): if not self.checked and m2.ssl_is_init_finished(self.ssl._ptr()): x509 = m2.ssl_get_peer_cert(self.ssl._ptr()) if x509 is not None: x509 = X509.X509(x509, 1) if self.isClient: host = self.transport.addr[0] else: host = self.transport.getPeer().host if not self.postConnectionCheck(x509, host): raise Checker.SSLVerificationError, 'post connection check' self.checked = 1 def _clientHello(self): try: # We rely on OpenSSL implicitly starting with client hello # when we haven't yet established an SSL connection encryptedData = self._encrypt(clientHello=1) ProtocolWrapper.write(self, encryptedData) self.helloDone = 1 except M2Crypto.BIO.BIOError, e: # See http://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS # for the error codes returned by SSL_get_verify_result. e.args = (m2.ssl_get_verify_result(self.ssl._ptr()), e.args[0]) raise e def _encrypt(self, data='', clientHello=0): # XXX near mirror image of _decrypt - refactor encryptedData = '' self.data += data # Optimizations to reduce attribute accesses sslBioPtr = self.sslBio._ptr() networkBio = self.networkBio._ptr() m2bio_ctrl_get_write_guarantee = m2.bio_ctrl_get_write_guarantee m2bio_write = m2.bio_write m2bio_should_retry = m2.bio_should_retry m2bio_ctrl_pending = m2.bio_ctrl_pending m2bio_read = m2.bio_read while 1: g = m2bio_ctrl_get_write_guarantee(sslBioPtr) if g > 0 and self.data != '' or clientHello: r = m2bio_write(sslBioPtr, self.data) if r <= 0: assert(m2bio_should_retry(sslBioPtr)) else: assert(self.checked) self.data = self.data[r:] pending = m2bio_ctrl_pending(networkBio) if pending: d = m2bio_read(networkBio, pending) if d is not None: # This is strange, but d can be None encryptedData += d else: assert(m2bio_should_retry(networkBio)) else: break return encryptedData def _decrypt(self, data=''): # XXX near mirror image of _encrypt - refactor self.encrypted += data decryptedData = '' # Optimizations to reduce attribute accesses sslBioPtr = self.sslBio._ptr() networkBio = self.networkBio._ptr() m2bio_ctrl_get_write_guarantee = m2.bio_ctrl_get_write_guarantee m2bio_write = m2.bio_write m2bio_should_retry = m2.bio_should_retry m2bio_ctrl_pending = m2.bio_ctrl_pending m2bio_read = m2.bio_read while 1: g = m2bio_ctrl_get_write_guarantee(networkBio) if g > 0 and self.encrypted != '': r = m2bio_write(networkBio, self.encrypted) if r <= 0: assert(m2bio_should_retry(networkBio)) else: self.encrypted = self.encrypted[r:] pending = m2bio_ctrl_pending(sslBioPtr) if pending: d = m2bio_read(sslBioPtr, pending) if d is not None: # This is strange, but d can be None decryptedData += d else: assert(m2bio_should_retry(sslBioPtr)) else: break return decryptedData M2Crypto-0.22.6rc4/M2Crypto/SSL/__init__.py0000664000175000017500000000152512611255457020361 0ustar matejmatej00000000000000"""M2Crypto SSL services. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import socket # M2Crypto from M2Crypto import m2 class SSLError(Exception): pass class SSLTimeoutError(SSLError, socket.timeout): pass m2.ssl_init(SSLError, SSLTimeoutError) # M2Crypto.SSL from Cipher import Cipher, Cipher_Stack from Context import Context from Connection import Connection from SSLServer import SSLServer, ForkingSSLServer, ThreadingSSLServer from ssl_dispatcher import ssl_dispatcher from timeout import timeout verify_none = m2.SSL_VERIFY_NONE verify_peer = m2.SSL_VERIFY_PEER verify_fail_if_no_peer_cert = m2.SSL_VERIFY_FAIL_IF_NO_PEER_CERT verify_client_once = m2.SSL_VERIFY_CLIENT_ONCE SSL_SENT_SHUTDOWN = m2.SSL_SENT_SHUTDOWN SSL_RECEIVED_SHUTDOWN = m2.SSL_RECEIVED_SHUTDOWN op_all = m2.SSL_OP_ALL op_no_sslv2 = m2.SSL_OP_NO_SSLv2 M2Crypto-0.22.6rc4/M2Crypto/SSL/cb.py0000664000175000017500000000446612607370517017215 0ustar matejmatej00000000000000"""SSL callbacks Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" __all__ = ['unknown_issuer', 'ssl_verify_callback_stub', 'ssl_verify_callback', 'ssl_verify_callback_allow_unknown_ca', 'ssl_info_callback'] # Python import sys # M2Crypto import Context from M2Crypto import m2 def ssl_verify_callback_stub(ssl_ctx_ptr, x509_ptr, errnum, errdepth, ok): # Deprecated return ok unknown_issuer = [ m2.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, m2.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, m2.X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, m2.X509_V_ERR_CERT_UNTRUSTED, ] def ssl_verify_callback(ssl_ctx_ptr, x509_ptr, errnum, errdepth, ok): # Deprecated ssl_ctx = Context.map()[long(ssl_ctx_ptr)] if errnum in unknown_issuer: if ssl_ctx.get_allow_unknown_ca(): sys.stderr.write("policy: %s: permitted...\n" % (m2.x509_get_verify_error(errnum))) sys.stderr.flush() ok = 1 # CRL checking goes here... if ok: if ssl_ctx.get_verify_depth() >= errdepth: ok = 1 else: ok = 0 return ok def ssl_verify_callback_allow_unknown_ca(ok, store): errnum = store.get_error() if errnum in unknown_issuer: ok = 1 return ok # Cribbed from OpenSSL's apps/s_cb.c. def ssl_info_callback(where, ret, ssl_ptr): w = where & ~m2.SSL_ST_MASK if (w & m2.SSL_ST_CONNECT): state = "SSL connect" elif (w & m2.SSL_ST_ACCEPT): state = "SSL accept" else: state = "SSL state unknown" if (where & m2.SSL_CB_LOOP): sys.stderr.write("LOOP: %s: %s\n" % (state, m2.ssl_get_state_v(ssl_ptr))) sys.stderr.flush() return if (where & m2.SSL_CB_EXIT): if not ret: sys.stderr.write("FAILED: %s: %s\n" % (state, m2.ssl_get_state_v(ssl_ptr))) sys.stderr.flush() else: sys.stderr.write("INFO: %s: %s\n" % (state, m2.ssl_get_state_v(ssl_ptr))) sys.stderr.flush() return if (where & m2.SSL_CB_ALERT): if (where & m2.SSL_CB_READ): w = 'read' else: w = 'write' sys.stderr.write("ALERT: %s: %s: %s\n" % \ (w, m2.ssl_get_alert_type_v(ret), m2.ssl_get_alert_desc_v(ret))) sys.stderr.flush() return M2Crypto-0.22.6rc4/M2Crypto/SSL/ssl_dispatcher.py0000664000175000017500000000155212607370517021631 0ustar matejmatej00000000000000"""SSL dispatcher Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" __all__ = ['ssl_dispatcher'] # Python import asyncore, socket # M2Crypto from Connection import Connection from M2Crypto import Err, m2 class ssl_dispatcher(asyncore.dispatcher): def create_socket(self, ssl_context): self.family_and_type=socket.AF_INET, socket.SOCK_STREAM self.ssl_ctx=ssl_context self.socket=Connection(self.ssl_ctx) #self.socket.setblocking(0) self.add_channel() def connect(self, addr): self.socket.setblocking(1) self.socket.connect(addr) self.socket.setblocking(0) def recv(self, buffer_size=4096): """Receive data over SSL.""" return self.socket.recv(buffer_size) def send(self, buffer): """Send data over SSL.""" return self.socket.send(buffer) M2Crypto-0.22.6rc4/M2Crypto/SSL/timeout.py0000664000175000017500000000122412607370517020304 0ustar matejmatej00000000000000"""Support for SSL socket timeouts. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Copyright 2008 Heikki Toivonen. All rights reserved. """ __all__ = ['DEFAULT_TIMEOUT', 'timeout', 'struct_to_timeout', 'struct_size'] import struct from M2Crypto import m2 DEFAULT_TIMEOUT = 600 class timeout: def __init__(self, sec=DEFAULT_TIMEOUT, microsec=0): self.sec = sec self.microsec = microsec def pack(self): return struct.pack('ll', self.sec, self.microsec) def struct_to_timeout(binstr): (s, ms) = struct.unpack('ll', binstr) return timeout(s, ms) def struct_size(): return struct.calcsize('ll') M2Crypto-0.22.6rc4/M2Crypto/ASN1.py0000664000175000017500000001276212607370517016670 0ustar matejmatej00000000000000""" M2Crypto wrapper for OpenSSL ASN1 API. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2005 OSAF. All Rights Reserved. """ import time, datetime import BIO import m2 MBSTRING_FLAG = 0x1000 MBSTRING_ASC = MBSTRING_FLAG | 1 MBSTRING_BMP = MBSTRING_FLAG | 2 class ASN1_Integer: m2_asn1_integer_free = m2.asn1_integer_free def __init__(self, asn1int, _pyfree=0): self.asn1int = asn1int self._pyfree = _pyfree def __cmp__(self, other): return m2.asn1_integer_cmp(self.asn1int, other.asn1int) def __del__(self): if self._pyfree: self.m2_asn1_integer_free(self.asn1int) class ASN1_String: m2_asn1_string_free = m2.asn1_string_free def __init__(self, asn1str, _pyfree=0): self.asn1str = asn1str self._pyfree = _pyfree def __str__(self): buf = BIO.MemoryBuffer() m2.asn1_string_print( buf.bio_ptr(), self.asn1str ) return buf.read_all() def __del__(self): if getattr(self, '_pyfree', 0): self.m2_asn1_string_free(self.asn1str) def _ptr(self): return self.asn1str def as_text(self, flags=0): buf = BIO.MemoryBuffer() m2.asn1_string_print_ex( buf.bio_ptr(), self.asn1str, flags) return buf.read_all() class ASN1_Object: m2_asn1_object_free = m2.asn1_object_free def __init__(self, asn1obj, _pyfree=0): self.asn1obj = asn1obj self._pyfree = _pyfree def __del__(self): if self._pyfree: self.m2_asn1_object_free(self.asn1obj) def _ptr(self): return self.asn1obj class _UTC(datetime.tzinfo): def tzname(self, dt): return "UTC" def dst(self, dt): return datetime.timedelta(0) def utcoffset(self, dt): return datetime.timedelta(0) def __repr__(self): return "" % self.tzname(None) UTC = _UTC() class LocalTimezone(datetime.tzinfo): """ Localtimezone from datetime manual """ def __init__(self): self._stdoffset = datetime.timedelta(seconds = -time.timezone) if time.daylight: self._dstoffset = datetime.timedelta(seconds = -time.altzone) else: self._dstoffset = self._stdoffset self._dstdiff = self._dstoffset - self._stdoffset def utcoffset(self, dt): if self._isdst(dt): return self._dstoffset else: return self._stdoffset def dst(self, dt): if self._isdst(dt): return self._dstdiff else: return datetime.timedelta(0) def tzname(self, dt): return time.tzname[self._isdst(dt)] def _isdst(self, dt): tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1) stamp = time.mktime(tt) tt = time.localtime(stamp) return tt.tm_isdst > 0 class ASN1_UTCTIME: _ssl_months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] m2_asn1_utctime_free = m2.asn1_utctime_free def __init__(self, asn1_utctime=None, _pyfree=0): if asn1_utctime is not None: assert m2.asn1_utctime_type_check(asn1_utctime), "'asn1_utctime' type error'" self.asn1_utctime = asn1_utctime self._pyfree = _pyfree else: self.asn1_utctime = m2.asn1_utctime_new () self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_asn1_utctime_free(self.asn1_utctime) def __str__(self): assert m2.asn1_utctime_type_check(self.asn1_utctime), "'asn1_utctime' type error'" buf = BIO.MemoryBuffer() m2.asn1_utctime_print( buf.bio_ptr(), self.asn1_utctime ) return buf.read_all() def _ptr(self): assert m2.asn1_utctime_type_check(self.asn1_utctime), "'asn1_utctime' type error'" return self.asn1_utctime def set_string (self, string): """ Set time from UTC string. """ assert m2.asn1_utctime_type_check(self.asn1_utctime), "'asn1_utctime' type error'" return m2.asn1_utctime_set_string( self.asn1_utctime, string ) def set_time (self, time): """ Set time from seconds since epoch (long). """ assert m2.asn1_utctime_type_check(self.asn1_utctime), "'asn1_utctime' type error'" return m2.asn1_utctime_set( self.asn1_utctime, time ) def get_datetime(self): date = str(self) timezone = None if ' ' not in date: raise ValueError("Invalid date: %s" % date) month, rest = date.split(' ', 1) if month not in self._ssl_months: raise ValueError("Invalid date %s: Invalid month: %s" % (date, month)) if rest.endswith(' GMT'): timezone = UTC rest = rest[:-4] tm = list(time.strptime(rest, "%d %H:%M:%S %Y"))[:6] tm[1] = self._ssl_months.index(month) + 1 tm.append(0) tm.append(timezone) return datetime.datetime(*tm) def set_datetime(self, date): local = LocalTimezone() if date.tzinfo is None: date = date.replace(tzinfo=local) date = date.astimezone(local) return self.set_time(int(time.mktime(date.timetuple()))) M2Crypto-0.22.6rc4/M2Crypto/AuthCookie.py0000664000175000017500000000601512607370517020213 0ustar matejmatej00000000000000"""Secure Authenticator Cookies Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" # M2Crypto import Rand, m2 # Python. Cookie is bundled with Python 2.x. import Cookie, binascii, re, time _MIX_FORMAT = 'exp=%s&data=%s&digest=' _MIX_RE = re.compile('exp=(\d+\.\d+)&data=(.+)&digest=(\S*)') def mix(expiry, data, format=_MIX_FORMAT): return format % (repr(expiry), data) def unmix(dough, regex=_MIX_RE): mo = regex.match(dough) if mo: return float(mo.group(1)), mo.group(2) else: return None def unmix3(dough, regex=_MIX_RE): mo = regex.match(dough) if mo: return float(mo.group(1)), mo.group(2), mo.group(3) else: return None _TOKEN = '_M2AUTH_' class AuthCookieJar: _keylen = 20 def __init__(self): self._key = Rand.rand_bytes(self._keylen) def _hmac(self, key, data): return binascii.b2a_base64(m2.hmac(key, data, m2.sha1()))[:-1] def makeCookie(self, expiry, data): dough = mix(expiry, data) return AuthCookie(expiry, data, dough, self._hmac(self._key, dough)) def isGoodCookie(self, cookie): assert isinstance(cookie, AuthCookie) if cookie.isExpired(): return 0 c = self.makeCookie(cookie._expiry, cookie._data) return (c._expiry == cookie._expiry) \ and (c._data == cookie._data) \ and (c._mac == cookie._mac) \ and (c.output() == cookie.output()) def isGoodCookieString(self, cookie_str): c = Cookie.SmartCookie() c.load(cookie_str) if not c.has_key(_TOKEN): return 0 undough = unmix3(c[_TOKEN].value) if undough is None: return 0 exp, data, mac = undough c2 = self.makeCookie(exp, data) return (not c2.isExpired()) and (c2._mac == mac) class AuthCookie: def __init__(self, expiry, data, dough, mac): self._expiry = expiry self._data = data self._mac = mac self._cookie = Cookie.SmartCookie() self._cookie[_TOKEN] = '%s%s' % (dough, mac) self._name = '%s%s' % (dough, mac) # XXX WebKit only. def expiry(self): """Return the cookie's expiry time.""" return self._expiry def data(self): """Return the data portion of the cookie.""" return self._data def mac(self): """Return the cookie's MAC.""" return self._mac def output(self): """Return the cookie's output in "Set-Cookie" format.""" return self._cookie.output() def value(self): """Return the cookie's output minus the "Set-Cookie: " portion. """ return self._cookie[_TOKEN].value def isExpired(self): """Return 1 if the cookie has expired, 0 otherwise.""" return (time.time() > self._expiry) # XXX Following methods are for WebKit only. These should be pushed # to WKAuthCookie. def name(self): return self._name def headerValue(self): return self.value() M2Crypto-0.22.6rc4/M2Crypto/BIO.py0000664000175000017500000001633512607370517016577 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL BIO API. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import m2 # Deprecated from m2 import bio_do_handshake as bio_do_ssl_handshake from cStringIO import StringIO class BIOError(Exception): pass m2.bio_init(BIOError) class BIO: """Abstract object interface to the BIO API.""" m2_bio_free = m2.bio_free def __init__(self, bio=None, _pyfree=0, _close_cb=None): self.bio = bio self._pyfree = _pyfree self._close_cb = _close_cb self.closed = 0 self.write_closed = 0 def __del__(self): if self._pyfree: self.m2_bio_free(self.bio) def _ptr(self): return self.bio # Deprecated. bio_ptr = _ptr def fileno(self): return m2.bio_get_fd(self.bio) def readable(self): return not self.closed def read(self, size=None): if not self.readable(): raise IOError, 'cannot read' if size is None: buf = StringIO() while 1: data = m2.bio_read(self.bio, 4096) if not data: break buf.write(data) return buf.getvalue() elif size == 0: return '' elif size < 0: raise ValueError, 'read count is negative' else: return m2.bio_read(self.bio, size) def readline(self, size=4096): if not self.readable(): raise IOError, 'cannot read' buf = m2.bio_gets(self.bio, size) return buf def readlines(self, sizehint='ignored'): if not self.readable(): raise IOError, 'cannot read' lines=[] while 1: buf=m2.bio_gets(self.bio, 4096) if buf is None: break lines.append(buf) return lines def writeable(self): return (not self.closed) and (not self.write_closed) def write(self, data): if not self.writeable(): raise IOError, 'cannot write' return m2.bio_write(self.bio, data) def write_close(self): self.write_closed = 1 def flush(self): m2.bio_flush(self.bio) def reset(self): """ Sets the bio to its initial state """ return m2.bio_reset(self.bio) def close(self): self.closed = 1 if self._close_cb: self._close_cb() def should_retry(self): """ Can the call be attempted again, or was there an error ie do_handshake """ return m2.bio_should_retry(self.bio) def should_read(self): """ Returns whether the cause of the condition is the bio should read more data """ return m2.bio_should_read(self.bio) def should_write(self): """ Returns whether the cause of the condition is the bio should write more data """ return m2.bio_should_write(self.bio) class MemoryBuffer(BIO): """ Object interface to BIO_s_mem. Empirical testing suggests that this class performs less well than cStringIO, because cStringIO is implemented in C, whereas this class is implemented in Python. Thus, the recommended practice is to use cStringIO for regular work and convert said cStringIO object to a MemoryBuffer object only when necessary. """ def __init__(self, data=None): BIO.__init__(self) self.bio = m2.bio_new(m2.bio_s_mem()) self._pyfree = 1 if data is not None: m2.bio_write(self.bio, data) def __len__(self): return m2.bio_ctrl_pending(self.bio) def read(self, size=0): if not self.readable(): raise IOError, 'cannot read' if size: return m2.bio_read(self.bio, size) else: return m2.bio_read(self.bio, m2.bio_ctrl_pending(self.bio)) # Backwards-compatibility. getvalue = read_all = read def write_close(self): self.write_closed = 1 m2.bio_set_mem_eof_return(self.bio, 0) close = write_close class File(BIO): """ Object interface to BIO_s_fp. This class interfaces Python to OpenSSL functions that expect BIO *. For general file manipulation in Python, use Python's builtin file object. """ def __init__(self, pyfile, close_pyfile=1): BIO.__init__(self, _pyfree=1) self.pyfile = pyfile self.close_pyfile = close_pyfile self.bio = m2.bio_new_fp(pyfile, 0) def close(self): self.closed = 1 if self.close_pyfile: self.pyfile.close() def openfile(filename, mode='rb'): return File(open(filename, mode)) class IOBuffer(BIO): """ Object interface to BIO_f_buffer. Its principal function is to be BIO_push()'ed on top of a BIO_f_ssl, so that makefile() of said underlying SSL socket works. """ m2_bio_pop = m2.bio_pop m2_bio_free = m2.bio_free def __init__(self, under_bio, mode='rwb', _pyfree=1): BIO.__init__(self, _pyfree=_pyfree) self.io = m2.bio_new(m2.bio_f_buffer()) self.bio = m2.bio_push(self.io, under_bio._ptr()) # This reference keeps the underlying BIO alive while we're not closed. self._under_bio = under_bio if 'w' in mode: self.write_closed = 0 else: self.write_closed = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_bio_pop(self.bio) self.m2_bio_free(self.io) def close(self): BIO.close(self) class CipherStream(BIO): """ Object interface to BIO_f_cipher. """ SALT_LEN = m2.PKCS5_SALT_LEN m2_bio_pop = m2.bio_pop m2_bio_free = m2.bio_free def __init__(self, obio): BIO.__init__(self, _pyfree=1) self.obio = obio self.bio = m2.bio_new(m2.bio_f_cipher()) self.closed = 0 def __del__(self): if not getattr(self, 'closed', 1): self.close() def close(self): self.m2_bio_pop(self.bio) self.m2_bio_free(self.bio) self.closed = 1 def write_close(self): self.obio.write_close() def set_cipher(self, algo, key, iv, op): cipher = getattr(m2, algo, None) if cipher is None: raise ValueError, ('unknown cipher', algo) m2.bio_set_cipher(self.bio, cipher(), key, iv, op) m2.bio_push(self.bio, self.obio._ptr()) class SSLBio(BIO): """ Object interface to BIO_f_ssl """ def __init__(self, _pyfree=1): BIO.__init__(self, _pyfree) self.bio = m2.bio_new(m2.bio_f_ssl()) self.closed = 0 def set_ssl(self, conn, close_flag=m2.bio_noclose): """ Sets the bio to the SSL pointer which is contained in the connection object. """ self._pyfree = 0 m2.bio_set_ssl(self.bio, conn.ssl, close_flag) if close_flag == m2.bio_noclose: conn.set_ssl_close_flag(m2.bio_close) def do_handshake(self): """ Do the handshake. Return 1 if the handshake completes Return 0 or a negative number if there is a problem """ return m2.bio_do_handshake(self.bio) M2Crypto-0.22.6rc4/M2Crypto/BN.py0000775000175000017500000000246212607370517016464 0ustar matejmatej00000000000000""" M2Crypto wrapper for OpenSSL BN (BIGNUM) API. Copyright (c) 2005 Open Source Applications Foundation. All rights reserved. """ import m2 def rand(bits, top=-1, bottom=0): """ Generate cryptographically strong random number. @param bits: Length of random number in bits. @param top: If -1, the most significant bit can be 0. If 0, the most significant bit is 1, and if 1, the two most significant bits will be 1. @param bottom: If bottom is true, the number will be odd. """ return m2.bn_rand(bits, top, bottom) def rand_range(range): """ Generate a random number in a range. @param range: Upper limit for range. @return: A random number in the range [0, range) """ return m2.bn_rand_range(range) def randfname(length): """ Return a random filename, which is simply a string where all the characters are from the set [a-zA-Z0-9]. @param length: Length of filename to return. @type length: int @return: random filename string """ letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890' lettersLen = len(letters) fname = [] for x in range(length): fname += [letters[m2.bn_rand_range(lettersLen)]] return ''.join(fname) M2Crypto-0.22.6rc4/M2Crypto/DH.py0000664000175000017500000000450612607370517016456 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL DH API. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from util import genparam_callback import BIO, Err, m2 class DHError(Exception): pass m2.dh_init(DHError) class DH: """ Object interface to the Diffie-Hellman key exchange protocol. """ m2_dh_free = m2.dh_free def __init__(self, dh, _pyfree=0): assert m2.dh_type_check(dh) self.dh = dh self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_dh_free(self.dh) def __len__(self): assert m2.dh_type_check(self.dh), "'dh' type error" return m2.dh_size(self.dh) def __getattr__(self, name): if name in ('p', 'g', 'pub', 'priv'): method = getattr(m2, 'dh_get_%s' % (name,)) assert m2.dh_type_check(self.dh), "'dh' type error" return method(self.dh) else: raise AttributeError def __setattr__(self, name, value): if name in ('p', 'g'): raise DHError, 'set (p, g) via set_params()' elif name in ('pub','priv'): raise DHError, 'generate (pub, priv) via gen_key()' else: self.__dict__[name] = value def _ptr(self): return self.dh def check_params(self): assert m2.dh_type_check(self.dh), "'dh' type error" return m2.dh_check(self.dh) def gen_key(self): assert m2.dh_type_check(self.dh), "'dh' type error" m2.dh_generate_key(self.dh) def compute_key(self, pubkey): assert m2.dh_type_check(self.dh), "'dh' type error" return m2.dh_compute_key(self.dh, pubkey) def print_params(self, bio): assert m2.dh_type_check(self.dh), "'dh' type error" return m2.dhparams_print(bio._ptr(), self.dh) def gen_params(plen, g, callback=genparam_callback): return DH(m2.dh_generate_parameters(plen, g, callback), 1) def load_params(file): bio = BIO.openfile(file) return load_params_bio(bio) def load_params_bio(bio): return DH(m2.dh_read_parameters(bio._ptr()), 1) def set_params(p, g): dh = m2.dh_new() m2.dh_set_p(dh, p) m2.dh_set_g(dh, g) return DH(dh, 1) #def free_params(cptr): # m2.dh_free(cptr) DH_GENERATOR_2 = m2.DH_GENERATOR_2 DH_GENERATOR_5 = m2.DH_GENERATOR_5 M2Crypto-0.22.6rc4/M2Crypto/DSA.py0000664000175000017500000003330312607370517016567 0ustar matejmatej00000000000000""" M2Crypto wrapper for OpenSSL DSA API. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004 OSAF. All Rights Reserved. """ import sys import util, BIO, m2 class DSAError(Exception): pass m2.dsa_init(DSAError) class DSA: """ This class is a context supporting DSA key and parameter values, signing and verifying. Simple example:: from M2Crypto import EVP, DSA, util message = 'Kilroy was here!' md = EVP.MessageDigest('sha1') md.update(message) digest = md.final() dsa = DSA.gen_params(1024) dsa.gen_key() r, s = dsa.sign(digest) good = dsa.verify(digest, r, s) if good: print ' ** success **' else: print ' ** verification failed **' """ m2_dsa_free = m2.dsa_free def __init__(self, dsa, _pyfree=0): """ Use one of the factory functions to create an instance. """ assert m2.dsa_type_check(dsa), "'dsa' type error" self.dsa = dsa self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_dsa_free(self.dsa) def __len__(self): """ Return the key length. @rtype: int @return: the DSA key length in bits """ assert m2.dsa_type_check(self.dsa), "'dsa' type error" return m2.dsa_keylen(self.dsa) def __getattr__(self, name): """ Return specified DSA parameters and key values. @type name: str @param name: name of variable to be returned. Must be one of 'p', 'q', 'g', 'pub', 'priv'. @rtype: str @return: value of specified variable (a "byte string") """ if name in ['p', 'q', 'g', 'pub', 'priv']: method = getattr(m2, 'dsa_get_%s' % (name,)) assert m2.dsa_type_check(self.dsa), "'dsa' type error" return method(self.dsa) else: raise AttributeError def __setattr__(self, name, value): if name in ['p', 'q', 'g']: raise DSAError('set (p, q, g) via set_params()') elif name in ['pub','priv']: raise DSAError('generate (pub, priv) via gen_key()') else: self.__dict__[name] = value def set_params(self, p, q, g): """ Set new parameters. @warning: This does not change the private key, so it may be unsafe to use this method. It is better to use gen_params function to create a new DSA object. """ m2.dsa_set_p(self.dsa, p) m2.dsa_set_q(self.dsa, q) m2.dsa_set_g(self.dsa, g) def gen_key(self): """ Generate a key pair. """ assert m2.dsa_type_check(self.dsa), "'dsa' type error" m2.dsa_gen_key(self.dsa) def save_params(self, filename): """ Save the DSA parameters to a file. @type filename: str @param filename: Save the DSA parameters to this file. @return: 1 (true) if successful """ bio = BIO.openfile(filename, 'wb') ret = m2.dsa_write_params_bio(self.dsa, bio._ptr()) bio.close() return ret def save_params_bio(self, bio): """ Save DSA parameters to a BIO object. @type bio: M2Crypto.BIO object @param bio: Save DSA parameters to this object. @return: 1 (true) if successful """ return m2.dsa_write_params_bio(self.dsa, bio._ptr()) def save_key(self, filename, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the DSA key pair to a file. @type filename: str @param filename: Save the DSA key pair to this file. @type cipher: str @param cipher: name of symmetric key algorithm and mode to encrypt the private key. @return: 1 (true) if successful """ bio = BIO.openfile(filename, 'wb') ret = self.save_key_bio(bio, cipher, callback) bio.close() return ret def save_key_bio(self, bio, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save DSA key pair to a BIO object. @type bio: M2Crypto.BIO object @param bio: Save DSA parameters to this object. @type cipher: str @param cipher: name of symmetric key algorithm and mode to encrypt the private key. @return: 1 (true) if successful """ if cipher is None: return m2.dsa_write_key_bio_no_cipher(self.dsa, bio._ptr(), callback) else: ciph = getattr(m2, cipher, None) if ciph is None: raise DSAError('no such cipher: %s' % cipher) else: ciph = ciph() return m2.dsa_write_key_bio(self.dsa, bio._ptr(), ciph, callback) def save_pub_key(self, filename): """ Save the DSA public key (with parameters) to a file. @type filename: str @param filename: Save DSA public key (with parameters) to this file. @return: 1 (true) if successful """ bio = BIO.openfile(filename, 'wb') ret = self.save_pub_key_bio(bio) bio.close() return ret def save_pub_key_bio(self, bio): """ Save DSA public key (with parameters) to a BIO object. @type bio: M2Crypto.BIO object @param bio: Save DSA public key (with parameters) to this object. @return: 1 (true) if successful """ return m2.dsa_write_pub_key_bio(self.dsa, bio._ptr()) def sign(self, digest): """ Sign the digest. @type digest: str @param digest: SHA-1 hash of message (same as output from MessageDigest, a "byte string") @rtype: tuple @return: DSA signature, a tuple of two values, r and s, both "byte strings". """ assert self.check_key(), 'key is not initialised' return m2.dsa_sign(self.dsa, digest) def verify(self, digest, r, s): """ Verify a newly calculated digest against the signature values r and s. @type digest: str @param digest: SHA-1 hash of message (same as output from MessageDigest, a "byte string") @type r: str @param r: r value of the signature, a "byte string" @type s: str @param s: s value of the signature, a "byte string" @rtype: int @return: 1 (true) if verify succeeded, 0 if failed """ assert self.check_key(), 'key is not initialised' return m2.dsa_verify(self.dsa, digest, r, s) def sign_asn1(self, digest): assert self.check_key(), 'key is not initialised' return m2.dsa_sign_asn1(self.dsa, digest) def verify_asn1(self, digest, blob): assert self.check_key(), 'key is not initialised' return m2.dsa_verify_asn1(self.dsa, digest, blob) def check_key(self): """ Check to be sure the DSA object has a valid private key. @rtype: int @return: 1 (true) if a valid private key """ assert m2.dsa_type_check(self.dsa), "'dsa' type error" return m2.dsa_check_key(self.dsa) class DSA_pub(DSA): """ This class is a DSA context that only supports a public key and verification. It does NOT support a private key or signing. """ def sign(self, *argv): raise DSAError('DSA_pub object has no private key') sign_asn1 = sign def check_key(self): return m2.dsa_check_pub_key(self.dsa) save_key = DSA.save_pub_key save_key_bio = DSA.save_pub_key_bio #--------------------------------------------------------------- # factories and other functions def gen_params(bits, callback=util.genparam_callback): """ Factory function that generates DSA parameters and instantiates a DSA object from the output. @type bits: int @param bits: The length of the prime to be generated. If 'bits' < 512, it is set to 512. @type callback: function @param callback: A Python callback object that will be invoked during parameter generation; it usual purpose is to provide visual feedback. @rtype: DSA @return: instance of DSA. """ dsa = m2.dsa_generate_parameters(bits, callback) if dsa is None: raise DSAError('problem generating DSA parameters') return DSA(dsa, 1) def set_params(p, q, g): """ Factory function that instantiates a DSA object with DSA parameters. @type p: str @param p: value of p, a "byte string" @type q: str @param q: value of q, a "byte string" @type g: str @param g: value of g, a "byte string" @rtype: DSA @return: instance of DSA. """ dsa = m2.dsa_new() m2.dsa_set_p(dsa, p) m2.dsa_set_q(dsa, q) m2.dsa_set_g(dsa, g) return DSA(dsa, 1) def load_params(file, callback=util.passphrase_callback): """ Factory function that instantiates a DSA object with DSA parameters from a file. @type file: str @param file: Names the file (a path) that contains the PEM representation of the DSA parameters. @type callback: A Python callable @param callback: A Python callback object that will be invoked if the DSA parameters file is passphrase-protected. @rtype: DSA @return: instance of DSA. """ bio = BIO.openfile(file) ret = load_params_bio(bio, callback) bio.close() return ret def load_params_bio(bio, callback=util.passphrase_callback): """ Factory function that instantiates a DSA object with DSA parameters from a M2Crypto.BIO object. @type bio: M2Crypto.BIO object @param bio: Contains the PEM representation of the DSA parameters. @type callback: A Python callable @param callback: A Python callback object that will be invoked if the DSA parameters file is passphrase-protected. @rtype: DSA @return: instance of DSA. """ dsa = m2.dsa_read_params(bio._ptr(), callback) if dsa is None: raise DSAError('problem loading DSA parameters') return DSA(dsa, 1) def load_key(file, callback=util.passphrase_callback): """ Factory function that instantiates a DSA object from a PEM encoded DSA key pair. @type file: str @param file: Names the file (a path) that contains the PEM representation of the DSA key pair. @type callback: A Python callable @param callback: A Python callback object that will be invoked if the DSA key pair is passphrase-protected. @rtype: DSA @return: instance of DSA. """ bio = BIO.openfile(file) ret = load_key_bio(bio, callback) bio.close() return ret def load_key_bio(bio, callback=util.passphrase_callback): """ Factory function that instantiates a DSA object from a PEM encoded DSA key pair. @type bio: M2Crypto.BIO object @param bio: Contains the PEM representation of the DSA key pair. @type callback: A Python callable @param callback: A Python callback object that will be invoked if the DSA key pair is passphrase-protected. @rtype: DSA @return: instance of DSA. """ dsa = m2.dsa_read_key(bio._ptr(), callback) if not dsa: raise DSAError('problem loading DSA key pair') return DSA(dsa, 1) def load_pub_key(file, callback=util.passphrase_callback): """ Factory function that instantiates a DSA_pub object using a DSA public key contained in PEM file. The PEM file must contain the parameters in addition to the public key. @type file: str @param file: Names the file (a path) that contains the PEM representation of the DSA public key. @type callback: A Python callable @param callback: A Python callback object that will be invoked should the DSA public key be passphrase-protected. @rtype: DSA_pub @return: instance of DSA_pub. """ bio = BIO.openfile(file) ret = load_pub_key_bio(bio, callback) bio.close() return ret def load_pub_key_bio(bio, callback=util.passphrase_callback): """ Factory function that instantiates a DSA_pub object using a DSA public key contained in PEM format. The PEM must contain the parameters in addition to the public key. @type bio: M2Crypto.BIO object @param bio: Contains the PEM representation of the DSA public key (with params). @type callback: A Python callable @param callback: A Python callback object that will be invoked should the DSA public key be passphrase-protected. @rtype: DSA_pub @return: instance of DSA_pub. """ dsapub = m2.dsa_read_pub_key(bio._ptr(), callback) if not dsapub: raise DSAError('problem loading DSA public key') return DSA_pub(dsapub, 1) M2Crypto-0.22.6rc4/M2Crypto/EC.py0000664000175000017500000002524412607370517016454 0ustar matejmatej00000000000000""" M2Crypto wrapper for OpenSSL ECDH/ECDSA API. @requires: OpenSSL 0.9.8 or newer Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved.""" import util, BIO, m2 class ECError(Exception): pass m2.ec_init(ECError) # Curve identifier constants NID_secp112r1 = m2.NID_secp112r1 NID_secp112r2 = m2.NID_secp112r2 NID_secp128r1 = m2.NID_secp128r1 NID_secp128r2 = m2.NID_secp128r2 NID_secp160k1 = m2.NID_secp160k1 NID_secp160r1 = m2.NID_secp160r1 NID_secp160r2 = m2.NID_secp160r2 NID_secp192k1 = m2.NID_secp192k1 NID_secp224k1 = m2.NID_secp224k1 NID_secp224r1 = m2.NID_secp224r1 NID_secp256k1 = m2.NID_secp256k1 NID_secp384r1 = m2.NID_secp384r1 NID_secp521r1 = m2.NID_secp521r1 NID_sect113r1 = m2.NID_sect113r1 NID_sect113r2 = m2.NID_sect113r2 NID_sect131r1 = m2.NID_sect131r1 NID_sect131r2 = m2.NID_sect131r2 NID_sect163k1 = m2.NID_sect163k1 NID_sect163r1 = m2.NID_sect163r1 NID_sect163r2 = m2.NID_sect163r2 NID_sect193r1 = m2.NID_sect193r1 NID_sect193r2 = m2.NID_sect193r2 NID_sect233k1 = m2.NID_sect233k1 # default for secg.org TLS test server NID_sect233r1 = m2.NID_sect233r1 NID_sect239k1 = m2.NID_sect239k1 NID_sect283k1 = m2.NID_sect283k1 NID_sect283r1 = m2.NID_sect283r1 NID_sect409k1 = m2.NID_sect409k1 NID_sect409r1 = m2.NID_sect409r1 NID_sect571k1 = m2.NID_sect571k1 NID_sect571r1 = m2.NID_sect571r1 NID_X9_62_prime192v1 = m2.NID_X9_62_prime192v1 NID_X9_62_prime192v2 = m2.NID_X9_62_prime192v2 NID_X9_62_prime192v3 = m2.NID_X9_62_prime192v3 NID_X9_62_prime239v1 = m2.NID_X9_62_prime239v1 NID_X9_62_prime239v2 = m2.NID_X9_62_prime239v2 NID_X9_62_prime239v3 = m2.NID_X9_62_prime239v3 NID_X9_62_prime256v1 = m2.NID_X9_62_prime256v1 NID_X9_62_c2pnb163v1 = m2.NID_X9_62_c2pnb163v1 NID_X9_62_c2pnb163v2 = m2.NID_X9_62_c2pnb163v2 NID_X9_62_c2pnb163v3 = m2.NID_X9_62_c2pnb163v3 NID_X9_62_c2pnb176v1 = m2.NID_X9_62_c2pnb176v1 NID_X9_62_c2tnb191v1 = m2.NID_X9_62_c2tnb191v1 NID_X9_62_c2tnb191v2 = m2.NID_X9_62_c2tnb191v2 NID_X9_62_c2tnb191v3 = m2.NID_X9_62_c2tnb191v3 NID_X9_62_c2pnb208w1 = m2.NID_X9_62_c2pnb208w1 NID_X9_62_c2tnb239v1 = m2.NID_X9_62_c2tnb239v1 NID_X9_62_c2tnb239v2 = m2.NID_X9_62_c2tnb239v2 NID_X9_62_c2tnb239v3 = m2.NID_X9_62_c2tnb239v3 NID_X9_62_c2pnb272w1 = m2.NID_X9_62_c2pnb272w1 NID_X9_62_c2pnb304w1 = m2.NID_X9_62_c2pnb304w1 NID_X9_62_c2tnb359v1 = m2.NID_X9_62_c2tnb359v1 NID_X9_62_c2pnb368w1 = m2.NID_X9_62_c2pnb368w1 NID_X9_62_c2tnb431r1 = m2.NID_X9_62_c2tnb431r1 NID_wap_wsg_idm_ecid_wtls1 = m2.NID_wap_wsg_idm_ecid_wtls1 NID_wap_wsg_idm_ecid_wtls3 = m2.NID_wap_wsg_idm_ecid_wtls3 NID_wap_wsg_idm_ecid_wtls4 = m2.NID_wap_wsg_idm_ecid_wtls4 NID_wap_wsg_idm_ecid_wtls5 = m2.NID_wap_wsg_idm_ecid_wtls5 NID_wap_wsg_idm_ecid_wtls6 = m2.NID_wap_wsg_idm_ecid_wtls6 NID_wap_wsg_idm_ecid_wtls7 = m2.NID_wap_wsg_idm_ecid_wtls7 NID_wap_wsg_idm_ecid_wtls8 = m2.NID_wap_wsg_idm_ecid_wtls8 NID_wap_wsg_idm_ecid_wtls9 = m2.NID_wap_wsg_idm_ecid_wtls9 NID_wap_wsg_idm_ecid_wtls10 = m2.NID_wap_wsg_idm_ecid_wtls10 NID_wap_wsg_idm_ecid_wtls11 = m2.NID_wap_wsg_idm_ecid_wtls11 NID_wap_wsg_idm_ecid_wtls12 = m2.NID_wap_wsg_idm_ecid_wtls12 # The following two curves, according to OpenSSL, have a # "Questionable extension field!" and are not supported by # the OpenSSL inverse function. ECError: no inverse. # As such they cannot be used for signing. They might, # however, be usable for encryption but that has not # been tested. Until thir usefulness can be established, # they are not supported at this time. # NID_ipsec3 = m2.NID_ipsec3 # NID_ipsec4 = m2.NID_ipsec4 class EC: """ Object interface to a EC key pair. """ m2_ec_key_free = m2.ec_key_free def __init__(self, ec, _pyfree=0): assert m2.ec_key_type_check(ec), "'ec' type error" self.ec = ec self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_ec_key_free(self.ec) def __len__(self): assert m2.ec_key_type_check(self.ec), "'ec' type error" return m2.ec_key_keylen(self.ec) def gen_key(self): """ Generates the key pair from its parameters. Use:: keypair = EC.gen_params(curve) keypair.gen_key() to create an EC key pair. """ assert m2.ec_key_type_check(self.ec), "'ec' type error" m2.ec_key_gen_key(self.ec) def pub(self): # Don't let python free return EC_pub(self.ec, 0) def sign_dsa(self, digest): """ Sign the given digest using ECDSA. Returns a tuple (r,s), the two ECDSA signature parameters. """ assert self._check_key_type(), "'ec' type error" return m2.ecdsa_sign(self.ec, digest) def verify_dsa(self, digest, r, s): """ Verify the given digest using ECDSA. r and s are the ECDSA signature parameters. """ assert self._check_key_type(), "'ec' type error" return m2.ecdsa_verify(self.ec, digest, r, s) def sign_dsa_asn1(self, digest): assert self._check_key_type(), "'ec' type error" return m2.ecdsa_sign_asn1(self.ec, digest) def verify_dsa_asn1(self, digest, blob): assert self._check_key_type(), "'ec' type error" return m2.ecdsa_verify_asn1(self.ec, digest, blob) def compute_dh_key(self,pub_key): """ Compute the ECDH shared key of this key pair and the given public key object. They must both use the same curve. Returns the shared key in binary as a buffer object. No Key Derivation Function is applied. """ assert self.check_key(), 'key is not initialised' return m2.ecdh_compute_key(self.ec, pub_key.ec) def save_key_bio(self, bio, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to an M2Crypto.BIO.BIO object in PEM format. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ if cipher is None: return m2.ec_key_write_bio_no_cipher(self.ec, bio._ptr(), callback) else: ciph = getattr(m2, cipher, None) if ciph is None: raise ValueError('not such cipher %s' % cipher) return m2.ec_key_write_bio(self.ec, bio._ptr(), ciph(), callback) def save_key(self, file, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to a file in PEM format. @type file: string @param file: Name of file to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ bio = BIO.openfile(file, 'wb') return self.save_key_bio(bio, cipher, callback) def save_pub_key_bio(self, bio): """ Save the public key to an M2Crypto.BIO.BIO object in PEM format. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object to save key to. """ return m2.ec_key_write_pubkey(self.ec, bio._ptr()) def save_pub_key(self, file): """ Save the public key to a file in PEM format. @type file: string @param file: Name of file to save key to. """ bio = BIO.openfile(file, 'wb') return m2.ec_key_write_pubkey(self.ec, bio._ptr()) def _check_key_type(self): return m2.ec_key_type_check(self.ec) def check_key(self): assert m2.ec_key_type_check(self.ec), "'ec' type error" return m2.ec_key_check_key(self.ec) class EC_pub(EC): """ Object interface to an EC public key. ((don't like this implementation inheritance)) """ def __init__(self,ec,_pyfree=0): EC.__init__(self,ec,_pyfree) self.der = None def get_der(self): """ Returns the public key in DER format as a buffer object. """ assert self.check_key(), 'key is not initialised' if self.der is None: self.der = m2.ec_key_get_public_der(self.ec) return self.der save_key = EC.save_pub_key save_key_bio = EC.save_pub_key_bio def gen_params(curve): """ Factory function that generates EC parameters and instantiates a EC object from the output. @param curve: This is the OpenSSL nid of the curve to use. """ return EC(m2.ec_key_new_by_curve_name(curve), 1) def load_key(file, callback=util.passphrase_callback): """ Factory function that instantiates a EC object. @param file: Names the file that contains the PEM representation of the EC key pair. @param callback: Python callback object that will be invoked if the EC key pair is passphrase-protected. """ bio = BIO.openfile(file) return load_key_bio(bio, callback) def load_key_bio(bio, callback=util.passphrase_callback): """ Factory function that instantiates a EC object. @param bio: M2Crypto.BIO object that contains the PEM representation of the EC key pair. @param callback: Python callback object that will be invoked if the EC key pair is passphrase-protected. """ return EC(m2.ec_key_read_bio(bio._ptr(), callback), 1) def load_pub_key(file): """ Load an EC public key from file. @type file: string @param file: Name of file containing EC public key in PEM format. @rtype: M2Crypto.EC.EC_pub @return: M2Crypto.EC.EC_pub object. """ bio = BIO.openfile(file) return load_pub_key_bio(bio) def load_pub_key_bio(bio): """ Load an EC public key from an M2Crypto.BIO.BIO object. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object containing EC public key in PEM format. @rtype: M2Crypto.EC.EC_pub @return: M2Crypto.EC.EC_pub object. """ ec = m2.ec_key_read_pubkey(bio._ptr()) if ec is None: ec_error() return EC_pub(ec, 1) def ec_error(): raise ECError, m2.err_reason_error_string(m2.err_get_error()) def pub_key_from_der(der): """ Create EC_pub from DER. """ return EC_pub(m2.ec_key_from_pubkey_der(der), 1) M2Crypto-0.22.6rc4/M2Crypto/EVP.py0000664000175000017500000002704212607370517016615 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL EVP API. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions Copyright (c) 2004-2007 Open Source Applications Foundation. Author: Heikki Toivonen """ from M2Crypto import Err, util, BIO, RSA import m2 class EVPError(Exception): pass m2.evp_init(EVPError) def pbkdf2(password, salt, iter, keylen): """ Derive a key from password using PBKDF2 algorithm specified in RFC 2898. @param password: Derive the key from this password. @type password: str @param salt: Salt. @type salt: str @param iter: Number of iterations to perform. @type iter: int @param keylen: Length of key to produce. @type keylen: int @return: Key. @rtype: str """ return m2.pkcs5_pbkdf2_hmac_sha1(password, salt, iter, keylen) class MessageDigest: """ Message Digest """ m2_md_ctx_free = m2.md_ctx_free def __init__(self, algo): md = getattr(m2, algo, None) if md is None: raise ValueError, ('unknown algorithm', algo) self.md=md() self.ctx=m2.md_ctx_new() m2.digest_init(self.ctx, self.md) def __del__(self): if getattr(self, 'ctx', None): self.m2_md_ctx_free(self.ctx) def update(self, data): """ Add data to be digested. @return: -1 for Python error, 1 for success, 0 for OpenSSL failure. """ return m2.digest_update(self.ctx, data) def final(self): return m2.digest_final(self.ctx) # Deprecated. digest = final class HMAC: m2_hmac_ctx_free = m2.hmac_ctx_free def __init__(self, key, algo='sha1'): md = getattr(m2, algo, None) if md is None: raise ValueError, ('unknown algorithm', algo) self.md=md() self.ctx=m2.hmac_ctx_new() m2.hmac_init(self.ctx, key, self.md) def __del__(self): if getattr(self, 'ctx', None): self.m2_hmac_ctx_free(self.ctx) def reset(self, key): m2.hmac_init(self.ctx, key, self.md) def update(self, data): m2.hmac_update(self.ctx, data) def final(self): return m2.hmac_final(self.ctx) digest=final def hmac(key, data, algo='sha1'): md = getattr(m2, algo, None) if md is None: raise ValueError, ('unknown algorithm', algo) return m2.hmac(key, data, md()) class Cipher: m2_cipher_ctx_free = m2.cipher_ctx_free def __init__(self, alg, key, iv, op, key_as_bytes=0, d='md5', salt='12345678', i=1, padding=1): cipher = getattr(m2, alg, None) if cipher is None: raise ValueError, ('unknown cipher', alg) self.cipher=cipher() if key_as_bytes: kmd = getattr(m2, d, None) if kmd is None: raise ValueError, ('unknown message digest', d) key = m2.bytes_to_key(self.cipher, kmd(), key, salt, iv, i) self.ctx=m2.cipher_ctx_new() m2.cipher_init(self.ctx, self.cipher, key, iv, op) self.set_padding(padding) del key def __del__(self): if getattr(self, 'ctx', None): self.m2_cipher_ctx_free(self.ctx) def update(self, data): return m2.cipher_update(self.ctx, data) def final(self): return m2.cipher_final(self.ctx) def set_padding(self, padding=1): return m2.cipher_set_padding(self.ctx, padding) class PKey: """ Public Key """ m2_pkey_free = m2.pkey_free m2_md_ctx_free = m2.md_ctx_free def __init__(self, pkey=None, _pyfree=0, md='sha1'): if pkey is not None: self.pkey = pkey self._pyfree = _pyfree else: self.pkey = m2.pkey_new() self._pyfree = 1 self._set_context(md) def __del__(self): if getattr(self, '_pyfree', 0): self.m2_pkey_free(self.pkey) if getattr(self, 'ctx', None): self.m2_md_ctx_free(self.ctx) def _ptr(self): return self.pkey def _set_context(self, md): mda = getattr(m2, md, None) if mda is None: raise ValueError, ('unknown message digest', md) self.md = mda() self.ctx = m2.md_ctx_new() def reset_context(self, md='sha1'): """ Reset internal message digest context. @type md: string @param md: The message digest algorithm. """ self._set_context(md) def sign_init(self): """ Initialise signing operation with self. """ m2.sign_init(self.ctx, self.md) def sign_update(self, data): """ Feed data to signing operation. @type data: string @param data: Data to be signed. """ m2.sign_update(self.ctx, data) def sign_final(self): """ Return signature. @rtype: string @return: The signature. """ return m2.sign_final(self.ctx, self.pkey) # Deprecated update = sign_update final = sign_final def verify_init(self): """ Initialise signature verification operation with self. """ m2.verify_init(self.ctx, self.md) def verify_update(self, data): """ Feed data to verification operation. @type data: string @param data: Data to be verified. @return: -1 on Python error, 1 for success, 0 for OpenSSL error """ return m2.verify_update(self.ctx, data) def verify_final(self, sign): """ Return result of verification. @param sign: Signature to use for verification @rtype: int @return: Result of verification: 1 for success, 0 for failure, -1 on other error. """ return m2.verify_final(self.ctx, sign, self.pkey) def assign_rsa(self, rsa, capture=1): """ Assign the RSA key pair to self. @type rsa: M2Crypto.RSA.RSA @param rsa: M2Crypto.RSA.RSA object to be assigned to self. @type capture: boolean @param capture: If true (default), this PKey object will own the RSA object, meaning that once the PKey object gets deleted it is no longer safe to use the RSA object. @rtype: int @return: Return 1 for success and 0 for failure. """ if capture: ret = m2.pkey_assign_rsa(self.pkey, rsa.rsa) if ret: rsa._pyfree = 0 else: ret = m2.pkey_set1_rsa(self.pkey, rsa.rsa) return ret def get_rsa(self): """ Return the underlying RSA key if that is what the EVP instance is holding. """ rsa_ptr = m2.pkey_get1_rsa(self.pkey) if rsa_ptr is None: raise ValueError("PKey instance is not holding a RSA key") rsa = RSA.RSA_pub(rsa_ptr, 1) return rsa def save_key(self, file, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to a file in PEM format. @type file: string @param file: Name of file to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ bio = BIO.openfile(file, 'wb') return self.save_key_bio(bio, cipher, callback) def save_key_bio(self, bio, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to the M2Crypto.BIO object 'bio' in PEM format. @type bio: M2Crypto.BIO @param bio: M2Crypto.BIO object to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ if cipher is None: return m2.pkey_write_pem_no_cipher(self.pkey, bio._ptr(), callback) else: proto = getattr(m2, cipher, None) if proto is None: raise ValueError, 'no such cipher %s' % cipher return m2.pkey_write_pem(self.pkey, bio._ptr(), proto(), callback) def as_pem(self, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Return key in PEM format in a string. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ bio = BIO.MemoryBuffer() self.save_key_bio(bio, cipher, callback) return bio.read_all() def as_der(self): """ Return key in DER format in a string """ buf = m2.pkey_as_der(self.pkey) bio = BIO.MemoryBuffer(buf) return bio.read_all() def size(self): """ Return the size of the key in bytes. """ return m2.pkey_size(self.pkey) def get_modulus(self): """ Return the modulus in hex format. """ return m2.pkey_get_modulus(self.pkey) def load_key(file, callback=util.passphrase_callback): """ Load an M2Crypto.EVP.PKey from file. @type file: string @param file: Name of file containing the key in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @rtype: M2Crypto.EVP.PKey @return: M2Crypto.EVP.PKey object. """ bio = m2.bio_new_file(file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) cptr = m2.pkey_read_pem(bio, callback) m2.bio_free(bio) if cptr is None: raise EVPError(Err.get_error()) return PKey(cptr, 1) def load_key_bio(bio, callback=util.passphrase_callback): """ Load an M2Crypto.EVP.PKey from an M2Crypto.BIO object. @type bio: M2Crypto.BIO @param bio: M2Crypto.BIO object containing the key in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @rtype: M2Crypto.EVP.PKey @return: M2Crypto.EVP.PKey object. """ cptr = m2.pkey_read_pem(bio._ptr(), callback) if cptr is None: raise EVPError(Err.get_error()) return PKey(cptr, 1) def load_key_string(string, callback=util.passphrase_callback): """ Load an M2Crypto.EVP.PKey from a string. @type string: string @param string: String containing the key in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. @rtype: M2Crypto.EVP.PKey @return: M2Crypto.EVP.PKey object. """ bio = BIO.MemoryBuffer(string) return load_key_bio( bio, callback) M2Crypto-0.22.6rc4/M2Crypto/Engine.py0000664000175000017500000000722412607370517017370 0ustar matejmatej00000000000000# vim: sts=4 sw=4 et """ M2Crypto wrapper for OpenSSL ENGINE API. Pavel Shramov IMEC MSU """ from M2Crypto import m2, EVP, X509, Err class EngineError(Exception): pass m2.engine_init_error(EngineError) class Engine: """Wrapper for ENGINE object.""" m2_engine_free = m2.engine_free def __init__(self, id = None, _ptr = None, _pyfree = 1): """Create new Engine from ENGINE pointer or obtain by id""" if not _ptr and not id: raise ValueError("No engine id specified") self._ptr = _ptr if not self._ptr: self._ptr = m2.engine_by_id(id) if not self._ptr: raise ValueError("Unknown engine: %s" % id) self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_engine_free(self._ptr) def init(self): """Obtain a functional reference to the engine. @return: 0 on error, non-zero on success.""" return m2.engine_init(self._ptr) def finish(self): """Release a functional and structural reference to the engine.""" return m2.engine_finish(self._ptr) def ctrl_cmd_string(self, cmd, arg, optional = 0): """Call ENGINE_ctrl_cmd_string""" if not m2.engine_ctrl_cmd_string(self._ptr, cmd, arg, optional): raise EngineError(Err.get_error()) def get_name(self): """Return engine name""" return m2.engine_get_name(self._ptr) def get_id(self): """Return engine id""" return m2.engine_get_id(self._ptr) def set_default(self, methods = m2.ENGINE_METHOD_ALL): """Use this engine as default for methods specified in argument Possible values are bitwise OR of m2.ENGINE_METHOD_*""" return m2.engine_set_default(self._ptr, methods) def _engine_load_key(self, func, name, pin = None): """Helper function for loading keys""" ui = m2.ui_openssl() cbd = m2.engine_pkcs11_data_new(pin) try: kptr = func(self._ptr, name, ui, cbd) if not kptr: raise EngineError(Err.get_error()) key = EVP.PKey(kptr, _pyfree = 1) finally: m2.engine_pkcs11_data_free(cbd) return key def load_private_key(self, name, pin = None): """Load private key with engine methods (e.g from smartcard). If pin is not set it will be asked """ return self._engine_load_key(m2.engine_load_private_key, name, pin) def load_public_key(self, name, pin = None): """Load public key with engine methods (e.g from smartcard).""" return self._engine_load_key(m2.engine_load_public_key, name, pin) def load_certificate(self, name): """Load certificate from engine (e.g from smartcard). NOTE: This function may be not implemented by engine!""" cptr = m2.engine_load_certificate(self._ptr, name) if not cptr: raise EngineError("Certificate or card not found") return X509.X509(cptr, _pyfree = 1) def load_dynamic_engine(id, sopath): """Load and return dymanic engine from sopath and assign id to it""" m2.engine_load_dynamic() e = Engine('dynamic') e.ctrl_cmd_string("SO_PATH", sopath) e.ctrl_cmd_string("ID", id) e.ctrl_cmd_string("LIST_ADD", "1") e.ctrl_cmd_string("LOAD", None) return e def load_dynamic(): """Load dynamic engine""" m2.engine_load_dynamic() def load_openssl(): """Load openssl engine""" m2.engine_load_openssl() def cleanup(): """If you load any engines, you need to clean up after your application is finished with the engines.""" m2.engine_cleanup() M2Crypto-0.22.6rc4/M2Crypto/Err.py0000664000175000017500000000214312607370517016706 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL Error API. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import BIO import m2 def get_error(): err=BIO.MemoryBuffer() m2.err_print_errors(err.bio_ptr()) return err.getvalue() def get_error_code(): return m2.err_get_error() def peek_error_code(): return m2.err_peek_error() def get_error_lib(err): return m2.err_lib_error_string(err) def get_error_func(err): return m2.err_func_error_string(err) def get_error_reason(err): return m2.err_reason_error_string(err) def get_x509_verify_error(err): return m2.x509_get_verify_error(err) class SSLError(Exception): def __init__(self, err, client_addr): self.err = err self.client_addr = client_addr def __str__(self): if (isinstance(self.client_addr, unicode)): s = self.client_addr.encode('utf8') else: s = self.client_addr return "%s: %s: %s" % \ (m2.err_func_error_string(self.err), \ s, \ m2.err_reason_error_string(self.err)) class M2CryptoError(Exception): pass M2Crypto-0.22.6rc4/M2Crypto/RC4.py0000664000175000017500000000126412607370517016551 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL RC4 API. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from m2 import rc4_new, rc4_free, rc4_set_key, rc4_update class RC4: """Object interface to the stream cipher RC4.""" rc4_free = rc4_free def __init__(self, key=None): self.cipher = rc4_new() if key: rc4_set_key(self.cipher, key) def __del__(self): if getattr(self, 'cipher', None): self.rc4_free(self.cipher) def set_key(self, key): rc4_set_key(self.cipher, key) def update(self, data): return rc4_update(self.cipher, data) def final(self): return '' M2Crypto-0.22.6rc4/M2Crypto/RSA.py0000664000175000017500000003151012607370517016603 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL RSA API. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import sys import util, BIO, Err, m2 class RSAError(Exception): pass m2.rsa_init(RSAError) no_padding = m2.no_padding pkcs1_padding = m2.pkcs1_padding sslv23_padding = m2.sslv23_padding pkcs1_oaep_padding = m2.pkcs1_oaep_padding class RSA: """ RSA Key Pair. """ m2_rsa_free = m2.rsa_free def __init__(self, rsa, _pyfree=0): assert m2.rsa_type_check(rsa), "'rsa' type error" self.rsa = rsa self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_rsa_free(self.rsa) def __len__(self): return m2.rsa_size(self.rsa) << 3 def __getattr__(self, name): if name == 'e': return m2.rsa_get_e(self.rsa) elif name == 'n': return m2.rsa_get_n(self.rsa) else: raise AttributeError def pub(self): assert self.check_key(), 'key is not initialised' return m2.rsa_get_e(self.rsa), m2.rsa_get_n(self.rsa) def public_encrypt(self, data, padding): assert self.check_key(), 'key is not initialised' return m2.rsa_public_encrypt(self.rsa, data, padding) def public_decrypt(self, data, padding): assert self.check_key(), 'key is not initialised' return m2.rsa_public_decrypt(self.rsa, data, padding) def private_encrypt(self, data, padding): assert self.check_key(), 'key is not initialised' return m2.rsa_private_encrypt(self.rsa, data, padding) def private_decrypt(self, data, padding): assert self.check_key(), 'key is not initialised' return m2.rsa_private_decrypt(self.rsa, data, padding) def save_key_bio(self, bio, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to an M2Crypto.BIO.BIO object in PEM format. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ if cipher is None: return m2.rsa_write_key_no_cipher(self.rsa, bio._ptr(), callback) else: ciph = getattr(m2, cipher, None) if ciph is None: raise RSAError, 'not such cipher %s' % cipher else: ciph = ciph() return m2.rsa_write_key(self.rsa, bio._ptr(), ciph, callback) def save_key(self, file, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Save the key pair to a file in PEM format. @type file: string @param file: Name of file to save key to. @type cipher: string @param cipher: Symmetric cipher to protect the key. The default cipher is 'aes_128_cbc'. If cipher is None, then the key is saved in the clear. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to protect the key. The default is util.passphrase_callback. """ bio = BIO.openfile(file, 'wb') return self.save_key_bio(bio, cipher, callback) save_pem = save_key def as_pem(self, cipher='aes_128_cbc', callback=util.passphrase_callback): """ Returns the key(pair) as a string in PEM format. """ bio = BIO.MemoryBuffer() self.save_key_bio(bio, cipher, callback) return bio.read() def save_key_der_bio(self, bio): """ Save the key pair to an M2Crypto.BIO.BIO object in DER format. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object to save key to. """ return m2.rsa_write_key_der(self.rsa, bio._ptr()) def save_key_der(self, file): """ Save the key pair to a file in DER format. @type file: str @param file: Filename to save key to """ bio = BIO.openfile(file, 'wb') return self.save_key_der_bio(bio) def save_pub_key_bio(self, bio): """ Save the public key to an M2Crypto.BIO.BIO object in PEM format. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object to save key to. """ return m2.rsa_write_pub_key(self.rsa, bio._ptr()) def save_pub_key(self, file): """ Save the public key to a file in PEM format. @type file: string @param file: Name of file to save key to. """ bio = BIO.openfile(file, 'wb') return m2.rsa_write_pub_key(self.rsa, bio._ptr()) def check_key(self): return m2.rsa_check_key(self.rsa) def sign_rsassa_pss(self, digest, algo='sha1', salt_length=20): """ Signs a digest with the private key using RSASSA-PSS @requires: OpenSSL 0.9.7h or later. @type digest: str @param digest: A digest created by using the digest method @type salt_length: int @param salt_length: The length of the salt to use @type algo: str @param algo: The hash algorithm to use @return: a string which is the signature """ hash = getattr(m2, algo, None) if hash is None: raise ValueError('not such hash algorithm %s' % hash_algo) signature = m2.rsa_padding_add_pkcs1_pss(self.rsa, digest, hash(), salt_length) return self.private_encrypt(signature, m2.no_padding) def verify_rsassa_pss(self, data, signature, algo='sha1', salt_length=20): """ Verifies the signature RSASSA-PSS @requires: OpenSSL 0.9.7h or later. @type data: str @param data: Data that has been signed @type signature: str @param signature: The signature signed with RSASSA-PSS @type salt_length: int @param salt_length: The length of the salt that was used @type algo: str @param algo: The hash algorithm to use @return: 1 or 0, depending on whether the signature was verified or not. """ hash = getattr(m2, algo, None) if hash is None: raise ValueError('not such hash algorithm %s' % hash_algo) plain_signature = self.public_decrypt(signature, m2.no_padding) return m2.rsa_verify_pkcs1_pss(self.rsa, data, plain_signature, hash(), salt_length) def sign(self, digest, algo='sha1'): """ Signs a digest with the private key @type digest: str @param digest: A digest created by using the digest method @type algo: str @param algo: The method that created the digest. Legal values are 'sha1','sha224', 'sha256', 'ripemd160', and 'md5'. @return: a string which is the signature """ digest_type = getattr(m2, 'NID_' + algo, None) if digest_type is None: raise ValueError, ('unknown algorithm', algo) return m2.rsa_sign(self.rsa, digest, digest_type) def verify(self, data, signature, algo='sha1'): """ Verifies the signature with the public key @type data: str @param data: Data that has been signed @type signature: str @param signature: The signature signed with the private key @type algo: str @param algo: The method use to create digest from the data before it was signed. Legal values are 'sha1','sha224', 'sha256', 'ripemd160', and 'md5'. @return: True or False, depending on whether the signature was verified. """ digest_type = getattr(m2, 'NID_' + algo, None) if digest_type is None: raise ValueError, ('unknown algorithm', algo) return m2.rsa_verify(self.rsa, data, signature, digest_type) class RSA_pub(RSA): """ Object interface to an RSA public key. """ def __setattr__(self, name, value): if name in ['e', 'n']: raise RSAError, \ 'use factory function new_pub_key() to set (e, n)' else: self.__dict__[name] = value def private_encrypt(self, *argv): raise RSAError, 'RSA_pub object has no private key' def private_decrypt(self, *argv): raise RSAError, 'RSA_pub object has no private key' def save_key(self, file, *args, **kw): """ Save public key to file. """ return self.save_pub_key(file) def save_key_bio(self, bio, *args, **kw): """ Save public key to BIO. """ return self.save_pub_key_bio(bio) #save_key_der #save_key_der_bio def check_key(self): return m2.rsa_check_pub_key(self.rsa) def rsa_error(): raise RSAError, m2.err_reason_error_string(m2.err_get_error()) def keygen_callback(p, n, out=sys.stdout): """ Default callback for gen_key(). """ ch = ['.','+','*','\n'] out.write(ch[p]) out.flush() def gen_key(bits, e, callback=keygen_callback): """ Generate an RSA key pair. @type bits: int @param bits: Key length, in bits. @type e: int @param e: The RSA public exponent. @type callback: Python callable @param callback: A Python callable object that is invoked during key generation; its usual purpose is to provide visual feedback. The default callback is keygen_callback. @rtype: M2Crypto.RSA.RSA @return: M2Crypto.RSA.RSA object. """ return RSA(m2.rsa_generate_key(bits, e, callback), 1) def load_key(file, callback=util.passphrase_callback): """ Load an RSA key pair from file. @type file: string @param file: Name of file containing RSA public key in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to unlock the key. The default is util.passphrase_callback. @rtype: M2Crypto.RSA.RSA @return: M2Crypto.RSA.RSA object. """ bio = BIO.openfile(file) return load_key_bio(bio, callback) def load_key_bio(bio, callback=util.passphrase_callback): """ Load an RSA key pair from an M2Crypto.BIO.BIO object. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object containing RSA key pair in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to unlock the key. The default is util.passphrase_callback. @rtype: M2Crypto.RSA.RSA @return: M2Crypto.RSA.RSA object. """ rsa = m2.rsa_read_key(bio._ptr(), callback) if rsa is None: rsa_error() return RSA(rsa, 1) def load_key_string(string, callback=util.passphrase_callback): """ Load an RSA key pair from a string. @type string: string @param string: String containing RSA key pair in PEM format. @type callback: Python callable @param callback: A Python callable object that is invoked to acquire a passphrase with which to unlock the key. The default is util.passphrase_callback. @rtype: M2Crypto.RSA.RSA @return: M2Crypto.RSA.RSA object. """ bio = BIO.MemoryBuffer(string) return load_key_bio(bio, callback) def load_pub_key(file): """ Load an RSA public key from file. @type file: string @param file: Name of file containing RSA public key in PEM format. @rtype: M2Crypto.RSA.RSA_pub @return: M2Crypto.RSA.RSA_pub object. """ bio = BIO.openfile(file) return load_pub_key_bio(bio) def load_pub_key_bio(bio): """ Load an RSA public key from an M2Crypto.BIO.BIO object. @type bio: M2Crypto.BIO.BIO @param bio: M2Crypto.BIO.BIO object containing RSA public key in PEM format. @rtype: M2Crypto.RSA.RSA_pub @return: M2Crypto.RSA.RSA_pub object. """ rsa = m2.rsa_read_pub_key(bio._ptr()) if rsa is None: rsa_error() return RSA_pub(rsa, 1) def new_pub_key((e, n)): """ Instantiate an RSA_pub object from an (e, n) tuple. @type e: string @param e: The RSA public exponent; it is a string in OpenSSL's MPINT format - 4-byte big-endian bit-count followed by the appropriate number of bits. @type n: string @param n: The RSA composite of primes; it is a string in OpenSSL's MPINT format - 4-byte big-endian bit-count followed by the appropriate number of bits. @rtype: M2Crypto.RSA.RSA_pub @return: M2Crypto.RSA.RSA_pub object. """ rsa = m2.rsa_new() m2.rsa_set_e(rsa, e) m2.rsa_set_n(rsa, n) return RSA_pub(rsa, 1) M2Crypto-0.22.6rc4/M2Crypto/Rand.py0000664000175000017500000000075012607370517017044 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL PRNG. Requires OpenSSL 0.9.5 and above. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" __all__ = ['rand_seed', 'rand_add', 'load_file', 'save_file', 'rand_bytes', 'rand_pseudo_bytes'] import m2 rand_seed = m2.rand_seed rand_add = m2.rand_add load_file = m2.rand_load_file save_file = m2.rand_save_file rand_bytes = m2.rand_bytes rand_pseudo_bytes = m2.rand_pseudo_bytes M2Crypto-0.22.6rc4/M2Crypto/SMIME.py0000664000175000017500000001646712607370517017046 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL S/MIME API. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import BIO, EVP, X509, Err, util import m2 PKCS7_TEXT = m2.PKCS7_TEXT PKCS7_NOCERTS = m2.PKCS7_NOCERTS PKCS7_NOSIGS = m2.PKCS7_NOSIGS PKCS7_NOCHAIN = m2.PKCS7_NOCHAIN PKCS7_NOINTERN = m2.PKCS7_NOINTERN PKCS7_NOVERIFY = m2.PKCS7_NOVERIFY PKCS7_DETACHED = m2.PKCS7_DETACHED PKCS7_BINARY = m2.PKCS7_BINARY PKCS7_NOATTR = m2.PKCS7_NOATTR PKCS7_SIGNED = m2.PKCS7_SIGNED PKCS7_ENVELOPED = m2.PKCS7_ENVELOPED PKCS7_SIGNED_ENVELOPED = m2.PKCS7_SIGNED_ENVELOPED # Deprecated PKCS7_DATA = m2.PKCS7_DATA class PKCS7_Error(Exception): pass m2.pkcs7_init(PKCS7_Error) class PKCS7: m2_pkcs7_free = m2.pkcs7_free def __init__(self, pkcs7=None, _pyfree=0): if pkcs7 is not None: self.pkcs7 = pkcs7 self._pyfree = _pyfree else: self.pkcs7 = m2.pkcs7_new() self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_pkcs7_free(self.pkcs7) def _ptr(self): return self.pkcs7 def type(self, text_name=0): if text_name: return m2.pkcs7_type_sn(self.pkcs7) else: return m2.pkcs7_type_nid(self.pkcs7) def write(self, bio): return m2.pkcs7_write_bio(self.pkcs7, bio._ptr()) def write_der(self, bio): return m2.pkcs7_write_bio_der(self.pkcs7, bio._ptr()) def get0_signers(self, certs, flags = 0): return X509.X509_Stack(m2.pkcs7_get0_signers(self.pkcs7, certs.stack, flags), 1) def load_pkcs7(p7file): bio = m2.bio_new_file(p7file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) try: p7_ptr = m2.pkcs7_read_bio(bio) finally: m2.bio_free(bio) if p7_ptr is None: raise PKCS7_Error(Err.get_error()) return PKCS7(p7_ptr, 1) def load_pkcs7_bio(p7_bio): p7_ptr = m2.pkcs7_read_bio(p7_bio._ptr()) if p7_ptr is None: raise PKCS7_Error(Err.get_error()) return PKCS7(p7_ptr, 1) def smime_load_pkcs7(p7file): bio = m2.bio_new_file(p7file, 'r') if bio is None: raise BIO.BIOError(Err.get_error()) try: p7_ptr, bio_ptr = m2.smime_read_pkcs7(bio) finally: m2.bio_free(bio) if p7_ptr is None: raise SMIME_Error(Err.get_error()) if bio_ptr is None: return PKCS7(p7_ptr, 1), None else: return PKCS7(p7_ptr, 1), BIO.BIO(bio_ptr, 1) def smime_load_pkcs7_bio(p7_bio): p7_ptr, bio_ptr = m2.smime_read_pkcs7(p7_bio._ptr()) if p7_ptr is None: raise SMIME_Error(Err.get_error()) if bio_ptr is None: return PKCS7(p7_ptr, 1), None else: return PKCS7(p7_ptr, 1), BIO.BIO(bio_ptr, 1) class Cipher: """ Object interface to EVP_CIPHER without all the frills of M2Crypto.EVP.Cipher. """ def __init__(self, algo): cipher = getattr(m2, algo, None) if cipher is None: raise ValueError, ('unknown cipher', algo) self.cipher = cipher() def _ptr(self): return self.cipher class SMIME_Error(Exception): pass m2.smime_init(SMIME_Error) class SMIME: def load_key(self, keyfile, certfile=None, callback=util.passphrase_callback): if certfile is None: certfile = keyfile self.pkey = EVP.load_key(keyfile, callback) self.x509 = X509.load_cert(certfile) def load_key_bio(self, keybio, certbio=None, callback=util.passphrase_callback): if certbio is None: certbio = keybio self.pkey = EVP.load_key_bio(keybio, callback) self.x509 = X509.load_cert_bio(certbio) def set_x509_stack(self, stack): assert isinstance(stack, X509.X509_Stack) self.x509_stack = stack def set_x509_store(self, store): assert isinstance(store, X509.X509_Store) self.x509_store = store def set_cipher(self, cipher): assert isinstance(cipher, Cipher) self.cipher = cipher def unset_key(self): del self.pkey del self.x509 def unset_x509_stack(self): del self.x509_stack def unset_x509_store(self): del self.x509_store def unset_cipher(self): del self.cipher def encrypt(self, data_bio, flags=0): if not hasattr(self, 'cipher'): raise SMIME_Error, 'no cipher: use set_cipher()' if not hasattr(self, 'x509_stack'): raise SMIME_Error, 'no recipient certs: use set_x509_stack()' pkcs7 = m2.pkcs7_encrypt(self.x509_stack._ptr(), data_bio._ptr(), self.cipher._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1) def decrypt(self, pkcs7, flags=0): if not hasattr(self, 'pkey'): raise SMIME_Error, 'no private key: use load_key()' if not hasattr(self, 'x509'): raise SMIME_Error, 'no certificate: load_key() used incorrectly?' blob = m2.pkcs7_decrypt(pkcs7._ptr(), self.pkey._ptr(), self.x509._ptr(), flags) if blob is None: raise SMIME_Error(Err.get_error()) return blob def sign(self, data_bio, flags=0): if not hasattr(self, 'pkey'): raise SMIME_Error, 'no private key: use load_key()' if hasattr(self, 'x509_stack'): pkcs7 = m2.pkcs7_sign1(self.x509._ptr(), self.pkey._ptr(), self.x509_stack._ptr(), data_bio._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1) else: pkcs7 = m2.pkcs7_sign0(self.x509._ptr(), self.pkey._ptr(), data_bio._ptr(), flags) if pkcs7 is None: raise SMIME_Error(Err.get_error()) return PKCS7(pkcs7, 1) def verify(self, pkcs7, data_bio=None, flags=0): if not hasattr(self, 'x509_stack'): raise SMIME_Error, 'no signer certs: use set_x509_stack()' if not hasattr(self, 'x509_store'): raise SMIME_Error, 'no x509 cert store: use set_x509_store()' assert isinstance(pkcs7, PKCS7), 'pkcs7 not an instance of PKCS7' p7 = pkcs7._ptr() if data_bio is None: blob = m2.pkcs7_verify0(p7, self.x509_stack._ptr(), self.x509_store._ptr(), flags) else: blob = m2.pkcs7_verify1(p7, self.x509_stack._ptr(), self.x509_store._ptr(), data_bio._ptr(), flags) if blob is None: raise SMIME_Error(Err.get_error()) return blob def write(self, out_bio, pkcs7, data_bio=None, flags=0): assert isinstance(pkcs7, PKCS7) if data_bio is None: return m2.smime_write_pkcs7(out_bio._ptr(), pkcs7._ptr(), flags) else: return m2.smime_write_pkcs7_multi(out_bio._ptr(), pkcs7._ptr(), data_bio._ptr(), flags) def text_crlf(text): bio_in = BIO.MemoryBuffer(text) bio_out = BIO.MemoryBuffer() if m2.smime_crlf_copy(bio_in._ptr(), bio_out._ptr()): return bio_out.read() else: raise SMIME_Error(Err.get_error()) def text_crlf_bio(bio_in): bio_out = BIO.MemoryBuffer() if m2.smime_crlf_copy(bio_in._ptr(), bio_out._ptr()): return bio_out else: raise SMIME_Error(Err.get_error()) M2Crypto-0.22.6rc4/M2Crypto/X509.py0000664000175000017500000010352612607370517016632 0ustar matejmatej00000000000000"""M2Crypto wrapper for OpenSSL X509 API. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004-2007 OSAF. All Rights Reserved. Author: Heikki Toivonen """ # M2Crypto from M2Crypto import ASN1, BIO, Err, EVP, util import m2 FORMAT_DER = 0 FORMAT_PEM = 1 class X509Error(Exception): pass m2.x509_init(X509Error) V_OK = m2.X509_V_OK def new_extension(name, value, critical=0, _pyfree=1): """ Create new X509_Extension instance. """ if name == 'subjectKeyIdentifier' and \ value.strip('0123456789abcdefABCDEF:') is not '': raise ValueError('value must be precomputed hash') lhash = m2.x509v3_lhash() ctx = m2.x509v3_set_conf_lhash(lhash) x509_ext_ptr = m2.x509v3_ext_conf(lhash, ctx, name, value) x509_ext = X509_Extension(x509_ext_ptr, _pyfree) x509_ext.set_critical(critical) return x509_ext class X509_Extension: """ X509 Extension """ m2_x509_extension_free = m2.x509_extension_free def __init__(self, x509_ext_ptr=None, _pyfree=1): self.x509_ext = x509_ext_ptr self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0) and self.x509_ext: self.m2_x509_extension_free(self.x509_ext) def _ptr(self): return self.x509_ext def set_critical(self, critical=1): """ Mark this extension critical or noncritical. By default an extension is not critical. @type critical: int @param critical: Nonzero sets this extension as critical. Calling this method without arguments will set this extension to critical. """ return m2.x509_extension_set_critical(self.x509_ext, critical) def get_critical(self): """ Return whether or not this is a critical extension. @rtype: int @return: Nonzero if this is a critical extension. """ return m2.x509_extension_get_critical(self.x509_ext) def get_name(self): """ Get the extension name, for example 'subjectAltName'. """ return m2.x509_extension_get_name(self.x509_ext) def get_value(self, flag=0, indent=0): """ Get the extension value, for example 'DNS:www.example.com'. @param flag: Flag to control what and how to print. @param indent: How many spaces to print before actual value. """ buf=BIO.MemoryBuffer() m2.x509_ext_print(buf.bio_ptr(), self.x509_ext, flag, indent) return buf.read_all() class X509_Extension_Stack: """ X509 Extension Stack @warning: Do not modify the underlying OpenSSL stack except through this interface, or use any OpenSSL functions that do so indirectly. Doing so will get the OpenSSL stack and the internal pystack of this class out of sync, leading to python memory leaks, exceptions or even python crashes! """ m2_sk_x509_extension_free = m2.sk_x509_extension_free def __init__(self, stack=None, _pyfree=0): if stack is not None: self.stack = stack self._pyfree = _pyfree num = m2.sk_x509_extension_num(self.stack) for i in range(num): self.pystack.append(X509_Extension(m2.sk_x509_extension_value(self.stack, i), _pyfree=_pyfree)) else: self.stack = m2.sk_x509_extension_new_null() self._pyfree = 1 self.pystack = [] # This must be kept in sync with self.stack def __del__(self): if getattr(self, '_pyfree', 0): self.m2_sk_x509_extension_free(self.stack) def __len__(self): assert m2.sk_x509_extension_num(self.stack) == len(self.pystack) return len(self.pystack) def __getitem__(self, idx): return self.pystack[idx] def __iter__(self): return iter(self.pystack) def _ptr(self): return self.stack def push(self, x509_ext): """ Push X509_Extension object onto the stack. @type x509_ext: M2Crypto.X509.X509_Extension @param x509_ext: X509_Extension object to be pushed onto the stack. @return: The number of extensions on the stack. """ self.pystack.append(x509_ext) ret = m2.sk_x509_extension_push(self.stack, x509_ext._ptr()) assert ret == len(self.pystack) return ret def pop(self): """ Pop X509_Extension object from the stack. @return: X509_Extension popped """ x509_ext_ptr = m2.sk_x509_extension_pop(self.stack) if x509_ext_ptr is None: assert len(self.pystack) == 0 return None return self.pystack.pop() class X509_Name_Entry: """ X509 Name Entry """ m2_x509_name_entry_free = m2.x509_name_entry_free def __init__(self, x509_name_entry, _pyfree=0): self.x509_name_entry = x509_name_entry self._pyfree = _pyfree def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_name_entry_free(self.x509_name_entry) def _ptr(self): return self.x509_name_entry def set_object(self, asn1obj): return m2.x509_name_entry_set_object(self.x509_name_entry, asn1obj._ptr()) def set_data(self, data, type=ASN1.MBSTRING_ASC): return m2.x509_name_entry_set_data(self.x509_name_entry, type, data) def get_object(self): return ASN1.ASN1_Object(m2.x509_name_entry_get_object(self.x509_name_entry)) def get_data(self): return ASN1.ASN1_String(m2.x509_name_entry_get_data(self.x509_name_entry)) def create_by_txt( self, field, type, entry, len): return m2.x509_name_entry_create_by_txt(self.x509_name_entry._ptr(), field, type, entry, len) class X509_Name: """ X509 Name """ nid = {'C' : m2.NID_countryName, 'SP' : m2.NID_stateOrProvinceName, 'ST' : m2.NID_stateOrProvinceName, 'stateOrProvinceName' : m2.NID_stateOrProvinceName, 'L' : m2.NID_localityName, 'localityName' : m2.NID_localityName, 'O' : m2.NID_organizationName, 'organizationName' : m2.NID_organizationName, 'OU' : m2.NID_organizationalUnitName, 'organizationUnitName' : m2.NID_organizationalUnitName, 'CN' : m2.NID_commonName, 'commonName' : m2.NID_commonName, 'Email' : m2.NID_pkcs9_emailAddress, 'emailAddress' : m2.NID_pkcs9_emailAddress, 'serialNumber' : m2.NID_serialNumber, 'SN' : m2.NID_surname, 'surname' : m2.NID_surname, 'GN' : m2.NID_givenName, 'givenName' : m2.NID_givenName } m2_x509_name_free = m2.x509_name_free def __init__(self, x509_name=None, _pyfree=0): if x509_name is not None: assert m2.x509_name_type_check(x509_name), "'x509_name' type error" self.x509_name = x509_name self._pyfree = _pyfree else: self.x509_name = m2.x509_name_new () self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_name_free(self.x509_name) def __str__(self): assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return m2.x509_name_oneline(self.x509_name) def __getattr__(self, attr): if attr in self.nid: assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return m2.x509_name_by_nid(self.x509_name, self.nid[attr]) if attr in self.__dict__: return self.__dict__[attr] raise AttributeError, (self, attr) def __setattr__(self, attr, value): if attr in self.nid: assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return m2.x509_name_set_by_nid(self.x509_name, self.nid[attr], value) self.__dict__[attr] = value def __len__(self): return m2.x509_name_entry_count(self.x509_name) def __getitem__(self, idx): if not 0 <= idx < self.entry_count(): raise IndexError("index out of range") return X509_Name_Entry(m2.x509_name_get_entry(self.x509_name, idx)) def __iter__(self): for i in xrange(self.entry_count()): yield self[i] def _ptr(self): #assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return self.x509_name def add_entry_by_txt(self, field, type, entry, len, loc, set): return m2.x509_name_add_entry_by_txt(self.x509_name, field, type, entry, len, loc, set ) def entry_count( self ): return m2.x509_name_entry_count( self.x509_name ) def get_entries_by_nid(self, nid): ret = [] lastpos = -1 while True: lastpos = m2.x509_name_get_index_by_nid(self.x509_name, nid, lastpos) if lastpos == -1: break ret.append(self[lastpos]) return ret def as_text(self, indent=0, flags=m2.XN_FLAG_COMPAT): """ as_text returns the name as a string. @param indent: Each line in multiline format is indented by this many spaces. @param flags: Flags that control how the output should be formatted. """ assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" buf=BIO.MemoryBuffer() m2.x509_name_print_ex(buf.bio_ptr(), self.x509_name, indent, flags) return buf.read_all() def as_der(self): assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return m2.x509_name_get_der(self.x509_name) def as_hash(self): assert m2.x509_name_type_check(self.x509_name), "'x509_name' type error" return m2.x509_name_hash(self.x509_name) class X509: """ X.509 Certificate """ m2_x509_free = m2.x509_free def __init__(self, x509=None, _pyfree=0): if x509 is not None: assert m2.x509_type_check(x509), "'x509' type error" self.x509 = x509 self._pyfree = _pyfree else: self.x509 = m2.x509_new () self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_free(self.x509) def _ptr(self): assert m2.x509_type_check(self.x509), "'x509' type error" return self.x509 def as_text(self): assert m2.x509_type_check(self.x509), "'x509' type error" buf=BIO.MemoryBuffer() m2.x509_print(buf.bio_ptr(), self.x509) return buf.read_all() def as_der(self): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.i2d_x509(self.x509) def as_pem(self): buf=BIO.MemoryBuffer() m2.x509_write_pem(buf.bio_ptr(), self.x509) return buf.read_all() def save_pem(self, filename): """ save_pem """ bio=BIO.openfile(filename, 'wb') return m2.x509_write_pem(bio.bio_ptr(), self.x509) def save(self, filename, format=FORMAT_PEM): """ Saves X.509 certificate to a file. Default output format is PEM. @type filename: string @param filename: Name of the file the cert will be saved to. @type format: int @param format: Controls what output format is used to save the cert. Either FORMAT_PEM or FORMAT_DER to save in PEM or DER format. Raises a ValueError if an unknow format is used. """ bio = BIO.openfile(filename, 'wb') if format == FORMAT_PEM: return m2.x509_write_pem(bio.bio_ptr(), self.x509) elif format == FORMAT_DER: return m2.i2d_x509_bio(bio.bio_ptr(), self.x509) else: raise ValueError("Unknown filetype. Must be either FORMAT_PEM or FORMAT_DER") def set_version(self, version): """ Set version. @type version: int @param version: Version number. @rtype: int @return: Returns 0 on failure. """ assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_version(self.x509, version) def set_not_before(self, asn1_utctime): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_not_before(self.x509, asn1_utctime._ptr()) def set_not_after(self, asn1_utctime): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_not_after(self.x509, asn1_utctime._ptr()) def set_subject_name(self, name): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_subject_name(self.x509, name.x509_name) def set_issuer_name(self, name): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_issuer_name(self.x509, name.x509_name) def get_version(self): assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_get_version(self.x509) def get_serial_number(self): assert m2.x509_type_check(self.x509), "'x509' type error" asn1_integer = m2.x509_get_serial_number(self.x509) return m2.asn1_integer_get(asn1_integer) def set_serial_number(self, serial): """ Set serial number. @type serial: int @param serial: Serial number. """ assert m2.x509_type_check(self.x509), "'x509' type error" # This "magically" changes serial since asn1_integer # is C pointer to x509's internal serial number. asn1_integer = m2.x509_get_serial_number(self.x509) return m2.asn1_integer_set(asn1_integer, serial) # XXX Or should I do this? #asn1_integer = m2.asn1_integer_new() #m2.asn1_integer_set(asn1_integer, serial) #return m2.x509_set_serial_number(self.x509, asn1_integer) def get_not_before(self): assert m2.x509_type_check(self.x509), "'x509' type error" return ASN1.ASN1_UTCTIME(m2.x509_get_not_before(self.x509)) def get_not_after(self): assert m2.x509_type_check(self.x509), "'x509' type error" return ASN1.ASN1_UTCTIME(m2.x509_get_not_after(self.x509)) def get_pubkey(self): assert m2.x509_type_check(self.x509), "'x509' type error" return EVP.PKey(m2.x509_get_pubkey(self.x509), _pyfree=1) def set_pubkey(self, pkey): """ Set the public key for the certificate @type pkey: EVP_PKEY @param pkey: Public key """ assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_pubkey(self.x509, pkey.pkey) def get_issuer(self): assert m2.x509_type_check(self.x509), "'x509' type error" return X509_Name(m2.x509_get_issuer_name(self.x509)) def set_issuer(self, name): """ Set issuer name. @type name: X509_Name @param name: subjectName field. """ assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_issuer_name(self.x509, name.x509_name) def get_subject(self): assert m2.x509_type_check(self.x509), "'x509' type error" return X509_Name(m2.x509_get_subject_name(self.x509)) def set_subject(self, name): """ Set subject name. @type name: X509_Name @param name: subjectName field. """ assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_set_subject_name(self.x509, name.x509_name) def add_ext(self, ext): """ Add X509 extension to this certificate. @type ext: X509_Extension @param ext: Extension """ assert m2.x509_type_check(self.x509), "'x509' type error" return m2.x509_add_ext(self.x509, ext.x509_ext, -1) def get_ext(self, name): """ Get X509 extension by name. @type name: Name of the extension @param name: str @return: X509_Extension """ # Optimizations to reduce attribute accesses m2x509_get_ext = m2.x509_get_ext m2x509_extension_get_name = m2.x509_extension_get_name x509 = self.x509 for i in range(m2.x509_get_ext_count(x509)): extPtr = m2x509_get_ext(x509, i) if m2x509_extension_get_name(extPtr) == name: return X509_Extension(extPtr, _pyfree=0) raise LookupError def get_ext_at(self, index): """ Get X509 extension by index. @type index: Name of the extension @param index: int @return: X509_Extension """ if index < 0 or index >= self.get_ext_count(): raise IndexError return X509_Extension(m2.x509_get_ext(self.x509, index), _pyfree=0) def get_ext_count(self): """ Get X509 extension count. """ return m2.x509_get_ext_count(self.x509) def sign(self, pkey, md): """ Sign the certificate. @type pkey: EVP_PKEY @param pkey: Public key @type md: str @param md: Message digest algorithm to use for signing, for example 'sha1'. """ assert m2.x509_type_check(self.x509), "'x509' type error" mda = getattr(m2, md, None) if mda is None: raise ValueError, ('unknown message digest', md) return m2.x509_sign(self.x509, pkey.pkey, mda()) def verify(self, pkey=None): assert m2.x509_type_check(self.x509), "'x509' type error" if pkey: return m2.x509_verify(self.x509, pkey.pkey) else: return m2.x509_verify(self.x509, self.get_pubkey().pkey) def check_ca(self): """ Check if the certificate is a Certificate Authority (CA) certificate. @return: 0 if the certificate is not CA, nonzero otherwise. @requires: OpenSSL 0.9.8 or newer """ return m2.x509_check_ca(self.x509) def check_purpose(self, id, ca): """ Check if the certificate's purpose matches the asked purpose. @param id: Purpose id. See X509_PURPOSE_* constants. @param ca: 1 if the certificate should be CA, 0 otherwise. @return: 0 if the certificate purpose does not match, nonzero otherwise. """ return m2.x509_check_purpose(self.x509, id, ca) def get_fingerprint(self, md='md5'): """ Get the fingerprint of the certificate. @param md: Message digest algorithm to use. @return: String containing the fingerprint in hex format. """ der = self.as_der() md = EVP.MessageDigest(md) md.update(der) digest = md.final() return hex(util.octx_to_num(digest))[2:-1].upper() def load_cert(file, format=FORMAT_PEM): """ Load certificate from file. @type file: string @param file: Name of file containing certificate in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.openfile(file) if format == FORMAT_PEM: return load_cert_bio(bio) elif format == FORMAT_DER: cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1) else: raise ValueError("Unknown format. Must be either FORMAT_DER or FORMAT_PEM") def load_cert_bio(bio, format=FORMAT_PEM): """ Load certificate from a bio. @type bio: M2Crypto.BIO.BIO @param bio: BIO pointing at a certificate in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the cert to be loaded, either PEM or DER. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ if format == FORMAT_PEM: cptr = m2.x509_read_pem(bio._ptr()) elif format == FORMAT_DER: cptr = m2.d2i_x509(bio._ptr()) else: raise ValueError("Unknown format. Must be either FORMAT_DER or FORMAT_PEM") if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1) def load_cert_string(string, format=FORMAT_PEM): """ Load certificate from a string. @type string: string @param string: String containing a certificate in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the cert to be loaded, either PEM or DER. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.MemoryBuffer(string) return load_cert_bio(bio, format) def load_cert_der_string(string): """ Load certificate from a string. @type string: string @param string: String containing a certificate in DER format. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.MemoryBuffer(string) cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1) class X509_Store_Context: """ X509 Store Context """ m2_x509_store_ctx_free = m2.x509_store_ctx_free def __init__(self, x509_store_ctx, _pyfree=0): self.ctx = x509_store_ctx self._pyfree = _pyfree def __del__(self): if self._pyfree: self.m2_x509_store_ctx_free(self.ctx) def _ptr(self): return self.ctx def get_current_cert(self): """ Get current X.509 certificate. @warning: The returned certificate is NOT refcounted, so you can not rely on it being valid once the store context goes away or is modified. """ return X509(m2.x509_store_ctx_get_current_cert(self.ctx), _pyfree=0) def get_error(self): """ Get error code. """ return m2.x509_store_ctx_get_error(self.ctx) def get_error_depth(self): """ Get error depth. """ return m2.x509_store_ctx_get_error_depth(self.ctx) def get1_chain(self): """ Get certificate chain. @return: Reference counted (i.e. safe to use even after the store context goes away) stack of certificates in the chain. @rtype: X509_Stack """ return X509_Stack(m2.x509_store_ctx_get1_chain(self.ctx), 1, 1) class X509_Store: """ X509 Store """ m2_x509_store_free = m2.x509_store_free def __init__(self, store=None, _pyfree=0): if store is not None: self.store = store self._pyfree = _pyfree else: self.store = m2.x509_store_new() self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_store_free(self.store) def _ptr(self): return self.store def load_info(self, file): ret = m2.x509_store_load_locations(self.store, file) if ret < 1: raise X509Error(Err.get_error()) return ret load_locations = load_info def add_x509(self, x509): assert isinstance(x509, X509) return m2.x509_store_add_cert(self.store, x509._ptr()) add_cert = add_x509 class X509_Stack: """ X509 Stack @warning: Do not modify the underlying OpenSSL stack except through this interface, or use any OpenSSL functions that do so indirectly. Doing so will get the OpenSSL stack and the internal pystack of this class out of sync, leading to python memory leaks, exceptions or even python crashes! """ m2_sk_x509_free = m2.sk_x509_free def __init__(self, stack=None, _pyfree=0, _pyfree_x509=0): if stack is not None: self.stack = stack self._pyfree = _pyfree self.pystack = [] # This must be kept in sync with self.stack num = m2.sk_x509_num(self.stack) for i in range(num): self.pystack.append(X509(m2.sk_x509_value(self.stack, i), _pyfree=_pyfree_x509)) else: self.stack = m2.sk_x509_new_null() self._pyfree = 1 self.pystack = [] # This must be kept in sync with self.stack def __del__(self): if getattr(self, '_pyfree', 0): self.m2_sk_x509_free(self.stack) def __len__(self): assert m2.sk_x509_num(self.stack) == len(self.pystack) return len(self.pystack) def __getitem__(self, idx): return self.pystack[idx] def __iter__(self): return iter(self.pystack) def _ptr(self): return self.stack def push(self, x509): """ push an X509 certificate onto the stack. @param x509: X509 object. @return: The number of X509 objects currently on the stack. """ assert isinstance(x509, X509) self.pystack.append(x509) ret = m2.sk_x509_push(self.stack, x509._ptr()) assert ret == len(self.pystack) return ret def pop(self): """ pop a certificate from the stack. @return: X509 object that was popped, or None if there is nothing to pop. """ x509_ptr = m2.sk_x509_pop(self.stack) if x509_ptr is None: assert len(self.pystack) == 0 return None return self.pystack.pop() def as_der(self): """ Return the stack as a DER encoded string """ return m2.get_der_encoding_stack(self.stack) def new_stack_from_der(der_string): """ Create a new X509_Stack from DER string. @return: X509_Stack """ stack_ptr = m2.make_stack_from_der_sequence(der_string) if stack_ptr is None: raise X509Error(Err.get_error()) return X509_Stack(stack_ptr, 1, 1) class Request: """ X509 Certificate Request. """ m2_x509_req_free = m2.x509_req_free def __init__(self, req=None, _pyfree=0): if req is not None: self.req = req self._pyfree = _pyfree else: self.req = m2.x509_req_new() self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_req_free(self.req) def as_text(self): buf=BIO.MemoryBuffer() m2.x509_req_print(buf.bio_ptr(), self.req) return buf.read_all() def as_pem(self): buf=BIO.MemoryBuffer() m2.x509_req_write_pem(buf.bio_ptr(), self.req) return buf.read_all() def as_der(self): buf = BIO.MemoryBuffer() m2.i2d_x509_req_bio(buf.bio_ptr(), self.req) return buf.read_all() def save_pem(self, filename): bio=BIO.openfile(filename, 'wb') return m2.x509_req_write_pem(bio.bio_ptr(), self.req) def save(self, filename, format=FORMAT_PEM): """ Saves X.509 certificate request to a file. Default output format is PEM. @type filename: string @param filename: Name of the file the request will be saved to. @type format: int @param format: Controls what output format is used to save the request. Either FORMAT_PEM or FORMAT_DER to save in PEM or DER format. Raises ValueError if an unknown format is used. """ bio = BIO.openfile(filename, 'wb') if format == FORMAT_PEM: return m2.x509_req_write_pem(bio.bio_ptr(), self.req) elif format == FORMAT_DER: return m2.i2d_x509_req_bio(bio.bio_ptr(), self.req) else: raise ValueError("Unknown filetype. Must be either FORMAT_DER or FORMAT_PEM") def get_pubkey(self): """ Get the public key for the request. @rtype: EVP_PKEY @return: Public key from the request. """ return EVP.PKey(m2.x509_req_get_pubkey(self.req), _pyfree=1) def set_pubkey(self, pkey): """ Set the public key for the request. @type pkey: EVP_PKEY @param pkey: Public key @rtype: int @return: Return 1 for success and 0 for failure. """ return m2.x509_req_set_pubkey( self.req, pkey.pkey ) def get_version(self): """ Get version. @rtype: int @return: Returns version. """ return m2.x509_req_get_version(self.req) def set_version(self, version): """ Set version. @type version: int @param version: Version number. @rtype: int @return: Returns 0 on failure. """ return m2.x509_req_set_version( self.req, version ) def get_subject(self): return X509_Name(m2.x509_req_get_subject_name( self.req )) def set_subject_name(self, name): """ Set subject name. @type name: X509_Name @param name: subjectName field. """ return m2.x509_req_set_subject_name( self.req, name.x509_name ) set_subject = set_subject_name def add_extensions(self, ext_stack): """ Add X509 extensions to this request. @type ext_stack: X509_Extension_Stack @param ext_stack: Stack of extensions to add. """ return m2.x509_req_add_extensions(self.req, ext_stack._ptr()) def verify(self, pkey): return m2.x509_req_verify(self.req, pkey.pkey) def sign(self, pkey, md): mda = getattr(m2, md, None) if mda is None: raise ValueError, ('unknown message digest', md) return m2.x509_req_sign(self.req, pkey.pkey, mda()) def load_request(file, format=FORMAT_PEM): """ Load certificate request from file. @type file: string @param file: Name of file containing certificate request in either PEM or DER format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ f=BIO.openfile(file) if format == FORMAT_PEM: cptr=m2.x509_req_read_pem(f.bio_ptr()) elif format == FORMAT_DER: cptr = m2.d2i_x509_req(f.bio_ptr()) else: raise ValueError("Unknown filetype. Must be either FORMAT_PEM or FORMAT_DER") f.close() if cptr is None: raise X509Error(Err.get_error()) return Request(cptr, 1) def load_request_bio(bio, format=FORMAT_PEM): """ Load certificate request from a bio. @type bio: M2Crypto.BIO.BIO @param bio: BIO pointing at a certificate request in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the request to be loaded, either PEM or DER. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ if format == FORMAT_PEM: cptr = m2.x509_req_read_pem(bio._ptr()) elif format == FORMAT_DER: cptr = m2.d2i_x509_req(bio._ptr()) else: raise ValueError("Unknown format. Must be either FORMAT_DER or FORMAT_PEM") if cptr is None: raise X509Error(Err.get_error()) return Request(cptr, _pyfree=1) def load_request_string(string, format=FORMAT_PEM): """ Load certificate request from a string. @type string: string @param string: String containing a certificate request in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the request to be loaded, either PEM or DER. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ bio = BIO.MemoryBuffer(string) return load_request_bio(bio, format) def load_request_der_string(string): """ Load certificate request from a string. @type string: string @param string: String containing a certificate request in DER format. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ bio = BIO.MemoryBuffer(string) return load_request_bio(bio, FORMAT_DER) class CRL: """ X509 Certificate Revocation List """ m2_x509_crl_free = m2.x509_crl_free def __init__(self, crl=None, _pyfree=0): if crl is not None: self.crl = crl self._pyfree = _pyfree else: self.crl = m2.x509_crl_new() self._pyfree = 1 def __del__(self): if getattr(self, '_pyfree', 0): self.m2_x509_crl_free(self.crl) def as_text(self): """ Return CRL in PEM format in a string. @rtype: string @return: String containing the CRL in PEM format. """ buf=BIO.MemoryBuffer() m2.x509_crl_print(buf.bio_ptr(), self.crl) return buf.read_all() def load_crl(file): """ Load CRL from file. @type file: string @param file: Name of file containing CRL in PEM format. @rtype: M2Crypto.X509.CRL @return: M2Crypto.X509.CRL object. """ f=BIO.openfile(file) cptr=m2.x509_crl_read_pem(f.bio_ptr()) f.close() if cptr is None: raise X509Error(Err.get_error()) return CRL(cptr, 1) M2Crypto-0.22.6rc4/M2Crypto/__init__.py0000664000175000017500000000261312613361405017710 0ustar matejmatej00000000000000""" M2Crypto is the most complete Python wrapper for OpenSSL featuring RSA, DSA, DH, EC, HMACs, message digests, symmetric ciphers (including AES); SSL functionality to implement clients and servers; HTTPS extensions to Python's httplib, urllib, and xmlrpclib; unforgeable HMAC'ing AuthCookies for web session management; FTP/TLS client and server; S/MIME; ZServerSSL: A HTTPS server for Zope and ZSmime: An S/MIME messenger for Zope. M2Crypto can also be used to provide SSL for Twisted. Smartcards supported through the Engine interface. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004-2007 OSAF. All Rights Reserved. Copyright 2008-2011 Heikki Toivonen. All rights reserved. """ version_info = (0, 21, 1) version = '.'.join([str(_v) for _v in version_info]) import _m2crypto import m2 import ASN1 import AuthCookie import BIO import BN import Rand import DH import DSA if m2.OPENSSL_VERSION_NUMBER >= 0x90800F and m2.OPENSSL_NO_EC == 0: import EC import Err import Engine import EVP import RSA import RC4 import SMIME import SSL import X509 import PGP import m2urllib # Backwards compatibility. urllib2 = m2urllib import sys if sys.version_info >= (2,4): import m2urllib2 del sys import ftpslib import httpslib import m2xmlrpclib import threading import util encrypt=1 decrypt=0 _m2crypto.lib_init() M2Crypto-0.22.6rc4/M2Crypto/callback.py0000664000175000017500000000037112607370517017713 0ustar matejmatej00000000000000"""Deprecated, use the util module instead. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import warnings warnings.warn('Use the util module instead', DeprecationWarning) from util import genparam_callback, passphrase_callback M2Crypto-0.22.6rc4/M2Crypto/ftpslib.py0000664000175000017500000000550112607370517017622 0ustar matejmatej00000000000000"""M2Crypto client-side FTP/TLS. This implementation complies with draft-murray-auth-ftp-ssl-07.txt. Example: >>> from M2Crypto import ftpslib >>> f = ftpslib.FTP_TLS() >>> f.connect('', 9021) '220 spinnaker.dyndns.org M2Crypto (Medusa) FTP/TLS server v0.07 ready.' >>> f.auth_tls() >>> f.set_pasv(0) >>> f.login('ftp', 'ngps@') '230 Ok.' >>> f.retrlines('LIST') -rw-rw-r-- 1 0 198 2326 Jul 3 1996 apache_pb.gif drwxrwxr-x 7 0 198 1536 Oct 10 2000 manual drwxrwxr-x 2 0 198 512 Oct 31 2000 modpy drwxrwxr-x 2 0 198 512 Oct 31 2000 bobo drwxr-xr-x 2 0 198 14336 May 28 15:54 postgresql drwxr-xr-x 4 100 198 512 May 16 17:19 home drwxr-xr-x 7 100 100 3584 Sep 23 2000 openacs drwxr-xr-x 10 0 0 512 Aug 5 2000 python1.5 -rw-r--r-- 1 100 198 326 Jul 29 03:29 index.html drwxr-xr-x 12 0 0 512 May 31 17:08 python2.1 '226 Transfer complete' >>> f.quit() '221 Goodbye.' >>> Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # Python from ftplib import * from ftplib import parse150, parse227 from ftplib import error_reply, error_temp, error_perm, error_proto import socket, time # M2Crypto import SSL DEFAULT_PROTOCOL='sslv23' class FTP_TLS(FTP): """Python OO interface to client-side FTP/TLS.""" def __init__(self, host=None, ssl_ctx=None): """Initialise the client. If 'host' is supplied, connect to it.""" if ssl_ctx is not None: self.ssl_ctx = ssl_ctx else: self.ssl_ctx = SSL.Context(DEFAULT_PROTOCOL) FTP.__init__(self, host) self.prot = 0 def auth_tls(self): """Secure the control connection per AUTH TLS, aka AUTH TLS-C.""" self.voidcmd('AUTH TLS') s = SSL.Connection(self.ssl_ctx, self.sock) s.setup_ssl() s.set_connect_state() s.connect_ssl() self.sock = s self.file = self.sock.makefile() def auth_ssl(self): """Secure the control connection per AUTH SSL, aka AUTH TLS-P.""" raise NotImplementedError def prot_p(self): """Set up secure data connection.""" self.voidcmd('PBSZ 0') self.voidcmd('PROT P') self.prot = 1 def prot_c(self): """Set up data connection in the clear.""" self.voidcmd('PROT C') self.prot = 0 def ntransfercmd(self, cmd, rest=None): """Initiate a data transfer.""" conn, size = FTP.ntransfercmd(self, cmd, rest) if self.prot: conn = SSL.Connection(self.ssl_ctx, conn) conn.setup_ssl() conn.set_connect_state() conn.set_session(self.sock.get_session()) conn.connect_ssl() return conn, size M2Crypto-0.22.6rc4/M2Crypto/httpslib.py0000664000175000017500000001727612611255457020024 0ustar matejmatej00000000000000"""M2Crypto support for Python's httplib. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import sys import socket from urlparse import urlsplit, urlunsplit import base64 from httplib import * from httplib import HTTPS_PORT # This is not imported with just '*' import SSL class HTTPSConnection(HTTPConnection): """ This class allows communication via SSL using M2Crypto. """ default_port = HTTPS_PORT def __init__(self, host, port=None, strict=None, **ssl): self.session = None keys = ssl.keys() try: keys.remove('key_file') except ValueError: pass try: keys.remove('cert_file') except ValueError: pass try: keys.remove('ssl_context') except ValueError: pass if keys: raise ValueError('unknown keyword argument') try: self.ssl_ctx = ssl['ssl_context'] assert isinstance(self.ssl_ctx, SSL.Context), self.ssl_ctx except KeyError: self.ssl_ctx = SSL.Context('sslv23') HTTPConnection.__init__(self, host, port, strict) def connect(self): error = None # We ignore the returned sockaddr because SSL.Connection.connect needs # a host name. for (family, _, _, _, _) in \ socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): sock = None try: sock = SSL.Connection(self.ssl_ctx, family=family) if self.session is not None: sock.set_session(self.session) sock.connect((self.host, self.port)) self.sock = sock sock = None return except socket.error, e: # Other exception are probably SSL-related, in that case we # abort and the exception is forwarded to the caller. error = e finally: if sock is not None: sock.close() if error is None: raise AssertionError("Empty list returned by getaddrinfo") raise error def close(self): # This kludges around line 545 of httplib.py, # which closes the connection in this object; # the connection remains open in the response # object. # # M2Crypto doesn't close-here-keep-open-there, # so, in effect, we don't close until the whole # business is over and gc kicks in. # # XXX Long-running callers beware leakage. # # XXX 05-Jan-2002: This module works with Python 2.2, # XXX but I've not investigated if the above conditions # XXX remain. pass def get_session(self): return self.sock.get_session() def set_session(self, session): self.session = session class HTTPS(HTTP): _connection_class = HTTPSConnection def __init__(self, host='', port=None, strict=None, **ssl): HTTP.__init__(self, host, port, strict) try: self.ssl_ctx = ssl['ssl_context'] except KeyError: self.ssl_ctx = SSL.Context('sslv23') assert isinstance(self._conn, HTTPSConnection) self._conn.ssl_ctx = self.ssl_ctx class ProxyHTTPSConnection(HTTPSConnection): """ An HTTPS Connection that uses a proxy and the CONNECT request. When the connection is initiated, CONNECT is first sent to the proxy (along with authorization headers, if supplied). If successful, an SSL connection will be established over the socket through the proxy and to the target host. Finally, the actual request is sent over the SSL connection tunneling through the proxy. """ _ports = {'http' : 80, 'https' : 443} _AUTH_HEADER = "Proxy-Authorization" _UA_HEADER = "User-Agent" def __init__(self, host, port=None, strict=None, username=None, password=None, **ssl): """ Create the ProxyHTTPSConnection object. host and port are the hostname and port number of the proxy server. """ HTTPSConnection.__init__(self, host, port, strict, **ssl) self._username = username self._password = password self._proxy_auth = None self._proxy_UA = None def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): #putrequest is called before connect, so can interpret url and get #real host/port to be used to make CONNECT request to proxy proto, netloc, path, query, fragment = urlsplit(url) if not proto: raise ValueError, "unknown URL type: %s" % url #get host & port try: username_password, host_port = netloc.split('@') except ValueError: host_port = netloc try: host, port = host_port.split(':') except ValueError: host = host_port #try to get port from proto try: port = self._ports[proto] except KeyError: raise ValueError, "unknown protocol for: %s" % url self._real_host = host self._real_port = int(port) rest = urlunsplit((None, None, path, query, fragment)) if sys.version_info < (2,4): HTTPSConnection.putrequest(self, method, rest, skip_host) else: HTTPSConnection.putrequest(self, method, rest, skip_host, skip_accept_encoding) def putheader(self, header, value): # Store the auth header if passed in. if header.lower() == self._UA_HEADER.lower(): self._proxy_UA = value if header.lower() == self._AUTH_HEADER.lower(): self._proxy_auth = value else: HTTPSConnection.putheader(self, header, value) def endheaders(self, *args, **kwargs): # We've recieved all of hte headers. Use the supplied username # and password for authorization, possibly overriding the authstring # supplied in the headers. if not self._proxy_auth: self._proxy_auth = self._encode_auth() HTTPSConnection.endheaders(self, *args, **kwargs) def connect(self): HTTPConnection.connect(self) #send proxy CONNECT request self.sock.sendall(self._get_connect_msg()) response = HTTPResponse(self.sock) response.begin() code = response.status if code != 200: #proxy returned and error, abort connection, and raise exception self.close() raise socket.error, "Proxy connection failed: %d" % code self._start_ssl() def _get_connect_msg(self): """ Return an HTTP CONNECT request to send to the proxy. """ msg = "CONNECT %s:%d HTTP/1.1\r\n" % (self._real_host, self._real_port) msg = msg + "Host: %s:%d\r\n" % (self._real_host, self._real_port) if self._proxy_UA: msg = msg + "%s: %s\r\n" % (self._UA_HEADER, self._proxy_UA) if self._proxy_auth: msg = msg + "%s: %s\r\n" % (self._AUTH_HEADER, self._proxy_auth) msg = msg + "\r\n" return msg def _start_ssl(self): """ Make this connection's socket SSL-aware. """ self.sock = SSL.Connection(self.ssl_ctx, self.sock) self.sock.setup_ssl() self.sock.set_connect_state() self.sock.connect_ssl() def _encode_auth(self): """ Encode the username and password for use in the auth header. """ if not (self._username and self._password): return None # Authenticated proxy userpass = "%s:%s" % (self._username, self._password) enc_userpass = base64.encodestring(userpass).replace("\n", "") return "Basic %s" % enc_userpass M2Crypto-0.22.6rc4/M2Crypto/m2.py0000664000175000017500000000142012613361405016462 0ustar matejmatej00000000000000"""M2Crypto low level OpenSSL wrapper functions. m2 is the low level wrapper for OpenSSL functions. Typically you would not need to use these directly, since these will be called by the higher level objects you should try to use instead. Naming conventions: All functions wrapped by m2 are all lower case, words separated by underscores. Examples: OpenSSL M2Crypto X509_get_version m2.x509_get_version X509_get_notBefore m2.x509_get_not_before X509_REQ_verify m2.x509_req_verify Exceptions to naming rules: XXX TDB Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004 OSAF. All Rights Reserved. """ from _m2crypto import * lib_init() M2Crypto-0.22.6rc4/M2Crypto/m2urllib.py0000664000175000017500000000411412607370517017706 0ustar matejmatej00000000000000"""M2Crypto enhancement to Python's urllib for handling 'https' url's. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import string, sys, urllib from urllib import * import SSL import httpslib DEFAULT_PROTOCOL='sslv23' def open_https(self, url, data=None, ssl_context=None): if ssl_context is not None and isinstance(ssl_context, SSL.Context): self.ctx = ssl_context else: self.ctx = SSL.Context(DEFAULT_PROTOCOL) user_passwd = None if type(url) is type(""): host, selector = splithost(url) if host: user_passwd, host = splituser(host) host = unquote(host) realhost = host else: host, selector = url urltype, rest = splittype(selector) url = rest user_passwd = None if string.lower(urltype) != 'http': realhost = None else: realhost, rest = splithost(rest) if realhost: user_passwd, realhost = splituser(realhost) if user_passwd: selector = "%s://%s%s" % (urltype, realhost, rest) #print "proxy via http:", host, selector if not host: raise IOError, ('http error', 'no host given') if user_passwd: import base64 auth = string.strip(base64.encodestring(user_passwd)) else: auth = None # Start here! h = httpslib.HTTPSConnection(host=host, ssl_context=self.ctx) #h.set_debuglevel(1) # Stop here! if data is not None: h.putrequest('POST', selector) h.putheader('Content-type', 'application/x-www-form-urlencoded') h.putheader('Content-length', '%d' % len(data)) else: h.putrequest('GET', selector) if auth: h.putheader('Authorization', 'Basic %s' % auth) for args in self.addheaders: apply(h.putheader, args) h.endheaders() if data is not None: h.send(data + '\r\n') # Here again! resp = h.getresponse() fp = resp.fp return urllib.addinfourl(fp, resp.msg, "https:" + url) # Stop again. # Minor brain surgery. URLopener.open_https = open_https M2Crypto-0.22.6rc4/M2Crypto/m2urllib2.py0000664000175000017500000001222512611255457017772 0ustar matejmatej00000000000000""" M2Crypto enhancement to Python's urllib2 for handling 'https' url's. Code from urllib2 is Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; All Rights Reserved Summary of changes: - Use an HTTPSProxyConnection if the request is going through a proxy. - Add the SSL context to the https connection when performing https_open. - Add the M2Crypto HTTPSHandler when building a default opener. """ import socket from urllib2 import * import urlparse import SSL import httpslib class _closing_fileobject(socket._fileobject): '''socket._fileobject that propagates self.close() to the socket. Python 2.5 provides this as socket._fileobject(sock, close=True). ''' def __init__(self, sock): socket._fileobject.__init__(self, sock) def close(self): sock = self._sock socket._fileobject.close(self) sock.close() class HTTPSHandler(AbstractHTTPHandler): def __init__(self, ssl_context = None): AbstractHTTPHandler.__init__(self) if ssl_context is not None: assert isinstance(ssl_context, SSL.Context), ssl_context self.ctx = ssl_context else: self.ctx = SSL.Context() # Copied from urllib2, so we can set the ssl context. def https_open(self, req): """Return an addinfourl object for the request, using http_class. http_class must implement the HTTPConnection API from httplib. The addinfourl return value is a file-like object. It also has methods and attributes including: - info(): return a mimetools.Message object for the headers - geturl(): return the original request URL - code: HTTP status code """ host = req.get_host() if not host: raise URLError('no host given') # Our change: Check to see if we're using a proxy. # Then create an appropriate ssl-aware connection. full_url = req.get_full_url() target_host = urlparse.urlparse(full_url)[1] if (target_host != host): request_uri = urlparse.urldefrag(full_url)[0] h = httpslib.ProxyHTTPSConnection(host = host, ssl_context = self.ctx) else: request_uri = req.get_selector() h = httpslib.HTTPSConnection(host = host, ssl_context = self.ctx) # End our change h.set_debuglevel(self._debuglevel) headers = dict(req.headers) headers.update(req.unredirected_hdrs) # We want to make an HTTP/1.1 request, but the addinfourl # class isn't prepared to deal with a persistent connection. # It will try to read all remaining data from the socket, # which will block while the server waits for the next request. # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" try: h.request(req.get_method(), request_uri, req.data, headers) r = h.getresponse() except socket.error, err: # XXX what error? raise URLError(err) # Pick apart the HTTPResponse object to get the addinfourl # object initialized properly. # Wrap the HTTPResponse object in socket's file object adapter # for Windows. That adapter calls recv(), so delegate recv() # to read(). This weird wrapping allows the returned object to # have readline() and readlines() methods. # XXX It might be better to extract the read buffering code # out of socket._fileobject() and into a base class. r.recv = r.read fp = _closing_fileobject(r) resp = addinfourl(fp, r.msg, req.get_full_url()) resp.code = r.status resp.msg = r.reason return resp https_request = AbstractHTTPHandler.do_request_ # Copied from urllib2 with modifications for ssl def build_opener(ssl_context = None, *handlers): """Create an opener object from a list of handlers. The opener will use several default handlers, including support for HTTP and FTP. If any of the handlers passed as arguments are subclasses of the default handlers, the default handlers will not be used. """ import types def isclass(obj): return isinstance(obj, types.ClassType) or hasattr(obj, "__bases__") opener = OpenerDirector() default_classes = [ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor] skip = [] for klass in default_classes: for check in handlers: if isclass(check): if issubclass(check, klass): skip.append(klass) elif isinstance(check, klass): skip.append(klass) for klass in skip: default_classes.remove(klass) for klass in default_classes: opener.add_handler(klass()) # Add the HTTPS handler with ssl_context if HTTPSHandler not in skip: opener.add_handler(HTTPSHandler(ssl_context)) for h in handlers: if isclass(h): h = h() opener.add_handler(h) return opener M2Crypto-0.22.6rc4/M2Crypto/m2xmlrpclib.py0000664000175000017500000000361012607370517020411 0ustar matejmatej00000000000000"""M2Crypto enhancement to xmlrpclib. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import base64, string, sys from xmlrpclib import * import M2Crypto import SSL, httpslib, m2urllib __version__ = M2Crypto.version class SSL_Transport(Transport): user_agent = "M2Crypto_XMLRPC/%s - %s" % (__version__, Transport.user_agent) def __init__(self, ssl_context=None, *args, **kw): if getattr(Transport, '__init__', None) is not None: Transport.__init__(self, *args, **kw) if ssl_context is None: self.ssl_ctx=SSL.Context('sslv23') else: self.ssl_ctx=ssl_context def request(self, host, handler, request_body, verbose=0): # Handle username and password. user_passwd, host_port = m2urllib.splituser(host) _host, _port = m2urllib.splitport(host_port) h = httpslib.HTTPS(_host, int(_port), ssl_context=self.ssl_ctx) if verbose: h.set_debuglevel(1) # What follows is as in xmlrpclib.Transport. (Except the authz bit.) h.putrequest("POST", handler) # required by HTTP/1.1 h.putheader("Host", _host) # required by XML-RPC h.putheader("User-Agent", self.user_agent) h.putheader("Content-Type", "text/xml") h.putheader("Content-Length", str(len(request_body))) # Authorisation. if user_passwd is not None: auth=string.strip(base64.encodestring(user_passwd)) h.putheader('Authorization', 'Basic %s' % auth) h.endheaders() if request_body: h.send(request_body) errcode, errmsg, headers = h.getreply() if errcode != 200: raise ProtocolError( host + handler, errcode, errmsg, headers ) self.verbose = verbose return self.parse_response(h.getfile()) M2Crypto-0.22.6rc4/M2Crypto/threading.py0000664000175000017500000000053312607370517020124 0ustar matejmatej00000000000000""" M2Crypto threading support, required for multithreaded applications. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # M2Crypto import m2 def init(): """ Initialize threading support. """ m2.threading_init() def cleanup(): """ End and cleanup threading support. """ m2.threading_cleanup() M2Crypto-0.22.6rc4/M2Crypto/util.py0000664000175000017500000000306412607370517017136 0ustar matejmatej00000000000000""" M2Crypto utility routines. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004 OSAF. All Rights Reserved. """ import sys import m2 class UtilError(Exception): pass m2.util_init(UtilError) def h2b(s): import array, string ar=array.array('c') start=0 if s[:2]=='0x': start=2 for i in range(start, len(s), 2): num=string.atoi("%s"%(s[i:i+2],), 16) ar.append(chr(num)) return ar.tostring() def pkcs5_pad(data, blklen=8): pad=(8-(len(data)%8)) return data+chr(pad)*pad def pkcs7_pad(data, blklen): if blklen>255: raise ValueError, 'illegal block size' pad=(blklen-(len(data)%blklen)) return data+chr(pad)*pad def octx_to_num(x): v = 0L lx = len(x) for i in range(lx): v = v + ord(x[i]) * (256L ** (lx-i-1)) return v def genparam_callback(p, n, out=sys.stdout): ch = ['.','+','*','\n'] out.write(ch[p]) out.flush() def quiet_genparam_callback(p, n, out): pass def passphrase_callback(v, prompt1='Enter passphrase:', prompt2='Verify passphrase:'): from getpass import getpass while 1: try: p1=getpass(prompt1) if v: p2=getpass(prompt2) if p1==p2: break else: break except KeyboardInterrupt: return None return p1 def no_passphrase_callback(*args): return '' M2Crypto-0.22.6rc4/M2Crypto.egg-info/0000775000175000017500000000000012613362233017267 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/M2Crypto.egg-info/PKG-INFO0000664000175000017500000000216012613362232020362 0ustar matejmatej00000000000000Metadata-Version: 1.1 Name: M2Crypto Version: 0.22.6rc4 Summary: M2Crypto: A Python crypto and SSL toolkit Home-page: https://gitlab.com/m2crypto/m2crypto Author: Matej Cepl Author-email: mcepl@cepl.eu License: BSD-style license Description: M2Crypto is the most complete Python wrapper for OpenSSL featuring RSA, DSA, DH, EC, HMACs, message digests, symmetric ciphers (including AES); SSL functionality to implement clients and servers; HTTPS extensions to Python's httplib, urllib, and xmlrpclib; unforgeable HMAC'ing AuthCookies for web session management; FTP/TLS client and server; S/MIME; ZServerSSL: A HTTPS server for Zope and ZSmime: An S/MIME messenger for Zope. M2Crypto can also be used to provide SSL for Twisted. Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Operating System :: OS Independent Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Topic :: Security :: Cryptography Classifier: Topic :: Software Development :: Libraries :: Python Modules M2Crypto-0.22.6rc4/M2Crypto.egg-info/SOURCES.txt0000664000175000017500000002077112613362233021162 0ustar matejmatej00000000000000CHANGES INSTALL.rst LICENCE MANIFEST.in README.rst epydoc.conf fedora_setup.sh setup.cfg setup.py M2Crypto/ASN1.py M2Crypto/AuthCookie.py M2Crypto/BIO.py M2Crypto/BN.py M2Crypto/DH.py M2Crypto/DSA.py M2Crypto/EC.py M2Crypto/EVP.py M2Crypto/Engine.py M2Crypto/Err.py M2Crypto/RC4.py M2Crypto/RSA.py M2Crypto/Rand.py M2Crypto/SMIME.py M2Crypto/X509.py M2Crypto/__init__.py M2Crypto/callback.py M2Crypto/ftpslib.py M2Crypto/httpslib.py M2Crypto/m2.py M2Crypto/m2urllib.py M2Crypto/m2urllib2.py M2Crypto/m2xmlrpclib.py M2Crypto/threading.py M2Crypto/util.py M2Crypto.egg-info/PKG-INFO M2Crypto.egg-info/SOURCES.txt M2Crypto.egg-info/dependency_links.txt M2Crypto.egg-info/top_level.txt M2Crypto/PGP/PublicKey.py M2Crypto/PGP/PublicKeyRing.py M2Crypto/PGP/RSA.py M2Crypto/PGP/__init__.py M2Crypto/PGP/constants.py M2Crypto/PGP/packet.py M2Crypto/SSL/Checker.py M2Crypto/SSL/Cipher.py M2Crypto/SSL/Connection.py M2Crypto/SSL/Context.py M2Crypto/SSL/SSLServer.py M2Crypto/SSL/Session.py M2Crypto/SSL/TwistedProtocolWrapper.py M2Crypto/SSL/__init__.py M2Crypto/SSL/cb.py M2Crypto/SSL/ssl_dispatcher.py M2Crypto/SSL/timeout.py SWIG/_aes.i SWIG/_asn1.i SWIG/_bio.i SWIG/_bn.i SWIG/_dh.i SWIG/_dsa.i SWIG/_ec.i SWIG/_engine.i SWIG/_evp.i SWIG/_lib.h SWIG/_lib.i SWIG/_m2crypto.def SWIG/_m2crypto.i SWIG/_objects.i SWIG/_pkcs7.i SWIG/_rand.i SWIG/_rc4.i SWIG/_rsa.i SWIG/_ssl.i SWIG/_threads.i SWIG/_util.i SWIG/_x509.i contrib/README contrib/SimpleX509create.README contrib/SimpleX509create.py contrib/dave.README contrib/dave.patch contrib/dispatcher.README contrib/dispatcher.py contrib/isaac.README contrib/isaac.httpslib.py contrib/m2crypto.spec contrib/smimeplus.README contrib/smimeplus.py demo/bio_mem_rw.py demo/dhtest.py demo/dsa1024pvtkey.pem demo/dsa_bench.py demo/dsatest.pem demo/dsatest.py demo/rsa.priv.pem demo/rsa.priv0.pem demo/rsa.pub.pem demo/rsa1024pvtkey.pem demo/rsa_bench.py demo/rsatest.py demo/CipherSaber/CipherSaber.py demo/CipherSaber/cstest1.cs1 demo/Zope/ca.pem demo/Zope/dh1024.pem demo/Zope/server.pem demo/Zope/starts demo/Zope/starts.bat demo/Zope/z2s.py demo/Zope/z2s.py.diff demo/Zope/ZServer/HTTPS_Server.py demo/Zope/ZServer/__init__.py demo/Zope/ZServer/medusa/ftps_server.py demo/Zope/ZServer/medusa/https_server.py demo/Zope/lib/python/Products/GuardedFile/GuardedFile.py demo/Zope/lib/python/Products/GuardedFile/README.txt demo/Zope/lib/python/Products/GuardedFile/TODO.txt demo/Zope/lib/python/Products/GuardedFile/__init__.py demo/Zope/lib/python/Products/GuardedFile/add.dtml demo/Zope/lib/python/Products/GuardedFile/refresh.txt demo/Zope/lib/python/Products/GuardedFile/version.txt demo/Zope/lib/python/Products/ZSmime/README.txt demo/Zope/lib/python/Products/ZSmime/SmimeTag.py demo/Zope/lib/python/Products/ZSmime/__init__.py demo/Zope/lib/python/Products/ZSmime/version.txt demo/Zope/utilities/x509_user.py demo/Zope27/INSTALL.txt demo/Zope27/install_dir/lib/python/ZServer/HTTPS_Server.py demo/Zope27/install_dir/lib/python/ZServer/__init__.py.patch demo/Zope27/install_dir/lib/python/ZServer/component.xml.patch demo/Zope27/install_dir/lib/python/ZServer/datatypes.py.patch demo/Zope27/install_dir/lib/python/ZServer/medusa/https_server.py demo/Zope27/instance_home/README.txt.patch demo/Zope27/instance_home/etc/zope.conf.patch demo/Zope27/instance_home/ssl/ca.pem demo/Zope27/instance_home/ssl/dh1024.pem demo/Zope27/instance_home/ssl/server.pem demo/ZopeX3/INSTALL.txt demo/ZopeX3/install_dir/lib/python/zope/app/server/configure.zcml.patch demo/ZopeX3/install_dir/lib/python/zope/app/server/https.py demo/ZopeX3/install_dir/lib/python/zope/server/http/https_server.py demo/ZopeX3/install_dir/lib/python/zope/server/http/https_serverchannel.py demo/ZopeX3/install_dir/lib/python/zope/server/http/publisherhttps_server.py demo/ZopeX3/instance_home/etc/zope.conf.patch demo/ZopeX3/instance_home/ssl/ca.pem demo/ZopeX3/instance_home/ssl/dh1024.pem demo/ZopeX3/instance_home/ssl/server.pem demo/ec/ecdhtest.py demo/ec/ecdsa_bench.py demo/ec/ecdsatest.pem demo/ec/ecdsatest.py demo/ec/secp160r1pvtkey.pem demo/https.howto/ca.pem demo/https.howto/dh1024.pem demo/https.howto/get_https.py demo/https.howto/https_cli.py demo/https.howto/orig_https_srv.py demo/https.howto/server.pem demo/medusa/00_README demo/medusa/START.py demo/medusa/START_xmlrpc.py demo/medusa/asynchat.py demo/medusa/asyncore.py demo/medusa/auth_handler.py demo/medusa/ca.pem demo/medusa/counter.py demo/medusa/default_handler.py demo/medusa/dh1024.pem demo/medusa/filesys.py demo/medusa/ftp_server.py demo/medusa/ftps_server.py demo/medusa/http_date.py demo/medusa/http_server.py demo/medusa/https_server.py demo/medusa/index.html demo/medusa/logger.py demo/medusa/m_syslog.py demo/medusa/medusa_gif.py demo/medusa/mime_type_table.py demo/medusa/poison_handler.py demo/medusa/producers.py demo/medusa/put_handler.py demo/medusa/redirecting_handler.py demo/medusa/server.pem demo/medusa/status_handler.py demo/medusa/virtual_handler.py demo/medusa/xmlrpc_handler.py demo/medusa054/00_README demo/medusa054/START.py demo/medusa054/START_xmlrpc.py demo/medusa054/ca.pem demo/medusa054/counter.py demo/medusa054/default_handler.py demo/medusa054/dh1024.pem demo/medusa054/filesys.py demo/medusa054/ftp_server.py demo/medusa054/ftps_server.py demo/medusa054/http_date.py demo/medusa054/http_server.py demo/medusa054/https_server.py demo/medusa054/index.html demo/medusa054/logger.py demo/medusa054/m_syslog.py demo/medusa054/medusa_gif.py demo/medusa054/poison_handler.py demo/medusa054/producers.py demo/medusa054/server.pem demo/medusa054/status_handler.py demo/medusa054/xmlrpc_handler.py demo/perf/memio.py demo/perf/sha1.py demo/pgp/pgpstep.py demo/pgp/pubring.pgp demo/pgp/secring.pgp demo/pkcs7/pkcs7-thawte.pem demo/pkcs7/test.py demo/smime/README demo/smime/ca.pem demo/smime/clear.p7 demo/smime/client.p12 demo/smime/client.pem demo/smime/client2.pem demo/smime/m2.se.p7 demo/smime/ns.p7 demo/smime/ns.se.p7 demo/smime/opaque.p7 demo/smime/sendsmime.py demo/smime/test.py demo/smime/unsmime.py demo/smime.howto/README demo/smime.howto/decrypt.py demo/smime.howto/dv.py demo/smime.howto/encrypt.p7 demo/smime.howto/encrypt.py demo/smime.howto/recipient.pem demo/smime.howto/recipient_key.pem demo/smime.howto/se.p7 demo/smime.howto/se.py demo/smime.howto/sendsmime.py demo/smime.howto/sign.p7 demo/smime.howto/sign.py demo/smime.howto/signer.pem demo/smime.howto/signer_key.pem demo/smime.howto/verify.py demo/ssl/README demo/ssl/c.py demo/ssl/c_bio.py demo/ssl/ca.der demo/ssl/ca.pem demo/ssl/client.p12 demo/ssl/client.pem demo/ssl/dh1024.pem demo/ssl/echo-eg.py demo/ssl/echo.py demo/ssl/echod-async.py demo/ssl/echod-eg1.py demo/ssl/echod-forking.py demo/ssl/echod-iterative.py demo/ssl/echod-thread.py demo/ssl/echod-threading.py demo/ssl/echod_lib.py demo/ssl/ftp_tls.py demo/ssl/http_cli_20.py demo/ssl/https_cli.py demo/ssl/https_cli_async.py demo/ssl/https_srv.py demo/ssl/myapp.py demo/ssl/s_client.py demo/ssl/s_server.py demo/ssl/server.pem demo/ssl/server3.py demo/ssl/sess.py demo/ssl/sess2.py demo/ssl/sess2.ssldump.out demo/ssl/socklib.py demo/ssl/somelib.py demo/ssl/ss.py demo/ssl/twistedsslclient.py demo/ssl/twistedsslserver.py demo/ssl/xmlrpc_cli.py demo/ssl/xmlrpc_srv.py demo/tinderbox/build_lib.py demo/tinderbox/killableprocess.py demo/tinderbox/slave.py demo/tinderbox/winprocess.py demo/x509/ca.py demo/x509/certdata2pem.py demo/x509/client2.pem demo/x509/demo1.py demo/x509/proxy_destroy.py demo/x509/proxy_info.py demo/x509/proxy_init.py demo/x509/proxylib.py demo/x509/server-expired.pem demo/x509/server.pem demo/x509/x509auth.py doc/ZServerSSL-HOWTO.html doc/howto.ca.html doc/howto.smime.html doc/howto.ssl.html tests/README tests/__init__.py tests/alltests.py tests/ca.pem tests/der_encoded_seq.b64 tests/dhparams.pem tests/dsa.param.pem tests/dsa.priv.pem tests/dsa.pub.pem tests/ec.priv.pem tests/ec.pub.pem tests/fips.py tests/long_serial_cert.pem tests/pubring.pgp tests/randpool.dat tests/recipient.pem tests/recipient_key.pem tests/rsa.priv.pem tests/rsa.priv2.pem tests/rsa.pub.pem tests/server.pem tests/sig.p7 tests/sig.p7s tests/signer.pem tests/signer_key.pem tests/test_asn1.py tests/test_authcookie.py tests/test_bio.py tests/test_bio_file.py tests/test_bio_iobuf.py tests/test_bio_membuf.py tests/test_bio_ssl.py tests/test_bn.py tests/test_dh.py tests/test_dsa.py tests/test_ec_curves.py tests/test_ecdh.py tests/test_ecdsa.py tests/test_engine.py tests/test_evp.py tests/test_obj.py tests/test_pgp.py tests/test_rand.py tests/test_rc4.py tests/test_rsa.py tests/test_smime.py tests/test_ssl.py tests/test_ssl_offline.py tests/test_ssl_win.py tests/test_threading.py tests/test_x509.py tests/thawte.pem tests/x509.der tests/x509.pemM2Crypto-0.22.6rc4/M2Crypto.egg-info/dependency_links.txt0000664000175000017500000000000112613362232023334 0ustar matejmatej00000000000000 M2Crypto-0.22.6rc4/M2Crypto.egg-info/top_level.txt0000664000175000017500000000001112613362232022010 0ustar matejmatej00000000000000M2Crypto M2Crypto-0.22.6rc4/SWIG/0000775000175000017500000000000012613362233014667 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/SWIG/_aes.i0000664000175000017500000000402312611255457015756 0ustar matejmatej00000000000000/* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #include #endif /* // 2004-10-10, ngps: // CTR mode is not included in the default OpenSSL build. // To use the AES CTR ciphers, link with your own copy of OpenSSL. */ #ifdef HAVE_AES_CTR extern EVP_CIPHER const *EVP_aes_128_ctr(void); extern EVP_CIPHER const *EVP_aes_192_ctr(void); extern EVP_CIPHER const *EVP_aes_256_ctr(void); #endif %} %apply Pointer NONNULL { AES_KEY * }; %constant int AES_BLOCK_SIZE = AES_BLOCK_SIZE; %inline %{ AES_KEY *aes_new(void) { AES_KEY *key; if (!(key = (AES_KEY *)PyMem_Malloc(sizeof(AES_KEY)))) PyErr_SetString(PyExc_MemoryError, "aes_new"); return key; } void AES_free(AES_KEY *key) { PyMem_Free((void *)key); } /* // op == 0: decrypt // otherwise: encrypt (Python code will supply the value 1.) */ PyObject *AES_set_key(AES_KEY *key, PyObject *value, int bits, int op) { const void *vbuf; Py_ssize_t vlen; if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) return NULL; if (op == 0) AES_set_encrypt_key(vbuf, bits, key); else AES_set_decrypt_key(vbuf, bits, key); Py_INCREF(Py_None); return Py_None; } /* // op == 0: decrypt // otherwise: encrypt (Python code will supply the value 1.) */ PyObject *AES_crypt(const AES_KEY *key, PyObject *in, int outlen, int op) { const void *buf; Py_ssize_t len; unsigned char *out; PyObject *res; if (PyObject_AsReadBuffer(in, &buf, &len) == -1) return NULL; if (!(out=(unsigned char *)PyMem_Malloc(outlen))) { PyErr_SetString(PyExc_MemoryError, "AES_crypt"); return NULL; } if (op == 0) AES_encrypt((const unsigned char *)in, out, key); else AES_decrypt((const unsigned char *)in, out, key); res = PyString_FromStringAndSize((char*)out, outlen); PyMem_Free(out); return res; } int AES_type_check(AES_KEY *key) { return 1; } %} M2Crypto-0.22.6rc4/SWIG/_asn1.i0000664000175000017500000001337112607370517016056 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ /* ** Portions created by Open Source Applications Foundation (OSAF) are ** Copyright (C) 2004 OSAF. All Rights Reserved. */ /* $Id$ */ %{ #include %} %apply Pointer NONNULL { BIO * }; %apply Pointer NONNULL { ASN1_OBJECT * }; %apply Pointer NONNULL { ASN1_STRING * }; %apply Pointer NONNULL { ASN1_INTEGER * }; %apply Pointer NONNULL { ASN1_UTCTIME * }; %rename(asn1_object_new) ASN1_OBJECT_new; extern ASN1_OBJECT *ASN1_OBJECT_new( void ); %rename(asn1_object_create) ASN1_OBJECT_create; extern ASN1_OBJECT *ASN1_OBJECT_create( int, unsigned char *, int, const char *, const char *); %rename(asn1_object_free) ASN1_OBJECT_free; extern void ASN1_OBJECT_free( ASN1_OBJECT *); %rename(i2d_asn1_object) i2d_ASN1_OBJECT; extern int i2d_ASN1_OBJECT( ASN1_OBJECT *, unsigned char **); %rename(c2i_asn1_object) c2i_ASN1_OBJECT; extern ASN1_OBJECT *c2i_ASN1_OBJECT( ASN1_OBJECT **, CONST098 unsigned char **, long); %rename(d2i_asn1_object) d2i_ASN1_OBJECT; extern ASN1_OBJECT *d2i_ASN1_OBJECT( ASN1_OBJECT **, CONST098 unsigned char **, long); %rename(asn1_bit_string_new) ASN1_BIT_STRING_new; extern ASN1_BIT_STRING *ASN1_BIT_STRING_new( void ); %rename(asn1_string_new) ASN1_STRING_new; extern ASN1_STRING *ASN1_STRING_new( void ); %rename(asn1_string_free) ASN1_STRING_free; extern void ASN1_STRING_free( ASN1_STRING *); %typemap(in) (const void *, int) { if (PyString_Check($input)) { Py_ssize_t len; $1 = PyString_AsString($input); len = PyString_Size($input); if (len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); return NULL; } $2 = len; } else { PyErr_SetString(PyExc_TypeError, "expected string"); return NULL; } } %rename(asn1_string_set) ASN1_STRING_set; extern int ASN1_STRING_set( ASN1_STRING *, const void *, int); %typemap(in) (const void *, int); %rename(asn1_string_print) ASN1_STRING_print; %threadallow ASN1_STRING_print; extern int ASN1_STRING_print(BIO *, ASN1_STRING *); %threadallow ASN1_STRING_print_ex; %rename(asn1_string_print_ex) ASN1_STRING_print_ex; extern int ASN1_STRING_print_ex(BIO *, ASN1_STRING *, unsigned long); %rename(asn1_utctime_new) ASN1_UTCTIME_new; extern ASN1_UTCTIME *ASN1_UTCTIME_new( void ); %rename(asn1_utctime_free) ASN1_UTCTIME_free; extern void ASN1_UTCTIME_free(ASN1_UTCTIME *); %rename(asn1_utctime_check) ASN1_UTCTIME_check; extern int ASN1_UTCTIME_check(ASN1_UTCTIME *); %rename(asn1_utctime_set) ASN1_UTCTIME_set; extern ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *, long); %rename(asn1_utctime_set_string) ASN1_UTCTIME_set_string; extern int ASN1_UTCTIME_set_string(ASN1_UTCTIME *, CONST098 char *); %rename(asn1_utctime_print) ASN1_UTCTIME_print; %threadallow ASN1_UTCTIME_print; extern int ASN1_UTCTIME_print(BIO *, ASN1_UTCTIME *); %rename(asn1_integer_new) ASN1_INTEGER_new; extern ASN1_INTEGER *ASN1_INTEGER_new( void ); %rename(asn1_integer_free) ASN1_INTEGER_free; extern void ASN1_INTEGER_free( ASN1_INTEGER *); %rename(asn1_integer_cmp) ASN1_INTEGER_cmp; extern int ASN1_INTEGER_cmp(ASN1_INTEGER *, ASN1_INTEGER *); %constant int ASN1_STRFLGS_ESC_2253 = 1; %constant int ASN1_STRFLGS_ESC_CTRL = 2; %constant int ASN1_STRFLGS_ESC_MSB = 4; %constant int ASN1_STRFLGS_ESC_QUOTE = 8; %constant int ASN1_STRFLGS_UTF8_CONVERT = 0x10; %constant int ASN1_STRFLGS_DUMP_UNKNOWN = 0x100; %constant int ASN1_STRFLGS_DUMP_DER = 0x200; %constant int ASN1_STRFLGS_RFC2253 = (ASN1_STRFLGS_ESC_2253 | \ ASN1_STRFLGS_ESC_CTRL | \ ASN1_STRFLGS_ESC_MSB | \ ASN1_STRFLGS_UTF8_CONVERT | \ ASN1_STRFLGS_DUMP_UNKNOWN | \ ASN1_STRFLGS_DUMP_DER); %inline %{ /* ASN1_UTCTIME_set_string () is a macro */ int asn1_utctime_type_check(ASN1_UTCTIME *ASN1_UTCTIME) { return 1; } PyObject *asn1_integer_get(ASN1_INTEGER *asn1) { BIGNUM *bn; PyObject *ret; char *hex; bn = ASN1_INTEGER_to_BN(asn1, NULL); if (!bn){ PyErr_SetString( PyExc_RuntimeError, ERR_reason_error_string(ERR_get_error())); return NULL; } hex = BN_bn2hex(bn); if (!hex){ PyErr_SetString( PyExc_RuntimeError, ERR_reason_error_string(ERR_get_error())); BN_free(bn); return NULL; } BN_free(bn); ret = PyLong_FromString(hex, NULL, 16); OPENSSL_free(hex); return ret; } int asn1_integer_set(ASN1_INTEGER *asn1, PyObject *value) { BIGNUM *bn = NULL; PyObject *fmt, *args, *hex; if (PyInt_Check(value)) return ASN1_INTEGER_set(asn1, PyInt_AS_LONG(value)); if (!PyLong_Check(value)){ PyErr_SetString(PyExc_TypeError, "expected int or long"); return 0; } fmt = PyString_FromString("%x"); if (!fmt) return 0; args = PyTuple_New(1); if (!args){ Py_DECREF(fmt); PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() failed"); return 0; } Py_INCREF(value); PyTuple_SET_ITEM(args, 0, value); hex = PyString_Format(fmt, args); if (!hex){ PyErr_SetString(PyExc_RuntimeError, "PyString_Format() failed"); Py_DECREF(fmt); Py_DECREF(args); return 0; } Py_DECREF(fmt); Py_DECREF(args); if (BN_hex2bn(&bn, PyString_AsString(hex)) <= 0){ PyErr_SetString( PyExc_RuntimeError, ERR_reason_error_string(ERR_get_error())); Py_DECREF(hex); return 0; } Py_DECREF(hex); if (!BN_to_ASN1_INTEGER(bn, asn1)){ PyErr_SetString( PyExc_RuntimeError, ERR_reason_error_string(ERR_get_error())); BN_free(bn); return 0; } BN_free(bn); return 1; } %} M2Crypto-0.22.6rc4/SWIG/_bio.i0000664000175000017500000001265512611255457015771 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. * * Portions created by Open Source Applications Foundation (OSAF) are * Copyright (C) 2004-2005 OSAF. All Rights Reserved. * Author: Heikki Toivonen */ /* $Id$ */ %{ #include %} %apply Pointer NONNULL { BIO * }; %apply Pointer NONNULL { BIO_METHOD * }; %rename(bio_s_bio) BIO_s_bio; extern BIO_METHOD *BIO_s_bio(void); %rename(bio_s_mem) BIO_s_mem; extern BIO_METHOD *BIO_s_mem(void); %rename(bio_s_socket) BIO_s_socket; extern BIO_METHOD *BIO_s_socket(void); %rename(bio_f_ssl) BIO_f_ssl; extern BIO_METHOD *BIO_f_ssl(void); %rename(bio_f_buffer) BIO_f_buffer; extern BIO_METHOD *BIO_f_buffer(void); %rename(bio_f_cipher) BIO_f_cipher; extern BIO_METHOD *BIO_f_cipher(void); %rename(bio_new) BIO_new; extern BIO *BIO_new(BIO_METHOD *); %rename(bio_new_socket) BIO_new_socket; extern BIO *BIO_new_socket(int, int); %rename(bio_new_fd) BIO_new_fd; extern BIO *BIO_new_fd(int, int); %rename(bio_new_fp) BIO_new_fp; extern BIO *BIO_new_fp(FILE *, int); %rename(bio_new_file) BIO_new_file; extern BIO *BIO_new_file(const char *, const char *); %rename(bio_free) BIO_free; %threadallow BIO_free; extern int BIO_free(BIO *); %rename(bio_free_all) BIO_free_all; %threadallow BIO_free_all; extern void BIO_free_all(BIO *); %rename(bio_dup_chain) BIO_dup_chain; extern BIO *BIO_dup_chain(BIO *); %rename(bio_push) BIO_push; extern BIO *BIO_push(BIO *, BIO *); %rename(bio_pop) BIO_pop; extern BIO *BIO_pop(BIO *); %constant int bio_noclose = BIO_NOCLOSE; %constant int bio_close = BIO_CLOSE; %constant int BIO_FLAGS_READ = 0x01; %constant int BIO_FLAGS_WRITE = 0x02; %constant int BIO_FLAGS_IO_SPECIAL = 0x04; %constant int BIO_FLAGS_RWS = (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL); %constant int BIO_FLAGS_SHOULD_RETRY = 0x08; %constant int BIO_FLAGS_MEM_RDONLY = 0x200; %inline %{ static PyObject *_bio_err; void bio_init(PyObject *bio_err) { Py_INCREF(bio_err); _bio_err = bio_err; } PyObject *bio_read(BIO *bio, int num) { PyObject *blob; void *buf; int r; if (!(buf = PyMem_Malloc(num))) { PyErr_SetString(PyExc_MemoryError, "bio_read"); return NULL; } Py_BEGIN_ALLOW_THREADS r = BIO_read(bio, buf, num); Py_END_ALLOW_THREADS if (r < 0) { PyMem_Free(buf); if (ERR_peek_error()) { PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); return NULL; } Py_INCREF(Py_None); return Py_None; } blob = PyString_FromStringAndSize(buf, r); PyMem_Free(buf); return blob; } PyObject *bio_gets(BIO *bio, int num) { PyObject *blob; void *buf; int r; if (!(buf = PyMem_Malloc(num))) { PyErr_SetString(PyExc_MemoryError, "bio_gets"); return NULL; } Py_BEGIN_ALLOW_THREADS r = BIO_gets(bio, buf, num); Py_END_ALLOW_THREADS if (r < 0) { PyMem_Free(buf); if (ERR_peek_error()) { PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); return NULL; } Py_INCREF(Py_None); return Py_None; } blob = PyString_FromStringAndSize(buf, r); PyMem_Free(buf); return blob; } int bio_write(BIO *bio, PyObject *from) { const void *fbuf; int flen, ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return -1; Py_BEGIN_ALLOW_THREADS ret = BIO_write(bio, fbuf, flen); Py_END_ALLOW_THREADS if (ret < 0) { if (ERR_peek_error()) { PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); } } return ret; } /* XXX Casting size_t to int. */ int bio_ctrl_pending(BIO *bio) { return (int)BIO_ctrl_pending(bio); } int bio_ctrl_wpending(BIO *bio) { return (int)BIO_ctrl_wpending(bio); } int bio_ctrl_get_write_guarantee(BIO *a) { return BIO_ctrl_get_write_guarantee(a); } int bio_reset(BIO *bio) { return (int)BIO_reset(bio); } %} %threadallow bio_flush; %inline %{ int bio_flush(BIO *bio) { return (int)BIO_flush(bio); } int bio_seek(BIO *bio, int offset) { return (int)BIO_seek(bio, offset); } void bio_set_flags(BIO *bio, int flags) { BIO_set_flags(bio, flags); } int bio_get_flags(BIO *bio) { return BIO_get_flags(bio); } PyObject *bio_set_cipher(BIO *b, EVP_CIPHER *c, PyObject *key, PyObject *iv, int op) { const void *kbuf, *ibuf; Py_ssize_t klen, ilen; if ((PyObject_AsReadBuffer(key, &kbuf, &klen) == -1) || (PyObject_AsReadBuffer(iv, &ibuf, &ilen) == -1)) return NULL; BIO_set_cipher(b, (const EVP_CIPHER *)c, (unsigned char *)kbuf, (unsigned char *)ibuf, op); Py_INCREF(Py_None); return Py_None; } int bio_set_mem_eof_return(BIO *b, int v) { return (int)BIO_set_mem_eof_return(b, v); } int bio_get_fd(BIO *bio) { return BIO_get_fd(bio, NULL); } %} %threadallow bio_do_handshake; %inline %{ int bio_do_handshake(BIO *bio) { return BIO_do_handshake(bio); } /* macro */ int bio_make_bio_pair(BIO* b1, BIO* b2) { return BIO_make_bio_pair(b1, b2); } int bio_set_write_buf_size(BIO* b, size_t size) { return BIO_set_write_buf_size(b, size); } int bio_should_retry(BIO* a) { return BIO_should_retry(a); } int bio_should_read(BIO* a) { return BIO_should_read(a); } int bio_should_write(BIO* a) { return BIO_should_write(a); } %} M2Crypto-0.22.6rc4/SWIG/_bn.i0000775000175000017500000000565712607370517015626 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 2005-2006 Open Source Applications Foundation. All rights reserved. */ /* We are converting between the Python arbitrarily long integer and * the BIGNUM arbitrarily long integer by converting to and from * a string representation of the number (in hexadecimal). * Direct manipulation would be a possibility, but would require * tighter integration with the Python and OpenSSL internals. */ %{ #include %} %inline %{ PyObject *bn_rand(int bits, int top, int bottom) { BIGNUM rnd; PyObject *ret; char *randhex; BN_init(&rnd); if (!BN_rand(&rnd, bits, top, bottom)) { /*Custom errors?*/ PyErr_SetString(PyExc_Exception, ERR_reason_error_string(ERR_get_error())); BN_free(&rnd); return NULL; } randhex = BN_bn2hex(&rnd); if (!randhex) { /*Custom errors?*/ PyErr_SetString(PyExc_Exception, ERR_reason_error_string(ERR_get_error())); BN_free(&rnd); return NULL; } BN_free(&rnd); ret = PyLong_FromString(randhex, NULL, 16); OPENSSL_free(randhex); return ret; } PyObject *bn_rand_range(PyObject *range) { BIGNUM rnd; BIGNUM *rng = NULL; PyObject *ret, *tuple; PyObject *format, *rangePyString; char *randhex, *rangehex; /* Wow, it's a lot of work to convert into a hex string in C! */ format = PyString_FromString("%x"); if (!format) { return NULL; } tuple = PyTuple_New(1); if (!tuple) { Py_DECREF(format); PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails"); return NULL; } Py_INCREF(range); PyTuple_SET_ITEM(tuple, 0, range); rangePyString = PyString_Format(format, tuple); if (!rangePyString) { PyErr_SetString(PyExc_Exception, "PyString_Format failed"); Py_DECREF(format); Py_DECREF(tuple); return NULL; } Py_DECREF(format); Py_DECREF(tuple); rangehex = PyString_AsString(rangePyString); if (!BN_hex2bn(&rng, rangehex)) { /*Custom errors?*/ PyErr_SetString(PyExc_Exception, ERR_reason_error_string(ERR_get_error())); Py_DECREF(rangePyString); return NULL; } Py_DECREF(rangePyString); BN_init(&rnd); if (!BN_rand_range(&rnd, rng)) { /*Custom errors?*/ PyErr_SetString(PyExc_Exception, ERR_reason_error_string(ERR_get_error())); BN_free(&rnd); BN_free(rng); return NULL; } BN_free(rng); randhex = BN_bn2hex(&rnd); if (!randhex) { /*Custom errors?*/ PyErr_SetString(PyExc_Exception, ERR_reason_error_string(ERR_get_error())); BN_free(&rnd); return NULL; } BN_free(&rnd); ret = PyLong_FromString(randhex, NULL, 16); OPENSSL_free(randhex); return ret; } %} M2Crypto-0.22.6rc4/SWIG/_dh.i0000664000175000017500000001073212611255457015605 0ustar matejmatej00000000000000/* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #include #include #include #include %} %apply Pointer NONNULL { DH * }; %rename(dh_new) DH_new; extern DH *DH_new(void); %rename(dh_free) DH_free; extern void DH_free(DH *); %rename(dh_size) DH_size; extern int DH_size(const DH *); %rename(dh_generate_key) DH_generate_key; extern int DH_generate_key(DH *); %rename(dhparams_print) DHparams_print; %threadallow DHparams_print; extern int DHparams_print(BIO *, const DH *); %constant int dh_check_ok = 0; %constant int dh_check_p_not_prime = DH_CHECK_P_NOT_PRIME; %constant int dh_check_p_not_strong = DH_CHECK_P_NOT_STRONG_PRIME; %constant int dh_check_g_failed = DH_UNABLE_TO_CHECK_GENERATOR; %constant int dh_check_bad_g = DH_NOT_SUITABLE_GENERATOR; %constant DH_GENERATOR_2 = 2; %constant DH_GENERATOR_5 = 5; %inline %{ static PyObject *_dh_err; void dh_init(PyObject *dh_err) { Py_INCREF(dh_err); _dh_err = dh_err; } int dh_type_check(DH *dh) { /* Our getting here means we passed Swig's type checking, XXX Still need to check the pointer for sanity? */ return 1; } %} %threadallow dh_read_parameters; %inline %{ DH *dh_read_parameters(BIO *bio) { return PEM_read_bio_DHparams(bio, NULL, NULL, NULL); } void gendh_callback(int p, int n, void *arg) { PyObject *argv, *ret, *cbfunc; cbfunc = (PyObject *)arg; argv = Py_BuildValue("(ii)", p, n); ret = PyEval_CallObject(cbfunc, argv); PyErr_Clear(); Py_DECREF(argv); Py_XDECREF(ret); } DH *dh_generate_parameters(int plen, int g, PyObject *pyfunc) { DH *dh; Py_INCREF(pyfunc); dh = DH_generate_parameters(plen, g, gendh_callback, (void *)pyfunc); Py_DECREF(pyfunc); if (!dh) PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error())); return dh; } /* Note return value shenanigan. */ int dh_check(DH *dh) { int err; return (DH_check(dh, &err)) ? 0 : err; } PyObject *dh_compute_key(DH *dh, PyObject *pubkey) { const void *pkbuf; int pklen, klen; void *key; BIGNUM *pk; PyObject *ret; if (m2_PyObject_AsReadBufferInt(pubkey, &pkbuf, &pklen) == -1) return NULL; if (!(pk = BN_mpi2bn((unsigned char *)pkbuf, pklen, NULL))) { PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(key = PyMem_Malloc(DH_size(dh)))) { BN_free(pk); PyErr_SetString(PyExc_MemoryError, "dh_compute_key"); return NULL; } if ((klen = DH_compute_key((unsigned char *)key, pk, dh)) == -1) { BN_free(pk); PyMem_Free(key); PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)key, klen); BN_free(pk); PyMem_Free(key); return ret; } PyObject *dh_get_p(DH *dh) { if (!dh->p) { PyErr_SetString(_dh_err, "'p' is unset"); return NULL; } return bn_to_mpi(dh->p); } PyObject *dh_get_g(DH *dh) { if (!dh->g) { PyErr_SetString(_dh_err, "'g' is unset"); return NULL; } return bn_to_mpi(dh->g); } PyObject *dh_get_pub(DH *dh) { if (!dh->pub_key) { PyErr_SetString(_dh_err, "'pub' is unset"); return NULL; } return bn_to_mpi(dh->pub_key); } PyObject *dh_get_priv(DH *dh) { if (!dh->priv_key) { PyErr_SetString(_dh_err, "'priv' is unset"); return NULL; } return bn_to_mpi(dh->priv_key); } PyObject *dh_set_p(DH *dh, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (dh->p) BN_free(dh->p); dh->p = bn; Py_INCREF(Py_None); return Py_None; } PyObject *dh_set_g(DH *dh, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (dh->g) BN_free(dh->g); dh->g = bn; Py_INCREF(Py_None); return Py_None; } %} M2Crypto-0.22.6rc4/SWIG/_dsa.i0000664000175000017500000002063312611255457015762 0ustar matejmatej00000000000000/* Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #include #include #include PyObject *dsa_sig_get_r(DSA_SIG *dsa_sig) { return bn_to_mpi(dsa_sig->r); } PyObject *dsa_sig_get_s(DSA_SIG *dsa_sig) { return bn_to_mpi(dsa_sig->s); } %} %apply Pointer NONNULL { DSA * }; %rename(dsa_new) DSA_new; extern DSA *DSA_new(void); %rename(dsa_free) DSA_free; extern void DSA_free(DSA *); %rename(dsa_size) DSA_size; extern int DSA_size(const DSA *); /* assert(dsa->q); */ %rename(dsa_gen_key) DSA_generate_key; extern int DSA_generate_key(DSA *); %inline %{ static PyObject *_dsa_err; void dsa_init(PyObject *dsa_err) { Py_INCREF(dsa_err); _dsa_err = dsa_err; } void genparam_callback(int p, int n, void *arg) { PyObject *argv, *ret, *cbfunc; cbfunc = (PyObject *)arg; argv = Py_BuildValue("(ii)", p, n); ret = PyEval_CallObject(cbfunc, argv); PyErr_Clear(); Py_DECREF(argv); Py_XDECREF(ret); } DSA *dsa_generate_parameters(int bits, PyObject *pyfunc) { DSA *dsa; Py_INCREF(pyfunc); dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, genparam_callback, (void *)pyfunc); Py_DECREF(pyfunc); if (!dsa) PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return dsa; } PyObject *dsa_get_p(DSA *dsa) { if (!dsa->p) { PyErr_SetString(_dsa_err, "'p' is unset"); return NULL; } return bn_to_mpi(dsa->p); } PyObject *dsa_get_q(DSA *dsa) { if (!dsa->q) { PyErr_SetString(_dsa_err, "'q' is unset"); return NULL; } return bn_to_mpi(dsa->q); } PyObject *dsa_get_g(DSA *dsa) { if (!dsa->g) { PyErr_SetString(_dsa_err, "'g' is unset"); return NULL; } return bn_to_mpi(dsa->g); } PyObject *dsa_get_pub(DSA *dsa) { if (!dsa->pub_key) { PyErr_SetString(_dsa_err, "'pub' is unset"); return NULL; } return bn_to_mpi(dsa->pub_key); } PyObject *dsa_get_priv(DSA *dsa) { if (!dsa->priv_key) { PyErr_SetString(_dsa_err, "'priv' is unset"); return NULL; } return bn_to_mpi(dsa->priv_key); } PyObject *dsa_set_p(DSA *dsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (dsa->p) BN_free(dsa->p); dsa->p = bn; Py_INCREF(Py_None); return Py_None; } PyObject *dsa_set_q(DSA *dsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (dsa->q) BN_free(dsa->q); dsa->q = bn; Py_INCREF(Py_None); return Py_None; } PyObject *dsa_set_g(DSA *dsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (dsa->g) BN_free(dsa->g); dsa->g = bn; Py_INCREF(Py_None); return Py_None; } %} %inline %{ DSA *dsa_read_params(BIO *f, PyObject *pyfunc) { DSA *ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_read_bio_DSAparams(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %threadallow dsa_write_params_bio; %inline %{ int dsa_write_params_bio(DSA* dsa, BIO* f) { return PEM_write_bio_DSAparams(f, dsa); } %} %inline %{ int dsa_write_key_bio(DSA* dsa, BIO* f, EVP_CIPHER *cipher, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_DSAPrivateKey(f, dsa, cipher, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ int dsa_write_key_bio_no_cipher(DSA* dsa, BIO* f, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_DSAPrivateKey(f, dsa, NULL, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %threadallow dsa_write_pub_key_bio; %inline %{ int dsa_write_pub_key_bio(DSA* dsa, BIO* f) { return PEM_write_bio_DSA_PUBKEY(f, dsa); } %} %inline %{ DSA *dsa_read_key(BIO *f, PyObject *pyfunc) { DSA *ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_read_bio_DSAPrivateKey(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ DSA *dsa_read_pub_key(BIO *f, PyObject *pyfunc) { DSA *ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_read_bio_DSA_PUBKEY(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } PyObject *dsa_sign(DSA *dsa, PyObject *value) { const void *vbuf; int vlen; PyObject *tuple; DSA_SIG *sig; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(sig = DSA_do_sign(vbuf, vlen, dsa))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(tuple = PyTuple_New(2))) { DSA_SIG_free(sig); PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails"); return NULL; } PyTuple_SET_ITEM(tuple, 0, dsa_sig_get_r(sig)); PyTuple_SET_ITEM(tuple, 1, dsa_sig_get_s(sig)); DSA_SIG_free(sig); return tuple; } int dsa_verify(DSA *dsa, PyObject *value, PyObject *r, PyObject *s) { const void *vbuf, *rbuf, *sbuf; int vlen, rlen, slen; DSA_SIG *sig; int ret; if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) || (m2_PyObject_AsReadBufferInt(r, &rbuf, &rlen) == -1) || (m2_PyObject_AsReadBufferInt(s, &sbuf, &slen) == -1)) return -1; if (!(sig = DSA_SIG_new())) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return -1; } if (!(sig->r = BN_mpi2bn((unsigned char *)rbuf, rlen, NULL))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); DSA_SIG_free(sig); return -1; } if (!(sig->s = BN_mpi2bn((unsigned char *)sbuf, slen, NULL))) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); DSA_SIG_free(sig); return -1; } ret = DSA_do_verify(vbuf, vlen, sig, dsa); DSA_SIG_free(sig); if (ret == -1) PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return ret; } PyObject *dsa_sign_asn1(DSA *dsa, PyObject *value) { const void *vbuf; int vlen; void *sigbuf; unsigned int siglen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(sigbuf = PyMem_Malloc(DSA_size(dsa)))) { PyErr_SetString(PyExc_MemoryError, "dsa_sign_asn1"); return NULL; } if (!DSA_sign(0, vbuf, vlen, (unsigned char *)sigbuf, &siglen, dsa)) { PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); PyMem_Free(sigbuf); return NULL; } ret = PyString_FromStringAndSize(sigbuf, siglen); PyMem_Free(sigbuf); return ret; } int dsa_verify_asn1(DSA *dsa, PyObject *value, PyObject *sig) { const void *vbuf; void *sbuf; int vlen, slen, ret; if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) || (m2_PyObject_AsReadBufferInt(sig, (const void **)&sbuf, &slen) == -1)) return -1; if ((ret = DSA_verify(0, vbuf, vlen, sbuf, slen, dsa)) == -1) PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error())); return ret; } int dsa_check_key(DSA *dsa) { return (dsa->pub_key) && (dsa->priv_key); } int dsa_check_pub_key(DSA *dsa) { return dsa->pub_key ? 1 : 0; } int dsa_keylen(DSA *dsa) { return BN_num_bits(dsa->p); } int dsa_type_check(DSA *dsa) { return 1; } %} M2Crypto-0.22.6rc4/SWIG/_ec.i0000664000175000017500000003146312611267722015603 0ustar matejmatej00000000000000/* Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved. Most code originally from _dsa.i, _rsa.i and _dh.i and adjusted for EC use. */ %include #if OPENSSL_VERSION_NUMBER < 0x0090800fL || defined(OPENSSL_NO_EC) #undef OPENSSL_NO_EC %constant OPENSSL_NO_EC = 1; #else %constant OPENSSL_NO_EC = 0; %{ #include #include #include #include #include #include %} %apply Pointer NONNULL { EC_KEY * }; %rename(ec_key_new) EC_KEY_new; extern EC_KEY *EC_KEY_new(void); %rename(ec_key_free) EC_KEY_free; extern void EC_KEY_free(EC_KEY *); %rename(ec_key_size) ECDSA_size; extern int ECDSA_size(const EC_KEY *); %rename(ec_key_gen_key) EC_KEY_generate_key; extern int EC_KEY_generate_key(EC_KEY *); %rename(ec_key_check_key) EC_KEY_check_key; extern int EC_KEY_check_key(const EC_KEY *); /* Curve identifier constants from OpenSSL */ %constant int NID_secp112r1 = NID_secp112r1; %constant int NID_secp112r2 = NID_secp112r2; %constant int NID_secp128r1 = NID_secp128r1; %constant int NID_secp128r2 = NID_secp128r2; %constant int NID_secp160k1 = NID_secp160k1; %constant int NID_secp160r1 = NID_secp160r1; %constant int NID_secp160r2 = NID_secp160r2; %constant int NID_secp192k1 = NID_secp192k1; %constant int NID_secp224k1 = NID_secp224k1; %constant int NID_secp224r1 = NID_secp224r1; %constant int NID_secp256k1 = NID_secp256k1; %constant int NID_secp384r1 = NID_secp384r1; %constant int NID_secp521r1 = NID_secp521r1; %constant int NID_sect113r1 = NID_sect113r1; %constant int NID_sect113r2 = NID_sect113r2; %constant int NID_sect131r1 = NID_sect131r1; %constant int NID_sect131r2 = NID_sect131r2; %constant int NID_sect163k1 = NID_sect163k1; %constant int NID_sect163r1 = NID_sect163r1; %constant int NID_sect163r2 = NID_sect163r2; %constant int NID_sect193r1 = NID_sect193r1; %constant int NID_sect193r2 = NID_sect193r2; %constant int NID_sect233k1 = NID_sect233k1; %constant int NID_sect233r1 = NID_sect233r1; %constant int NID_sect239k1 = NID_sect239k1; %constant int NID_sect283k1 = NID_sect283k1; %constant int NID_sect283r1 = NID_sect283r1; %constant int NID_sect409k1 = NID_sect409k1; %constant int NID_sect409r1 = NID_sect409r1; %constant int NID_sect571k1 = NID_sect571k1; %constant int NID_sect571r1 = NID_sect571r1; %constant int NID_X9_62_prime192v1 = NID_X9_62_prime192v1; %constant int NID_X9_62_prime192v2 = NID_X9_62_prime192v2; %constant int NID_X9_62_prime192v3 = NID_X9_62_prime192v3; %constant int NID_X9_62_prime239v1 = NID_X9_62_prime239v1; %constant int NID_X9_62_prime239v2 = NID_X9_62_prime239v2; %constant int NID_X9_62_prime239v3 = NID_X9_62_prime239v3; %constant int NID_X9_62_prime256v1 = NID_X9_62_prime256v1; %constant int NID_X9_62_c2pnb163v1 = NID_X9_62_c2pnb163v1; %constant int NID_X9_62_c2pnb163v2 = NID_X9_62_c2pnb163v2; %constant int NID_X9_62_c2pnb163v3 = NID_X9_62_c2pnb163v3; %constant int NID_X9_62_c2pnb176v1 = NID_X9_62_c2pnb176v1; %constant int NID_X9_62_c2tnb191v1 = NID_X9_62_c2tnb191v1; %constant int NID_X9_62_c2tnb191v2 = NID_X9_62_c2tnb191v2; %constant int NID_X9_62_c2tnb191v3 = NID_X9_62_c2tnb191v3; %constant int NID_X9_62_c2pnb208w1 = NID_X9_62_c2pnb208w1; %constant int NID_X9_62_c2tnb239v1 = NID_X9_62_c2tnb239v1; %constant int NID_X9_62_c2tnb239v2 = NID_X9_62_c2tnb239v2; %constant int NID_X9_62_c2tnb239v3 = NID_X9_62_c2tnb239v3; %constant int NID_X9_62_c2pnb272w1 = NID_X9_62_c2pnb272w1; %constant int NID_X9_62_c2pnb304w1 = NID_X9_62_c2pnb304w1; %constant int NID_X9_62_c2tnb359v1 = NID_X9_62_c2tnb359v1; %constant int NID_X9_62_c2pnb368w1 = NID_X9_62_c2pnb368w1; %constant int NID_X9_62_c2tnb431r1 = NID_X9_62_c2tnb431r1; %constant int NID_wap_wsg_idm_ecid_wtls1 = NID_wap_wsg_idm_ecid_wtls1; %constant int NID_wap_wsg_idm_ecid_wtls3 = NID_wap_wsg_idm_ecid_wtls3; %constant int NID_wap_wsg_idm_ecid_wtls4 = NID_wap_wsg_idm_ecid_wtls4; %constant int NID_wap_wsg_idm_ecid_wtls5 = NID_wap_wsg_idm_ecid_wtls5; %constant int NID_wap_wsg_idm_ecid_wtls6 = NID_wap_wsg_idm_ecid_wtls6; %constant int NID_wap_wsg_idm_ecid_wtls7 = NID_wap_wsg_idm_ecid_wtls7; %constant int NID_wap_wsg_idm_ecid_wtls8 = NID_wap_wsg_idm_ecid_wtls8; %constant int NID_wap_wsg_idm_ecid_wtls9 = NID_wap_wsg_idm_ecid_wtls9; %constant int NID_wap_wsg_idm_ecid_wtls10 = NID_wap_wsg_idm_ecid_wtls10; %constant int NID_wap_wsg_idm_ecid_wtls11 = NID_wap_wsg_idm_ecid_wtls11; %constant int NID_wap_wsg_idm_ecid_wtls12 = NID_wap_wsg_idm_ecid_wtls12; %constant int NID_ipsec3 = NID_ipsec3; %constant int NID_ipsec4 = NID_ipsec4; %inline %{ static PyObject *_ec_err; void ec_init(PyObject *ec_err) { Py_INCREF(ec_err); _ec_err = ec_err; } EC_KEY* ec_key_new_by_curve_name(int nid) { EC_KEY *key; EC_GROUP *group; int ret =0; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; int asn1_flag = OPENSSL_EC_NAMED_CURVE; /* If I simply do "return EC_KEY_new_by_curve_name(nid);" * I get large public keys (222 vs 84 bytes for sect233k1 curve). * I don't know why that is, but 'openssl ecparam -genkey ...' sets * the ASN.1 flag and the point conversion form, and gets the * small pub keys. So let's do that too. */ key = EC_KEY_new(); if (!key) { PyErr_SetString(PyExc_MemoryError, "ec_key_new_by_curve_name"); return NULL; } group = EC_GROUP_new_by_curve_name(nid); if (!group) { EC_KEY_free(key); PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } EC_GROUP_set_asn1_flag(group, asn1_flag); EC_GROUP_set_point_conversion_form(group, form); ret = EC_KEY_set_group(key, group); EC_GROUP_free(group); if (ret == 0) { /* EC_KEY_set_group only returns 0 or 1, and does not set error. */ PyErr_SetString(_ec_err, "cannot set key's group"); EC_KEY_free(key); return NULL; } return key; } PyObject *ec_key_get_public_der(EC_KEY *key) { unsigned char *src=NULL; void *dst=NULL; int src_len=0; Py_ssize_t dst_len=0; PyObject *pyo=NULL; int ret=0; /* Convert to binary */ src_len = i2d_EC_PUBKEY( key, &src ); if (src_len < 0) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } /* Create a PyBuffer containing a copy of the binary, * to simplify memory deallocation */ pyo = PyBuffer_New( src_len ); ret = PyObject_AsWriteBuffer( pyo, &dst, &dst_len ); assert( src_len == dst_len ); if (ret < 0) { Py_DECREF(pyo); OPENSSL_free(src); PyErr_SetString(_ec_err, "cannot get write buffer"); return NULL; } memcpy( dst, src, src_len ); OPENSSL_free(src); return pyo; } %} %threadallow ec_key_read_pubkey; %inline %{ EC_KEY *ec_key_read_pubkey(BIO *f) { return PEM_read_bio_EC_PUBKEY(f, NULL, NULL, NULL); } %} %threadallow ec_key_write_pubkey; %inline %{ int ec_key_write_pubkey(EC_KEY *key, BIO *f) { return PEM_write_bio_EC_PUBKEY(f, key ); } %} %inline %{ EC_KEY *ec_key_read_bio(BIO *f, PyObject *pyfunc) { EC_KEY *ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_read_bio_ECPrivateKey(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ int ec_key_write_bio(EC_KEY *key, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_ECPrivateKey(f, key, cipher, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ int ec_key_write_bio_no_cipher(EC_KEY *key, BIO *f, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_ECPrivateKey(f, key, NULL, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } PyObject *ecdsa_sig_get_r(ECDSA_SIG *ecdsa_sig) { return bn_to_mpi(ecdsa_sig->r); } PyObject *ecdsa_sig_get_s(ECDSA_SIG *ecdsa_sig) { return bn_to_mpi(ecdsa_sig->s); } PyObject *ecdsa_sign(EC_KEY *key, PyObject *value) { const void *vbuf; int vlen; PyObject *tuple; ECDSA_SIG *sig; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(sig = ECDSA_do_sign(vbuf, vlen, key))) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(tuple = PyTuple_New(2))) { ECDSA_SIG_free(sig); PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails"); return NULL; } PyTuple_SET_ITEM(tuple, 0, ecdsa_sig_get_r(sig)); PyTuple_SET_ITEM(tuple, 1, ecdsa_sig_get_s(sig)); ECDSA_SIG_free(sig); return tuple; } int ecdsa_verify(EC_KEY *key, PyObject *value, PyObject *r, PyObject *s) { const void *vbuf, *rbuf, *sbuf; int vlen, rlen, slen; ECDSA_SIG *sig; int ret; if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) || (m2_PyObject_AsReadBufferInt(r, &rbuf, &rlen) == -1) || (m2_PyObject_AsReadBufferInt(s, &sbuf, &slen) == -1)) return -1; if (!(sig = ECDSA_SIG_new())) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return -1; } if (!BN_mpi2bn((unsigned char *)rbuf, rlen, sig->r)) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); ECDSA_SIG_free(sig); return -1; } if (!BN_mpi2bn((unsigned char *)sbuf, slen, sig->s)) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); ECDSA_SIG_free(sig); return -1; } ret = ECDSA_do_verify(vbuf, vlen, sig, key); ECDSA_SIG_free(sig); if (ret == -1) PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return ret; } PyObject *ecdsa_sign_asn1(EC_KEY *key, PyObject *value) { const void *vbuf; int vlen; void *sigbuf; unsigned int siglen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(sigbuf = PyMem_Malloc(ECDSA_size(key)))) { PyErr_SetString(PyExc_MemoryError, "ecdsa_sign_asn1"); return NULL; } if (!ECDSA_sign(0, vbuf, vlen, (unsigned char *)sigbuf, &siglen, key)) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); PyMem_Free(sigbuf); return NULL; } ret = PyString_FromStringAndSize(sigbuf, siglen); PyMem_Free(sigbuf); return ret; } int ecdsa_verify_asn1(EC_KEY *key, PyObject *value, PyObject *sig) { const void *vbuf; void *sbuf; int vlen, slen, ret; if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) || (m2_PyObject_AsReadBufferInt(sig, (const void **)&sbuf, &slen) == -1)) return -1; if ((ret = ECDSA_verify(0, vbuf, vlen, sbuf, slen, key)) == -1) PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return ret; } PyObject *ecdh_compute_key(EC_KEY *keypairA, EC_KEY *pubkeyB) { int sharedkeylen; void *sharedkey; const EC_POINT *pkpointB; PyObject *ret; const EC_GROUP* groupA; if ((pkpointB = EC_KEY_get0_public_key(pubkeyB)) == NULL) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } groupA = EC_KEY_get0_group(keypairA); sharedkeylen = (EC_GROUP_get_degree(groupA) + 7)/8; if (!(sharedkey = PyMem_Malloc(sharedkeylen))) { PyErr_SetString(PyExc_MemoryError, "ecdh_compute_key"); return NULL; } if ((sharedkeylen = ECDH_compute_key((unsigned char *)sharedkey, sharedkeylen, pkpointB, keypairA, NULL)) == -1) { PyMem_Free(sharedkey); PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)sharedkey, sharedkeylen); PyMem_Free(sharedkey); return ret; } EC_KEY* ec_key_from_pubkey_der(PyObject *pubkey) { const void *keypairbuf; Py_ssize_t keypairbuflen; const unsigned char *tempBuf; EC_KEY *keypair; if (PyObject_AsReadBuffer(pubkey, &keypairbuf, &keypairbuflen) == -1) { return NULL; } tempBuf = (const unsigned char *)keypairbuf; if ((keypair = d2i_EC_PUBKEY( NULL, &tempBuf, keypairbuflen)) == 0) { PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error())); return NULL; } return keypair; } // According to [SEC2] the degree of the group is defined as EC key length int ec_key_keylen(EC_KEY *key) { const EC_GROUP *group = EC_KEY_get0_group(key); return EC_GROUP_get_degree(group); } int ec_key_type_check(EC_KEY *key) { return 1; } %} #endif // if OpenSSL version with EC support M2Crypto-0.22.6rc4/SWIG/_engine.i0000664000175000017500000001251312212052026016436 0ustar matejmatej00000000000000/* * -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: syntax=c sts=4 sw=4 * * ENGINE functions from engine(3SSL). * * Pavel Shramov * IMEC MSU */ %{ #include #include #include %} %apply Pointer NONNULL { ENGINE * }; %apply Pointer NONNULL { const ENGINE * }; %apply Pointer NONNULL { const char * }; /* * Functions to load different engines */ %rename(engine_load_builtin_engines) ENGINE_load_builtin_engines; extern void ENGINE_load_builtin_engines(void); %rename(engine_load_dynamic) ENGINE_load_dynamic; extern void ENGINE_load_dynamic(void); %rename(engine_load_openssl) ENGINE_load_openssl; extern void ENGINE_load_openssl(void); %rename(engine_cleanup) ENGINE_cleanup; extern void ENGINE_cleanup(void); /* * Engine allocation functions */ %rename(engine_new) ENGINE_new; extern ENGINE * ENGINE_new(); %rename(engine_by_id) ENGINE_by_id; extern ENGINE * ENGINE_by_id(const char *); %rename(engine_free) ENGINE_free; extern int ENGINE_free(ENGINE *); %rename(engine_init) ENGINE_init; extern int ENGINE_init(ENGINE *); %rename(engine_finish) ENGINE_finish; extern int ENGINE_finish(ENGINE *); /* * Engine id/name functions */ %rename(engine_get_id) ENGINE_get_id; extern const char * ENGINE_get_id(const ENGINE *); %rename(engine_get_name) ENGINE_get_name; extern const char * ENGINE_get_name(const ENGINE *); /* * Engine control functions * Control argument may be NULL (e.g for LOAD command) */ %clear const char *; %rename(engine_ctrl_cmd_string) ENGINE_ctrl_cmd_string; extern int ENGINE_ctrl_cmd_string(ENGINE *e, const char *NONNULL, const char *arg, int cmd_optional); %apply Pointer NONNULL { const char * }; /* * UI methods. * XXX: UI_OpenSSL method is static and UI_destroy_method is not needed. */ %rename(ui_openssl) UI_OpenSSL; extern UI_METHOD * UI_OpenSSL(); /* %rename(ui_destroy_method) UI_destroy_method; extern void UI_destroy_method(UI_METHOD *ui_method); */ %clear const char *; %inline %{ /* * Code from engine-pkcs11 1.4.0 in engine-pkcs11.c * 99 static char *get_pin(UI_METHOD * ui_method, void *callback_data, char *sc_pin, 100 int maxlen) 101 { 102 UI *ui; 103 struct { 104 const void *password; 105 const char *prompt_info; 106 } *mycb = callback_data; 107 108 if (mycb->password) { 109 sc_pin = set_pin(mycb->password); 110 return sc_pin; 111 } * * So callback_data need to be always provided and have fixed type. * UI method still may be NULL. * * Following functions allocate and free callback data structure with * optional password set. */ typedef struct { char * password; char * prompt; } _cbd_t; void * engine_pkcs11_data_new(const char *pin) { _cbd_t * cb = (_cbd_t *) PyMem_Malloc(sizeof(_cbd_t)); if (!cb) { PyErr_SetString(PyExc_MemoryError, "engine_pkcs11_data_new"); return NULL; } cb->password = NULL; if (pin) { size_t size = strlen(pin); cb->password = (char *) PyMem_Malloc(size + 1); if (!cb->password) { PyErr_SetString(PyExc_MemoryError, "engine_pkcs11_data_new"); PyMem_Free(cb); return NULL; } memcpy(cb->password, pin, size + 1); } cb->prompt = NULL; return cb; } void engine_pkcs11_data_free(void * vcb) { _cbd_t * cb = (_cbd_t *) vcb; if (!cb) return; if (cb->password) PyMem_Free(cb->password); PyMem_Free(cb); } %} %apply Pointer NONNULL { const char * }; /* * Engine key/cert load functions. * See above notice about callback_data. */ %rename(engine_load_private_key) ENGINE_load_private_key; extern EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); %rename(engine_load_public_key) ENGINE_load_public_key; extern EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); /* * This function may be not implemented in engine. * pkcs11 engine has this control. */ %inline %{ static PyObject *_engine_err; void engine_init_error(PyObject *engine_err) { Py_INCREF(engine_err); _engine_err = engine_err; } X509 * engine_load_certificate(ENGINE *e, const char * slot) { struct { const char * slot; X509 * cert; } cbd; cbd.slot = slot; cbd.cert = NULL; if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &cbd, NULL, 0)) { PyErr_SetString(_engine_err, "cannot load certificate"); return NULL; } return cbd.cert; } %} /* These flags are used to control combinations of algorithm (methods) * by bitwise "OR"ing. */ %constant int ENGINE_METHOD_RSA = 0x0001; %constant int ENGINE_METHOD_DSA = 0x0002; %constant int ENGINE_METHOD_DH = 0x0004; %constant int ENGINE_METHOD_RAND = 0x0008; %constant int ENGINE_METHOD_ECDH = 0x0010; %constant int ENGINE_METHOD_ECDSA = 0x0020; %constant int ENGINE_METHOD_CIPHERS = 0x0040; %constant int ENGINE_METHOD_DIGESTS = 0x0080; %constant int ENGINE_METHOD_STORE = 0x0100; /* Obvious all-or-nothing cases. */ %constant int ENGINE_METHOD_ALL = 0xFFFF; %constant int ENGINE_METHOD_NONE = 0x0000; %rename(engine_set_default) ENGINE_set_default; extern int ENGINE_set_default(ENGINE *e, unsigned int flags); M2Crypto-0.22.6rc4/SWIG/_evp.i0000664000175000017500000004220512611267725016005 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. Portions Copyright (c) 2004-2007 Open Source Applications Foundation. Author: Heikki Toivonen Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. */ %include %{ #include #include #include #include #include #include %} %apply Pointer NONNULL { EVP_MD_CTX * }; %apply Pointer NONNULL { EVP_MD * }; %apply Pointer NONNULL { EVP_PKEY * }; %apply Pointer NONNULL { HMAC_CTX * }; %apply Pointer NONNULL { EVP_CIPHER_CTX * }; %apply Pointer NONNULL { EVP_CIPHER * }; %apply Pointer NONNULL { RSA * }; %rename(md5) EVP_md5; extern const EVP_MD *EVP_md5(void); %rename(sha1) EVP_sha1; extern const EVP_MD *EVP_sha1(void); %rename(ripemd160) EVP_ripemd160; extern const EVP_MD *EVP_ripemd160(void); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL %rename(sha224) EVP_sha224; extern const EVP_MD *EVP_sha224(void); %rename(sha256) EVP_sha256; extern const EVP_MD *EVP_sha256(void); %rename(sha384) EVP_sha384; extern const EVP_MD *EVP_sha384(void); %rename(sha512) EVP_sha512; extern const EVP_MD *EVP_sha512(void); #endif %rename(digest_init) EVP_DigestInit; extern int EVP_DigestInit(EVP_MD_CTX *, const EVP_MD *); %rename(des_ecb) EVP_des_ecb; extern const EVP_CIPHER *EVP_des_ecb(void); %rename(des_ede_ecb) EVP_des_ede; extern const EVP_CIPHER *EVP_des_ede(void); %rename(des_ede3_ecb) EVP_des_ede3; extern const EVP_CIPHER *EVP_des_ede3(void); %rename(des_cbc) EVP_des_cbc; extern const EVP_CIPHER *EVP_des_cbc(void); %rename(des_ede_cbc) EVP_des_ede_cbc; extern const EVP_CIPHER *EVP_des_ede_cbc(void); %rename(des_ede3_cbc) EVP_des_ede3_cbc; extern const EVP_CIPHER *EVP_des_ede3_cbc(void); %rename(des_cfb) EVP_des_cfb; extern const EVP_CIPHER *EVP_des_cfb(void); %rename(des_ede_cfb) EVP_des_ede_cfb; extern const EVP_CIPHER *EVP_des_ede_cfb(void); %rename(des_ede3_cfb) EVP_des_ede3_cfb; extern const EVP_CIPHER *EVP_des_ede3_cfb(void); %rename(des_ofb) EVP_des_ofb; extern const EVP_CIPHER *EVP_des_ofb(void); %rename(des_ede_ofb) EVP_des_ede_ofb; extern const EVP_CIPHER *EVP_des_ede_ofb(void); %rename(des_ede3_ofb) EVP_des_ede3_ofb; extern const EVP_CIPHER *EVP_des_ede3_ofb(void); %rename(bf_ecb) EVP_bf_ecb; extern const EVP_CIPHER *EVP_bf_ecb(void); %rename(bf_cbc) EVP_bf_cbc; extern const EVP_CIPHER *EVP_bf_cbc(void); %rename(bf_cfb) EVP_bf_cfb; extern const EVP_CIPHER *EVP_bf_cfb(void); %rename(bf_ofb) EVP_bf_ofb; extern const EVP_CIPHER *EVP_bf_ofb(void); /* %rename(idea_ecb) extern const EVP_CIPHER *EVP_idea_ecb(void); %rename(idea_cbc) extern const EVP_CIPHER *EVP_idea_cbc(void); %rename(idea_cfb) extern const EVP_CIPHER *EVP_idea_cfb(void); %rename(idea_ofb) extern const EVP_CIPHER *EVP_idea_ofb(void); */ %rename(cast5_ecb) EVP_cast5_ecb; extern const EVP_CIPHER *EVP_cast5_ecb(void); %rename(cast5_cbc) EVP_cast5_cbc; extern const EVP_CIPHER *EVP_cast5_cbc(void); %rename(cast5_cfb) EVP_cast5_cfb; extern const EVP_CIPHER *EVP_cast5_cfb(void); %rename(cast5_ofb) EVP_cast5_ofb; extern const EVP_CIPHER *EVP_cast5_ofb(void); /* %rename(rc5_ecb) extern const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); %rename(rc5_cbc) extern const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); %rename(rc5_cfb) extern const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void); %rename(rc5_ofb) extern const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); */ %rename(rc4) EVP_rc4; extern const EVP_CIPHER *EVP_rc4(void); %rename(rc2_40_cbc) EVP_rc2_40_cbc; extern const EVP_CIPHER *EVP_rc2_40_cbc(void); %rename(aes_128_ecb) EVP_aes_128_ecb; extern const EVP_CIPHER *EVP_aes_128_ecb(void); %rename(aes_128_cbc) EVP_aes_128_cbc; extern const EVP_CIPHER *EVP_aes_128_cbc(void); %rename(aes_128_cfb) EVP_aes_128_cfb; extern const EVP_CIPHER *EVP_aes_128_cfb(void); %rename(aes_128_ofb) EVP_aes_128_ofb; extern const EVP_CIPHER *EVP_aes_128_ofb(void); %rename(aes_192_ecb) EVP_aes_192_ecb; extern const EVP_CIPHER *EVP_aes_192_ecb(void); %rename(aes_192_cbc) EVP_aes_192_cbc; extern const EVP_CIPHER *EVP_aes_192_cbc(void); %rename(aes_192_cfb) EVP_aes_192_cfb; extern const EVP_CIPHER *EVP_aes_192_cfb(void); %rename(aes_192_ofb) EVP_aes_192_ofb; extern const EVP_CIPHER *EVP_aes_192_ofb(void); %rename(aes_256_ecb) EVP_aes_256_ecb; extern const EVP_CIPHER *EVP_aes_256_ecb(void); %rename(aes_256_cbc) EVP_aes_256_cbc; extern const EVP_CIPHER *EVP_aes_256_cbc(void); %rename(aes_256_cfb) EVP_aes_256_cfb; extern const EVP_CIPHER *EVP_aes_256_cfb(void); %rename(aes_256_ofb) EVP_aes_256_ofb; extern const EVP_CIPHER *EVP_aes_256_ofb(void); %rename(cipher_set_padding) EVP_CIPHER_CTX_set_padding; extern int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *, int); %rename(pkey_new) EVP_PKEY_new; extern EVP_PKEY *EVP_PKEY_new(void); %rename(pkey_free) EVP_PKEY_free; extern void EVP_PKEY_free(EVP_PKEY *); %rename(pkey_assign) EVP_PKEY_assign; extern int EVP_PKEY_assign(EVP_PKEY *, int, char *); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_EC) %rename(pkey_assign_ec) EVP_PKEY_assign_EC_KEY; extern int EVP_PKEY_assign_EC_KEY(EVP_PKEY *, EC_KEY *); #endif %rename(pkey_set1_rsa) EVP_PKEY_set1_RSA; extern int EVP_PKEY_set1_RSA(EVP_PKEY *, RSA *); %rename(pkey_get1_rsa) EVP_PKEY_get1_RSA; extern RSA* EVP_PKEY_get1_RSA(EVP_PKEY *); %rename(sign_init) EVP_SignInit; extern int EVP_SignInit(EVP_MD_CTX *, const EVP_MD *); %rename(verify_init) EVP_VerifyInit; extern int EVP_VerifyInit(EVP_MD_CTX *, const EVP_MD *); %rename(pkey_size) EVP_PKEY_size; extern int EVP_PKEY_size(EVP_PKEY *); %inline %{ #define PKCS5_SALT_LEN 8 static PyObject *_evp_err; void evp_init(PyObject *evp_err) { Py_INCREF(evp_err); _evp_err = evp_err; } PyObject *pkcs5_pbkdf2_hmac_sha1(PyObject *pass, PyObject *salt, int iter, int keylen) { unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char *saltbuf; char *passbuf; PyObject *ret; int passlen, saltlen; if (m2_PyObject_AsReadBufferInt(pass, (const void **)&passbuf, &passlen) == -1) return NULL; if (m2_PyObject_AsReadBufferInt(salt, (const void **)&saltbuf, &saltlen) == -1) return NULL; PKCS5_PBKDF2_HMAC_SHA1(passbuf, passlen, saltbuf, saltlen, iter, keylen, key); ret = PyString_FromStringAndSize((char*)key, keylen); OPENSSL_cleanse(key, keylen); return ret; } EVP_MD_CTX *md_ctx_new(void) { EVP_MD_CTX *ctx; if (!(ctx = EVP_MD_CTX_create())) { PyErr_SetString(PyExc_MemoryError, "md_ctx_new"); } return ctx; } void md_ctx_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); } int digest_update(EVP_MD_CTX *ctx, PyObject *blob) { const void *buf; Py_ssize_t len; if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) return -1; return EVP_DigestUpdate(ctx, buf, len); } PyObject *digest_final(EVP_MD_CTX *ctx) { void *blob; int blen; PyObject *ret; if (!(blob = PyMem_Malloc(ctx->digest->md_size))) { PyErr_SetString(PyExc_MemoryError, "digest_final"); return NULL; } if (!EVP_DigestFinal(ctx, blob, (unsigned int *)&blen)) { PyMem_Free(blob); PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize(blob, blen); PyMem_Free(blob); return ret; } HMAC_CTX *hmac_ctx_new(void) { HMAC_CTX *ctx; if (!(ctx = (HMAC_CTX *)PyMem_Malloc(sizeof(HMAC_CTX)))) { PyErr_SetString(PyExc_MemoryError, "hmac_ctx_new"); return NULL; } HMAC_CTX_init(ctx); return ctx; } void hmac_ctx_free(HMAC_CTX *ctx) { HMAC_CTX_cleanup(ctx); PyMem_Free((void *)ctx); } PyObject *hmac_init(HMAC_CTX *ctx, PyObject *key, const EVP_MD *md) { const void *kbuf; int klen; if (m2_PyObject_AsReadBufferInt(key, &kbuf, &klen) == -1) return NULL; if (!HMAC_Init(ctx, kbuf, klen, md)) { PyErr_SetString(_evp_err, "HMAC_Init failed"); return NULL; } Py_INCREF(Py_None); return Py_None; } PyObject *hmac_update(HMAC_CTX *ctx, PyObject *blob) { const void *buf; Py_ssize_t len; if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) return NULL; if (!HMAC_Update(ctx, buf, len)) { PyErr_SetString(_evp_err, "HMAC_Update failed"); return NULL; } Py_INCREF(Py_None); return Py_None; } PyObject *hmac_final(HMAC_CTX *ctx) { void *blob; int blen; PyObject *ret; if (!(blob = PyMem_Malloc(ctx->md->md_size))) { PyErr_SetString(PyExc_MemoryError, "hmac_final"); return NULL; } if (!HMAC_Final(ctx, blob, (unsigned int *)&blen)) { PyErr_SetString(_evp_err, "HMAC_Final failed"); return NULL; } ret = PyString_FromStringAndSize(blob, blen); PyMem_Free(blob); return ret; } PyObject *hmac(PyObject *key, PyObject *data, const EVP_MD *md) { const void *kbuf, *dbuf; void *blob; int klen; unsigned int blen; Py_ssize_t dlen; PyObject *ret; if ((m2_PyObject_AsReadBufferInt(key, &kbuf, &klen) == -1) || (PyObject_AsReadBuffer(data, &dbuf, &dlen) == -1)) return NULL; if (!(blob = PyMem_Malloc(EVP_MAX_MD_SIZE))) { PyErr_SetString(PyExc_MemoryError, "hmac"); return NULL; } HMAC(md, kbuf, klen, dbuf, dlen, blob, &blen); blob = PyMem_Realloc(blob, blen); ret = PyString_FromStringAndSize(blob, blen); PyMem_Free(blob); return ret; } EVP_CIPHER_CTX *cipher_ctx_new(void) { EVP_CIPHER_CTX *ctx; if (!(ctx = (EVP_CIPHER_CTX *)PyMem_Malloc(sizeof(EVP_CIPHER_CTX)))) { PyErr_SetString(PyExc_MemoryError, "cipher_ctx_new"); return NULL; } EVP_CIPHER_CTX_init(ctx); return ctx; } void cipher_ctx_free(EVP_CIPHER_CTX *ctx) { EVP_CIPHER_CTX_cleanup(ctx); PyMem_Free((void *)ctx); } PyObject *bytes_to_key(const EVP_CIPHER *cipher, EVP_MD *md, PyObject *data, PyObject *salt, PyObject *iv, /* Not used */ int iter) { unsigned char key[EVP_MAX_KEY_LENGTH]; const void *dbuf, *sbuf; int dlen, klen; Py_ssize_t slen; PyObject *ret; if ((m2_PyObject_AsReadBufferInt(data, &dbuf, &dlen) == -1) || (PyObject_AsReadBuffer(salt, &sbuf, &slen) == -1)) return NULL; assert((slen == 8) || (slen == 0)); klen = EVP_BytesToKey(cipher, md, (unsigned char *)sbuf, (unsigned char *)dbuf, dlen, iter, key, NULL); /* Since we are not returning IV no need to derive it */ ret = PyString_FromStringAndSize((char*)key, klen); return ret; } PyObject *cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, PyObject *key, PyObject *iv, int mode) { const void *kbuf, *ibuf; Py_ssize_t klen, ilen; if ((PyObject_AsReadBuffer(key, &kbuf, &klen) == -1) || (PyObject_AsReadBuffer(iv, &ibuf, &ilen) == -1)) return NULL; if (!EVP_CipherInit(ctx, cipher, (unsigned char *)kbuf, (unsigned char *)ibuf, mode)) { PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } Py_INCREF(Py_None); return Py_None; } PyObject *cipher_update(EVP_CIPHER_CTX *ctx, PyObject *blob) { const void *buf; int len, olen; void *obuf; PyObject *ret; if (m2_PyObject_AsReadBufferInt(blob, &buf, &len) == -1) return NULL; if (!(obuf = PyMem_Malloc(len + EVP_CIPHER_CTX_block_size(ctx) - 1))) { PyErr_SetString(PyExc_MemoryError, "cipher_update"); return NULL; } if (!EVP_CipherUpdate(ctx, obuf, &olen, (unsigned char *)buf, len)) { PyMem_Free(obuf); PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize(obuf, olen); PyMem_Free(obuf); return ret; } PyObject *cipher_final(EVP_CIPHER_CTX *ctx) { void *obuf; int olen; PyObject *ret; if (!(obuf = PyMem_Malloc(ctx->cipher->block_size))) { PyErr_SetString(PyExc_MemoryError, "cipher_final"); return NULL; } if (!EVP_CipherFinal(ctx, (unsigned char *)obuf, &olen)) { PyMem_Free(obuf); PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize(obuf, olen); PyMem_Free(obuf); return ret; } PyObject *sign_update(EVP_MD_CTX *ctx, PyObject *blob) { const void *buf; Py_ssize_t len; if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) return NULL; if (!EVP_SignUpdate(ctx, buf, len)) { PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } Py_INCREF(Py_None); return Py_None; } PyObject *sign_final(EVP_MD_CTX *ctx, EVP_PKEY *pkey) { PyObject *ret; unsigned char *sigbuf; unsigned int siglen = EVP_PKEY_size(pkey); sigbuf = (unsigned char*)OPENSSL_malloc(siglen); if (!sigbuf) { PyErr_SetString(PyExc_MemoryError, "sign_final"); return NULL; } if (!EVP_SignFinal(ctx, sigbuf, &siglen, pkey)) { OPENSSL_cleanse(sigbuf, siglen); OPENSSL_free(sigbuf); PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((char*)sigbuf, siglen); OPENSSL_cleanse(sigbuf, siglen); OPENSSL_free(sigbuf); return ret; } int verify_update(EVP_MD_CTX *ctx, PyObject *blob) { const void *buf; Py_ssize_t len; if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) return -1; return EVP_VerifyUpdate(ctx, buf, len); } int verify_final(EVP_MD_CTX *ctx, PyObject *blob, EVP_PKEY *pkey) { unsigned char *kbuf; int len; if (m2_PyObject_AsReadBufferInt(blob, (const void **)&kbuf, &len) == -1) return -1; return EVP_VerifyFinal(ctx, kbuf, len, pkey); } %} %inline %{ int pkey_write_pem_no_cipher(EVP_PKEY *pkey, BIO *f, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_PKCS8PrivateKey(f, pkey, NULL, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ int pkey_write_pem(EVP_PKEY *pkey, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_PKCS8PrivateKey(f, pkey, cipher, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ EVP_PKEY *pkey_read_pem(BIO *f, PyObject *pyfunc) { EVP_PKEY *pk; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS pk = PEM_read_bio_PrivateKey(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return pk; } int pkey_assign_rsa(EVP_PKEY *pkey, RSA *rsa) { return EVP_PKEY_assign_RSA(pkey, rsa); } PyObject *pkey_as_der(EVP_PKEY *pkey) { unsigned char * pp = NULL; int len; PyObject * der; len = i2d_PUBKEY(pkey, &pp); if (len < 0){ PyErr_SetString(PyExc_ValueError, "EVP_PKEY as DER failed"); return NULL; } der = PyString_FromStringAndSize((char*)pp, len); OPENSSL_free(pp); return der; } PyObject *pkey_get_modulus(EVP_PKEY *pkey) { RSA *rsa; DSA *dsa; BIO *bio; BUF_MEM *bptr; PyObject *ret; switch (pkey->type) { case EVP_PKEY_RSA: rsa = EVP_PKEY_get1_RSA(pkey); bio = BIO_new(BIO_s_mem()); if (!bio) { RSA_free(rsa); PyErr_SetString(PyExc_MemoryError, "pkey_get_modulus"); return NULL; } if (!BN_print(bio, rsa->n)) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); BIO_free(bio); RSA_free(rsa); return NULL; } BIO_get_mem_ptr(bio, &bptr); ret = PyString_FromStringAndSize(bptr->data, bptr->length); BIO_set_close(bio, BIO_CLOSE); BIO_free(bio); RSA_free(rsa); break; case EVP_PKEY_DSA: dsa = EVP_PKEY_get1_DSA(pkey); bio = BIO_new(BIO_s_mem()); if (!bio) { DSA_free(dsa); PyErr_SetString(PyExc_MemoryError, "pkey_get_modulus"); return NULL; } if (!BN_print(bio, dsa->pub_key)) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); BIO_free(bio); DSA_free(dsa); return NULL; } BIO_get_mem_ptr(bio, &bptr); ret = PyString_FromStringAndSize(bptr->data, bptr->length); BIO_set_close(bio, BIO_CLOSE); BIO_free(bio); DSA_free(dsa); break; default: PyErr_SetString(PyExc_ValueError, "unsupported key type"); return NULL; } return ret; } %} M2Crypto-0.22.6rc4/SWIG/_lib.h0000664000175000017500000000221212611255457015751 0ustar matejmatej00000000000000/* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) typedef int Py_ssize_t; #define PY_SSIZE_T_MAX INT_MAX #define PY_SSIZE_T_MIN INT_MIN #endif #if PY_VERSION_HEX < 0x02060000 struct Py_buffer /* Only a subset */ { void *buf; Py_ssize_t len; }; #define PyBUF_CONTIG_RO 0 #endif /* PY_VERSION_HEX < 0x02060000 */ typedef struct _blob { unsigned char *data; int len; } Blob; Blob *blob_new(int len, const char *errmsg); Blob *blob_copy(Blob *from, const char *errmsg); void blob_free(Blob *blob); static int m2_PyObject_AsReadBufferInt(PyObject *obj, const void **buffer, int *buffer_len); static int m2_PyString_AsStringAndSizeInt(PyObject *obj, char **s, int *len); /* Always use these two together, to correctly handle non-memoryview objects. */ static int m2_PyObject_GetBufferInt(PyObject *obj, Py_buffer *view, int flags); static void m2_PyBuffer_Release(PyObject *obj, Py_buffer *view); void gen_callback(int p, int n, void *arg); int passphrase_callback(char *buf, int num, int v, void *userdata); void lib_init(void); M2Crypto-0.22.6rc4/SWIG/_lib.i0000664000175000017500000003446212611255457015766 0ustar matejmatej00000000000000/* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #include #include #include #include #include #include /* Blob interface. Deprecated. */ Blob *blob_new(int len, const char *errmsg) { Blob *blob; if (!(blob=(Blob *)PyMem_Malloc(sizeof(Blob)))){ PyErr_SetString(PyExc_MemoryError, errmsg); return NULL; } if (!(blob->data=(unsigned char *)PyMem_Malloc(len))) { PyMem_Free(blob); PyErr_SetString(PyExc_MemoryError, errmsg); return NULL; } blob->len=len; return blob; } Blob *blob_copy(Blob *from, const char *errmsg) { Blob *blob=blob_new(from->len, errmsg); if (!blob) { PyErr_SetString(PyExc_MemoryError, errmsg); return NULL; } memcpy(blob->data, from->data, from->len); return blob; } void blob_free(Blob *blob) { PyMem_Free(blob->data); PyMem_Free(blob); } /* Python helpers. */ %} %ignore PyObject_CheckBuffer; %ignore PyObject_GetBuffer; %ignore PyBuffer_Release; %ignore m2_PyObject_AsReadBufferInt; %ignore m2_PyObject_GetBufferInt; %ignore m2_PyBuffer_Release; %ignore m2_PyString_AsStringAndSizeInt; %{ #if PY_VERSION_HEX < 0x02060000 static int PyObject_CheckBuffer(PyObject *obj) { (void)obj; return 0; } static int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { (void)obj; (void)view; (void)flags; return -1; } static void PyBuffer_Release(Py_buffer *view) { (void)view; } #endif /* PY_VERSION_HEX < 0x02060000 */ static int m2_PyObject_AsReadBufferInt(PyObject *obj, const void **buffer, int *buffer_len) { int ret; Py_ssize_t len; ret = PyObject_AsReadBuffer(obj, buffer, &len); if (ret) return ret; if (len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); return -1; } *buffer_len = len; return 0; } static int m2_PyObject_GetBufferInt(PyObject *obj, Py_buffer *view, int flags) { int ret; if (PyObject_CheckBuffer(obj)) ret = PyObject_GetBuffer(obj, view, flags); else { const void *buf; ret = PyObject_AsReadBuffer(obj, &buf, &view->len); if (ret == 0) view->buf = (void *)buf; } if (ret) return ret; if (view->len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); m2_PyBuffer_Release(obj, view); return -1; } return 0; } static void m2_PyBuffer_Release(PyObject *obj, Py_buffer *view) { if (PyObject_CheckBuffer(obj)) PyBuffer_Release(view); /* else do nothing, view->buf comes from PyObject_AsReadBuffer */ } static int m2_PyString_AsStringAndSizeInt(PyObject *obj, char **s, int *len) { int ret; Py_ssize_t len2; ret = PyString_AsStringAndSize(obj, s, &len2); if (ret) return ret; if (len2 > INT_MAX) { PyErr_SetString(PyExc_ValueError, "string too large"); return -1; } *len = len2; return 0; } /* C callbacks invoked by OpenSSL; these in turn call back into Python. */ int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { PyObject *argv, *ret; PyObject *_x509_store_ctx_swigptr=0, *_x509_store_ctx_obj=0, *_x509_store_ctx_inst=0, *_klass=0; PyObject *_x509=0, *_ssl_ctx=0; SSL *ssl; SSL_CTX *ssl_ctx; X509 *x509; int errnum, errdepth; int cret; int new_style_callback = 0, warning_raised_exception=0; PyGILState_STATE gilstate; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); gilstate = PyGILState_Ensure(); if (PyMethod_Check(ssl_verify_cb_func)) { PyObject *func; PyCodeObject *code; func = PyMethod_Function(ssl_verify_cb_func); code = (PyCodeObject *) PyFunction_GetCode(func); if (code && code->co_argcount == 3) { /* XXX Python internals */ new_style_callback = 1; } } else if (PyFunction_Check(ssl_verify_cb_func)) { PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(ssl_verify_cb_func); if (code && code->co_argcount == 2) { /* XXX Python internals */ new_style_callback = 1; } } else { /* XXX There are lots of other callable types, but we will assume * XXX that any other type of callable uses the new style callback, * XXX although this is not entirely safe assumption. */ new_style_callback = 1; } if (new_style_callback) { PyObject *x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); _klass = PyObject_GetAttrString(x509mod, "X509_Store_Context"); _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0); _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0); _x509_store_ctx_inst = PyInstance_New(_klass, _x509_store_ctx_obj, NULL); argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst); } else { if (PyErr_Warn(PyExc_DeprecationWarning, "Old style callback, use cb_func(ok, store) instead")) { warning_raised_exception = 1; } x509 = X509_STORE_CTX_get_current_cert(ctx); errnum = X509_STORE_CTX_get_error(ctx); errdepth = X509_STORE_CTX_get_error_depth(ctx); ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); ssl_ctx = SSL_get_SSL_CTX(ssl); _x509 = SWIG_NewPointerObj((void *)x509, SWIGTYPE_p_X509, 0); _ssl_ctx = SWIG_NewPointerObj((void *)ssl_ctx, SWIGTYPE_p_SSL_CTX, 0); argv = Py_BuildValue("(OOiii)", _ssl_ctx, _x509, errnum, errdepth, ok); } if (!warning_raised_exception) { ret = PyEval_CallObject(ssl_verify_cb_func, argv); } else { ret = 0; } if (!ret) { /* Got an exception in PyEval_CallObject(), let's fail verification * to be safe. */ cret = 0; } else { cret = (int)PyInt_AsLong(ret); } Py_XDECREF(ret); Py_XDECREF(argv); if (new_style_callback) { Py_XDECREF(_x509_store_ctx_inst); Py_XDECREF(_x509_store_ctx_obj); Py_XDECREF(_x509_store_ctx_swigptr); Py_XDECREF(_klass); } else { Py_XDECREF(_x509); Py_XDECREF(_ssl_ctx); } PyGILState_Release(gilstate); return cret; } void ssl_info_callback(const SSL *s, int where, int ret) { PyObject *argv, *retval, *_SSL; PyGILState_STATE gilstate; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); _SSL = SWIG_NewPointerObj((void *)s, SWIGTYPE_p_SSL, 0); argv = Py_BuildValue("(iiO)", where, ret, _SSL); retval = PyEval_CallObject(ssl_info_cb_func, argv); Py_XDECREF(retval); Py_XDECREF(argv); Py_XDECREF(_SSL); PyGILState_Release(gilstate); } DH *ssl_set_tmp_dh_callback(SSL *ssl, int is_export, int keylength) { PyObject *argv, *ret, *_ssl; DH *dh; PyGILState_STATE gilstate; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); _ssl = SWIG_NewPointerObj((void *)ssl, SWIGTYPE_p_SSL, 0); argv = Py_BuildValue("(Oii)", _ssl, is_export, keylength); ret = PyEval_CallObject(ssl_set_tmp_dh_cb_func, argv); if ((SWIG_ConvertPtr(ret, (void **)&dh, SWIGTYPE_p_DH, SWIG_POINTER_EXCEPTION | 0)) == -1) dh = NULL; Py_XDECREF(ret); Py_XDECREF(argv); Py_XDECREF(_ssl); PyGILState_Release(gilstate); return dh; } RSA *ssl_set_tmp_rsa_callback(SSL *ssl, int is_export, int keylength) { PyObject *argv, *ret, *_ssl; RSA *rsa; PyGILState_STATE gilstate; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ gilstate = PyGILState_Ensure(); _ssl = SWIG_NewPointerObj((void *)ssl, SWIGTYPE_p_SSL, 0); argv = Py_BuildValue("(Oii)", _ssl, is_export, keylength); ret = PyEval_CallObject(ssl_set_tmp_rsa_cb_func, argv); if ((SWIG_ConvertPtr(ret, (void **)&rsa, SWIGTYPE_p_RSA, SWIG_POINTER_EXCEPTION | 0)) == -1) rsa = NULL; Py_XDECREF(ret); Py_XDECREF(argv); Py_XDECREF(_ssl); PyGILState_Release(gilstate); return rsa; } void gen_callback(int p, int n, void *arg) { PyObject *argv, *ret, *cbfunc; PyGILState_STATE gilstate; gilstate = PyGILState_Ensure(); cbfunc = (PyObject *)arg; argv = Py_BuildValue("(ii)", p, n); ret = PyEval_CallObject(cbfunc, argv); Py_DECREF(argv); Py_XDECREF(ret); PyGILState_Release(gilstate); } int passphrase_callback(char *buf, int num, int v, void *arg) { int i; Py_ssize_t len; char *str; PyObject *argv, *ret, *cbfunc; PyGILState_STATE gilstate; gilstate = PyGILState_Ensure(); cbfunc = (PyObject *)arg; argv = Py_BuildValue("(i)", v); ret = PyEval_CallObject(cbfunc, argv); Py_DECREF(argv); if (ret == NULL) { PyGILState_Release(gilstate); return -1; } if (!PyString_Check(ret)) { Py_DECREF(ret); PyGILState_Release(gilstate); return -1; } if ((len = PyString_Size(ret)) > num) len = num; str = PyString_AsString(ret); for (i = 0; i < len; i++) buf[i] = str[i]; Py_DECREF(ret); PyGILState_Release(gilstate); return len; } %} %inline %{ void lib_init() { SSLeay_add_all_algorithms(); ERR_load_ERR_strings(); } /* Bignum routines that aren't not numerous enough to warrant a separate file. */ PyObject *bn_to_mpi(BIGNUM *bn) { int len; unsigned char *mpi; PyObject *pyo; len = BN_bn2mpi(bn, NULL); if (!(mpi=(unsigned char *)PyMem_Malloc(len))) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); return NULL; } len=BN_bn2mpi(bn, mpi); pyo=PyString_FromStringAndSize((const char *)mpi, len); PyMem_Free(mpi); return pyo; } BIGNUM *mpi_to_bn(PyObject *value) { const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; return BN_mpi2bn(vbuf, vlen, NULL); } PyObject *bn_to_bin(BIGNUM *bn) { int len; unsigned char *bin; PyObject *pyo; len = BN_num_bytes(bn); if (!(bin=(unsigned char *)PyMem_Malloc(len))) { PyErr_SetString(PyExc_MemoryError, "bn_to_bin"); return NULL; } BN_bn2bin(bn, bin); pyo=PyString_FromStringAndSize((const char *)bin, len); PyMem_Free(bin); return pyo; } BIGNUM *bin_to_bn(PyObject *value) { const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; return BN_bin2bn(vbuf, vlen, NULL); } PyObject *bn_to_hex(BIGNUM *bn) { char *hex; PyObject *pyo; Py_ssize_t len; hex = BN_bn2hex(bn); if (!hex) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); OPENSSL_free(hex); return NULL; } len = strlen(hex); pyo=PyString_FromStringAndSize(hex, len); OPENSSL_free(hex); return pyo; } BIGNUM *hex_to_bn(PyObject *value) { const void *vbuf; Py_ssize_t vlen; BIGNUM *bn; if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) return NULL; if ((bn=BN_new())==NULL) { PyErr_SetString(PyExc_MemoryError, "hex_to_bn"); return NULL; } if (BN_hex2bn(&bn, (const char *)vbuf) <= 0) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); BN_free(bn); return NULL; } return bn; } BIGNUM *dec_to_bn(PyObject *value) { const void *vbuf; Py_ssize_t vlen; BIGNUM *bn; if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) return NULL; if ((bn=BN_new())==NULL) { PyErr_SetString(PyExc_MemoryError, "dec_to_bn"); return NULL; } if ((BN_dec2bn(&bn, (const char *)vbuf) <= 0)) { PyErr_SetString(PyExc_RuntimeError, ERR_error_string(ERR_get_error(), NULL)); BN_free(bn); return NULL; } return bn; } %} /* Various useful typemaps. */ %typemap(in) Blob * { Py_ssize_t len; if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyString"); return NULL; } len=PyString_Size($input); if (len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); return -1; } $1=(Blob *)PyMem_Malloc(sizeof(Blob)); if (!$1) { PyErr_SetString(PyExc_MemoryError, "malloc Blob"); return NULL; } $1->data=(unsigned char *)PyString_AsString($input); $1->len=len; } %typemap(out) Blob * { if ($1==NULL) { Py_INCREF(Py_None); $result=Py_None; } else { $result=PyString_FromStringAndSize((const char *)$1->data, $1->len); PyMem_Free($1->data); PyMem_Free($1); } } %typemap(in) FILE * { if (!PyFile_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyFile"); return NULL; } $1=PyFile_AsFile($input); } %typemap(in) PyObject *pyfunc { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyCallable"); return NULL; } $1=$input; } %typemap(in) PyObject *pyblob { if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "expected PyString"); return NULL; } $1=$input; } %typemap(in) PyObject * { $1=$input; } %typemap(out) PyObject * { $result=$1; } %typemap(out) int { $result=PyInt_FromLong($1); if (PyErr_Occurred()) SWIG_fail; } /* Pointer checks. */ %apply Pointer NONNULL { Blob * }; /* A bunch of "straight-thru" functions. */ %rename(err_print_errors_fp) ERR_print_errors_fp; %threadallow ERR_print_errors_fp; extern void ERR_print_errors_fp(FILE *); %rename(err_print_errors) ERR_print_errors; %threadallow ERR_print_errors; extern void ERR_print_errors(BIO *); %rename(err_get_error) ERR_get_error; extern unsigned long ERR_get_error(void); %rename(err_peek_error) ERR_peek_error; extern unsigned long ERR_peek_error(void); %rename(err_lib_error_string) ERR_lib_error_string; extern const char *ERR_lib_error_string(unsigned long); %rename(err_func_error_string) ERR_func_error_string; extern const char *ERR_func_error_string(unsigned long); %rename(err_reason_error_string) ERR_reason_error_string; extern const char *ERR_reason_error_string(unsigned long); M2Crypto-0.22.6rc4/SWIG/_m2crypto.def0000664000175000017500000000003012613361405017256 0ustar matejmatej00000000000000EXPORTS init__m2crypto M2Crypto-0.22.6rc4/SWIG/_m2crypto.i0000664000175000017500000000352612613361405016765 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved. * * Portions created by Open Source Applications Foundation (OSAF) are * Copyright (C) 2004-2006 OSAF. All Rights Reserved. * * Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. * */ %module(threads=1) _m2crypto /* We really don't need threadblock (PyGILState_Ensure() etc.) anywhere. Disable threadallow as well, only enable it for operations likely to block. */ %nothreadblock; %nothreadallow; %{ #include #include #include <_lib.h> #include "compile.h" static PyObject *ssl_verify_cb_func; static PyObject *ssl_info_cb_func; static PyObject *ssl_set_tmp_dh_cb_func; static PyObject *ssl_set_tmp_rsa_cb_func; %} %include #if OPENSSL_VERSION_NUMBER >= 0x0090707fL #define CONST const #else #define CONST #endif #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #define CONST098 const #else #define CONST098 #endif /* Bring in STACK_OF macro definition */ %include /* Bring in LHASH_OF macro definition */ /* XXX Can't include lhash.h where LHASH_OF is defined, because it includes XXX stdio.h etc. which we fail to include. So we have to (re)define XXX LHASH_OF here instead. %include */ #if OPENSSL_VERSION_NUMBER >= 0x10000000L #define LHASH_OF(type) struct lhash_st_##type #endif %include constraints.i %include _threads.i %include _lib.i %include _bio.i %include _bn.i %include _rand.i %include _evp.i %include _aes.i %include _rc4.i %include _dh.i %include _rsa.i %include _dsa.i %include _ssl.i %include _x509.i %include _asn1.i %include _pkcs7.i %include _util.i %include _ec.i %include _engine.i %include _objects.i #ifdef SWIG_VERSION %constant int encrypt = 1; %constant int decrypt = 0; #endif M2Crypto-0.22.6rc4/SWIG/_objects.i0000664000175000017500000000551012607370517016641 0ustar matejmatej00000000000000/* * -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: syntax=c sts=4 sw=4 * * ASN1_OBJECT manipulation functions from OBJ_obj2txt(3SSL). * * Pavel Shramov * IMEC MSU */ %{ #include %} %apply Pointer NONNULL { ASN1_OBJECT * }; %apply Pointer NONNULL { const char * }; %rename(obj_nid2obj) OBJ_nid2obj; extern ASN1_OBJECT * OBJ_nid2obj(int n); %rename(obj_nid2ln) OBJ_nid2ln; extern const char * OBJ_nid2ln(int n); %rename(obj_nid2sn) OBJ_nid2sn; extern const char * OBJ_nid2sn(int n); %rename(obj_obj2nid) OBJ_obj2nid; extern int OBJ_obj2nid(const ASN1_OBJECT *o); %rename(obj_ln2nid) OBJ_ln2nid; extern int OBJ_ln2nid(const char *ln); %rename(obj_sn2nid) OBJ_sn2nid; extern int OBJ_sn2nid(const char *sn); %rename(obj_txt2nid) OBJ_txt2nid; extern int OBJ_txt2nid(const char *s); %rename(obj_txt2obj) OBJ_txt2obj; extern ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name); %rename(_obj_obj2txt) OBJ_obj2txt; extern int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int); %inline %{ /* From the manpage for OBJ_obt2txt (): BUGS OBJ_obj2txt() is awkward and messy to use: it doesn’t follow the convention of other OpenSSL functions where the buffer can be set to NULL to determine the amount of data that should be written. Instead buf must point to a valid buffer and buf_len should be set to a positive value. A buffer length of 80 should be more than enough to handle any OID encountered in practice. The first call to OBJ_obj2txt () therefore passes a non-NULL dummy buffer. This wart is reportedly removed in OpenSSL 0.9.8b, although the manpage has not been updated. OBJ_obj2txt always prints \0 at the end. But the return value is the number of "good" bytes written. So memory is allocated for len + 1 bytes but only len bytes are marshalled to python. */ PyObject *obj_obj2txt(const ASN1_OBJECT *obj, int no_name) { int len; PyObject *ret; char *buf; char dummy[1]; len = OBJ_obj2txt(dummy, 1, obj, no_name); if (len < 0) { PyErr_SetString(PyExc_RuntimeError, ERR_reason_error_string(ERR_get_error())); return NULL; } else if (len == 0) { /* XXX: For OpenSSL prior to 0.9.8b. Changes between 0.9.8a and 0.9.8b [04 May 2006] ... *) Several fixes and enhancements to the OID generation code. The old code sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't handle numbers larger than ULONG_MAX, truncated printing and had a non standard OBJ_obj2txt() behaviour. [Steve Henson] */ len = 80; } buf = PyMem_Malloc(len + 1); len = OBJ_obj2txt(buf, len + 1, obj, no_name); ret = PyString_FromStringAndSize(buf, len); PyMem_Free(buf); return ret; } %} M2Crypto-0.22.6rc4/SWIG/_pkcs7.i0000664000175000017500000001472012611255457016242 0ustar matejmatej00000000000000/* Copyright (c) 2000 Ng Pheng Siong. All rights reserved. * Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. */ /* $Id$ */ %{ #include #include #include #include %} %apply Pointer NONNULL { BIO * }; %apply Pointer NONNULL { EVP_CIPHER * }; %apply Pointer NONNULL { EVP_PKEY * }; %apply Pointer NONNULL { PKCS7 * }; %apply Pointer NONNULL { STACK_OF(X509) * }; %apply Pointer NONNULL { X509 * }; %rename(pkcs7_new) PKCS7_new; extern PKCS7 *PKCS7_new(void); %rename(pkcs7_free) PKCS7_free; extern void PKCS7_free(PKCS7 *); %rename(pkcs7_add_certificate) PKCS7_add_certificate; extern void PKCS7_add_certificate(PKCS7 *, X509 *); /* S/MIME operation */ %constant int PKCS7_TEXT = 0x1; %constant int PKCS7_NOCERTS = 0x2; %constant int PKCS7_NOSIGS = 0x4; %constant int PKCS7_NOCHAIN = 0x8; %constant int PKCS7_NOINTERN = 0x10; %constant int PKCS7_NOVERIFY = 0x20; %constant int PKCS7_DETACHED = 0x40; %constant int PKCS7_BINARY = 0x80; %constant int PKCS7_NOATTR = 0x100; %constant int PKCS7_SIGNED = NID_pkcs7_signed; %constant int PKCS7_ENVELOPED = NID_pkcs7_enveloped; %constant int PKCS7_SIGNED_ENVELOPED = NID_pkcs7_signedAndEnveloped; %constant int PKCS7_DATA = NID_pkcs7_data; %inline %{ static PyObject *_pkcs7_err, *_smime_err; void pkcs7_init(PyObject *pkcs7_err) { Py_INCREF(pkcs7_err); _pkcs7_err = pkcs7_err; } void smime_init(PyObject *smime_err) { Py_INCREF(smime_err); _smime_err = smime_err; } %} %threadallow pkcs7_encrypt; %inline %{ PKCS7 *pkcs7_encrypt(STACK_OF(X509) *stack, BIO *bio, EVP_CIPHER *cipher, int flags) { return PKCS7_encrypt(stack, bio, cipher, flags); } PyObject *pkcs7_decrypt(PKCS7 *pkcs7, EVP_PKEY *pkey, X509 *cert, int flags) { int outlen; char *outbuf; BIO *bio; PyObject *ret; if (!(bio=BIO_new(BIO_s_mem()))) { PyErr_SetString(PyExc_MemoryError, "pkcs7_decrypt"); return NULL; } if (!PKCS7_decrypt(pkcs7, pkey, cert, bio, flags)) { PyErr_SetString(_pkcs7_err, ERR_reason_error_string(ERR_get_error())); BIO_free(bio); return NULL; } outlen = BIO_ctrl_pending(bio); if (!(outbuf=(char *)PyMem_Malloc(outlen))) { PyErr_SetString(PyExc_MemoryError, "pkcs7_decrypt"); BIO_free(bio); return NULL; } BIO_read(bio, outbuf, outlen); ret = PyString_FromStringAndSize(outbuf, outlen); BIO_free(bio); PyMem_Free(outbuf); return ret; } %} %threadallow pkcs7_sign0; %inline %{ PKCS7 *pkcs7_sign0(X509 *x509, EVP_PKEY *pkey, BIO *bio, int flags) { return PKCS7_sign(x509, pkey, NULL, bio, flags); } %} %threadallow pkcs7_sign1; %inline %{ PKCS7 *pkcs7_sign1(X509 *x509, EVP_PKEY *pkey, STACK_OF(X509) *stack, BIO *bio, int flags) { return PKCS7_sign(x509, pkey, stack, bio, flags); } %} %inline %{ PyObject *pkcs7_verify1(PKCS7 *pkcs7, STACK_OF(X509) *stack, X509_STORE *store, BIO *data, int flags) { int res, outlen; char *outbuf; BIO *bio; PyObject *ret; if (!(bio=BIO_new(BIO_s_mem()))) { PyErr_SetString(PyExc_MemoryError, "pkcs7_verify1"); return NULL; } Py_BEGIN_ALLOW_THREADS res = PKCS7_verify(pkcs7, stack, store, data, bio, flags); Py_END_ALLOW_THREADS if (!res) { PyErr_SetString(_pkcs7_err, ERR_reason_error_string(ERR_get_error())); BIO_free(bio); return NULL; } outlen = BIO_ctrl_pending(bio); if (!(outbuf=(char *)PyMem_Malloc(outlen))) { PyErr_SetString(PyExc_MemoryError, "pkcs7_verify1"); BIO_free(bio); return NULL; } BIO_read(bio, outbuf, outlen); ret = PyString_FromStringAndSize(outbuf, outlen); BIO_free(bio); PyMem_Free(outbuf); return ret; } PyObject *pkcs7_verify0(PKCS7 *pkcs7, STACK_OF(X509) *stack, X509_STORE *store, int flags) { return pkcs7_verify1(pkcs7, stack, store, NULL, flags); } %} %threadallow smime_write_pkcs7_multi; %inline %{ int smime_write_pkcs7_multi(BIO *bio, PKCS7 *pkcs7, BIO *data, int flags) { return SMIME_write_PKCS7(bio, pkcs7, data, flags | PKCS7_DETACHED); } %} %threadallow smime_write_pkcs7; %inline %{ int smime_write_pkcs7(BIO *bio, PKCS7 *pkcs7, int flags) { return SMIME_write_PKCS7(bio, pkcs7, NULL, flags); } PyObject *smime_read_pkcs7(BIO *bio) { BIO *bcont = NULL; PKCS7 *p7; PyObject *tuple, *_p7, *_BIO; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ if (BIO_method_type(bio) == BIO_TYPE_MEM) { /* OpenSSL FAQ explains that this is needed for mem BIO to return EOF, * like file BIO does. Might need to do this for more mem BIOs but * not sure if that is safe, so starting with just this single place. */ BIO_set_mem_eof_return(bio, 0); } Py_BEGIN_ALLOW_THREADS p7=SMIME_read_PKCS7(bio, &bcont); Py_END_ALLOW_THREADS if (!p7) { PyErr_SetString(_smime_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(tuple=PyTuple_New(2))) { PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails"); return NULL; } _p7 = SWIG_NewPointerObj((void *)p7, SWIGTYPE_p_PKCS7, 0); PyTuple_SET_ITEM(tuple, 0, _p7); if (!bcont) { Py_INCREF(Py_None); PyTuple_SET_ITEM(tuple, 1, Py_None); } else { _BIO = SWIG_NewPointerObj((void *)bcont, SWIGTYPE_p_BIO, 0); PyTuple_SET_ITEM(tuple, 1, _BIO); } return tuple; } %} %threadallow pkcs7_read_bio; %inline %{ PKCS7 *pkcs7_read_bio(BIO *bio) { return PEM_read_bio_PKCS7(bio, NULL, NULL, NULL); } %} %threadallow pkcs7_read_bio_der; %inline %{ PKCS7 *pkcs7_read_bio_der(BIO *bio) { return d2i_PKCS7_bio(bio, NULL); } %} %threadallow pkcs7_write_bio; %inline %{ int pkcs7_write_bio(PKCS7 *pkcs7, BIO* bio) { return PEM_write_bio_PKCS7(bio, pkcs7); } %} %threadallow pkcs7_write_bio_der; %inline %{ int pkcs7_write_bio_der(PKCS7 *pkcs7, BIO *bio) { return i2d_PKCS7_bio(bio, pkcs7); } int pkcs7_type_nid(PKCS7 *pkcs7) { return OBJ_obj2nid(pkcs7->type); } const char *pkcs7_type_sn(PKCS7 *pkcs7) { return OBJ_nid2sn(OBJ_obj2nid(pkcs7->type)); } %} %threadallow smime_crlf_copy; %inline %{ int smime_crlf_copy(BIO *in, BIO *out) { return SMIME_crlf_copy(in, out, PKCS7_TEXT); } /* return STACK_OF(X509)* */ STACK_OF(X509) *pkcs7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) { return PKCS7_get0_signers(p7, certs, flags); } %} M2Crypto-0.22.6rc4/SWIG/_rand.i0000664000175000017500000000530012611255457016131 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. * Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. */ /* $Id$ */ %module _rand %rename(rand_load_file) RAND_load_file; extern int RAND_load_file(const char *, long); %rename(rand_save_file) RAND_write_file; extern int RAND_write_file(const char *); %rename(rand_poll) RAND_poll; extern int RAND_poll(void); %rename(rand_status) RAND_status; extern int RAND_status(void); %rename(rand_cleanup) RAND_cleanup; extern void RAND_cleanup(void); %inline %{ static PyObject *_rand_err; void rand_init(PyObject *rand_err) { Py_INCREF(rand_err); _rand_err = rand_err; } PyObject *rand_seed(PyObject *seed) { const void *buf; int len; if (m2_PyObject_AsReadBufferInt(seed, &buf, &len) == -1) return NULL; RAND_seed(buf, len); Py_INCREF(Py_None); return Py_None; } PyObject *rand_add(PyObject *blob, double entropy) { const void *buf; int len; if (m2_PyObject_AsReadBufferInt(blob, &buf, &len) == -1) return NULL; RAND_add(buf, len, entropy); Py_INCREF(Py_None); return Py_None; } PyObject *rand_bytes(int n) { void *blob; PyObject *obj; if (!(blob = PyMem_Malloc(n))) { PyErr_SetString(PyExc_MemoryError, "rand_bytes"); return NULL; } if (RAND_bytes(blob, n)) { obj = PyString_FromStringAndSize(blob, n); PyMem_Free(blob); return obj; } else { PyMem_Free(blob); Py_INCREF(Py_None); return Py_None; } } PyObject *rand_pseudo_bytes(int n) { int ret; unsigned char *blob; PyObject *tuple; if (!(blob=(unsigned char *)PyMem_Malloc(n))) { PyErr_SetString(PyExc_MemoryError, "rand_pseudo_bytes"); return NULL; } if (!(tuple=PyTuple_New(2))) { PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails"); PyMem_Free(blob); return NULL; } ret = RAND_pseudo_bytes(blob, n); if (ret == -1) { PyMem_Free(blob); Py_DECREF(tuple); Py_INCREF(Py_None); return Py_None; } else { PyTuple_SET_ITEM(tuple, 0, PyString_FromStringAndSize((char*)blob, n)); PyMem_Free(blob); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((long)ret)); return tuple; } } void rand_screen(void) { #ifdef __WINDOWS__ RAND_screen(); #endif } int rand_win32_event(unsigned int imsg, int wparam, long lparam) { #ifdef __WINDOWS__ return RAND_event(imsg, wparam, lparam); #else return 0; #endif } %} /* 2004-04-05, ngps: Still missing: RAND_egd RAND_egd_bytes RAND_query_egd_bytes RAND_file_name */ M2Crypto-0.22.6rc4/SWIG/_rc4.i0000664000175000017500000000234112611255457015677 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include %} %apply Pointer NONNULL { RC4_KEY * }; %inline %{ RC4_KEY *rc4_new(void) { RC4_KEY *key; if (!(key = (RC4_KEY *)PyMem_Malloc(sizeof(RC4_KEY)))) PyErr_SetString(PyExc_MemoryError, "rc4_new"); return key; } void rc4_free(RC4_KEY *key) { PyMem_Free((void *)key); } PyObject *rc4_set_key(RC4_KEY *key, PyObject *value) { const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; RC4_set_key(key, vlen, vbuf); Py_INCREF(Py_None); return Py_None; } PyObject *rc4_update(RC4_KEY *key, PyObject *in) { PyObject *ret; const void *buf; Py_ssize_t len; void *out; if (PyObject_AsReadBuffer(in, &buf, &len) == -1) return NULL; if (!(out = PyMem_Malloc(len))) { PyErr_SetString(PyExc_MemoryError, "expected a string object"); return NULL; } RC4(key, len, buf, out); ret = PyString_FromStringAndSize(out, len); PyMem_Free(out); return ret; } int rc4_type_check(RC4_KEY *key) { return 1; } %} M2Crypto-0.22.6rc4/SWIG/_rsa.i0000664000175000017500000002735612611255457016011 0ustar matejmatej00000000000000/* Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #include #include #include #include %} %apply Pointer NONNULL { RSA * }; %apply Pointer NONNULL { PyObject *pyfunc }; %rename(rsa_new) RSA_new; extern RSA *RSA_new(void); %rename(rsa_free) RSA_free; extern void RSA_free(RSA *); %rename(rsa_size) RSA_size; extern int RSA_size(const RSA *); %rename(rsa_check_key) RSA_check_key; extern int RSA_check_key(const RSA *); %constant int no_padding = RSA_NO_PADDING; %constant int pkcs1_padding = RSA_PKCS1_PADDING; %constant int sslv23_padding = RSA_SSLV23_PADDING; %constant int pkcs1_oaep_padding = RSA_PKCS1_OAEP_PADDING; %constant int NID_sha1 = NID_sha1; #if OPENSSL_VERSION_NUMBER >= 0x0090800fL %constant int NID_sha224 = NID_sha224; %constant int NID_sha256 = NID_sha256; %constant int NID_sha384 = NID_sha384; %constant int NID_sha512 = NID_sha512; #endif %constant int NID_md5 = NID_md5; %constant int NID_ripemd160 = NID_ripemd160; %inline %{ static PyObject *_rsa_err; void rsa_init(PyObject *rsa_err) { Py_INCREF(rsa_err); _rsa_err = rsa_err; } %} %inline %{ RSA *rsa_read_key(BIO *f, PyObject *pyfunc) { RSA *rsa; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS rsa = PEM_read_bio_RSAPrivateKey(f, NULL, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return rsa; } %} %inline %{ int rsa_write_key(RSA *rsa, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_RSAPrivateKey(f, rsa, cipher, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %inline %{ int rsa_write_key_no_cipher(RSA *rsa, BIO *f, PyObject *pyfunc) { int ret; Py_INCREF(pyfunc); Py_BEGIN_ALLOW_THREADS ret = PEM_write_bio_RSAPrivateKey(f, rsa, NULL, NULL, 0, passphrase_callback, (void *)pyfunc); Py_END_ALLOW_THREADS Py_DECREF(pyfunc); return ret; } %} %threadallow rsa_read_pub_key; %inline %{ RSA *rsa_read_pub_key(BIO *f) { return PEM_read_bio_RSA_PUBKEY(f, NULL, NULL, NULL); } %} %threadallow rsa_write_pub_key; %inline %{ int rsa_write_pub_key(RSA *rsa, BIO *f) { return PEM_write_bio_RSA_PUBKEY(f, rsa); } PyObject *rsa_get_e(RSA *rsa) { if (!rsa->e) { PyErr_SetString(_rsa_err, "'e' is unset"); return NULL; } return bn_to_mpi(rsa->e); } PyObject *rsa_get_n(RSA *rsa) { if (!rsa->n) { PyErr_SetString(_rsa_err, "'n' is unset"); return NULL; } return bn_to_mpi(rsa->n); } PyObject *rsa_set_e(RSA *rsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (rsa->e) BN_free(rsa->e); rsa->e = bn; Py_INCREF(Py_None); return Py_None; } PyObject *rsa_set_n(RSA *rsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (rsa->n) BN_free(rsa->n); rsa->n = bn; Py_INCREF(Py_None); return Py_None; } PyObject *rsa_set_e_bin(RSA *rsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_bin2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (rsa->e) BN_free(rsa->e); rsa->e = bn; Py_INCREF(Py_None); return Py_None; } PyObject *rsa_set_n_bin(RSA *rsa, PyObject *value) { BIGNUM *bn; const void *vbuf; int vlen; if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) return NULL; if (!(bn = BN_bin2bn((unsigned char *)vbuf, vlen, NULL))) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } if (rsa->n) BN_free(rsa->n); rsa->n = bn; Py_INCREF(Py_None); return Py_None; } PyObject *rsa_private_encrypt(RSA *rsa, PyObject *from, int padding) { const void *fbuf; void *tbuf; int flen, tlen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return NULL; if (!(tbuf = PyMem_Malloc(BN_num_bytes(rsa->n)))) { PyErr_SetString(PyExc_MemoryError, "rsa_private_encrypt"); return NULL; } tlen = RSA_private_encrypt(flen, (unsigned char *)fbuf, (unsigned char *)tbuf, rsa, padding); if (tlen == -1) { PyMem_Free(tbuf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)tbuf, tlen); PyMem_Free(tbuf); return ret; } PyObject *rsa_public_decrypt(RSA *rsa, PyObject *from, int padding) { const void *fbuf; void *tbuf; int flen, tlen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return NULL; if (!(tbuf = PyMem_Malloc(BN_num_bytes(rsa->n)))) { PyErr_SetString(PyExc_MemoryError, "rsa_public_decrypt"); return NULL; } tlen = RSA_public_decrypt(flen, (unsigned char *)fbuf, (unsigned char *)tbuf, rsa, padding); if (tlen == -1) { PyMem_Free(tbuf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)tbuf, tlen); PyMem_Free(tbuf); return ret; } PyObject *rsa_public_encrypt(RSA *rsa, PyObject *from, int padding) { const void *fbuf; void *tbuf; int flen, tlen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return NULL; if (!(tbuf = PyMem_Malloc(BN_num_bytes(rsa->n)))) { PyErr_SetString(PyExc_MemoryError, "rsa_public_encrypt"); return NULL; } tlen = RSA_public_encrypt(flen, (unsigned char *)fbuf, (unsigned char *)tbuf, rsa, padding); if (tlen == -1) { PyMem_Free(tbuf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)tbuf, tlen); PyMem_Free(tbuf); return ret; } PyObject *rsa_private_decrypt(RSA *rsa, PyObject *from, int padding) { const void *fbuf; void *tbuf; int flen, tlen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) return NULL; if (!(tbuf = PyMem_Malloc(BN_num_bytes(rsa->n)))) { PyErr_SetString(PyExc_MemoryError, "rsa_private_decrypt"); return NULL; } tlen = RSA_private_decrypt(flen, (unsigned char *)fbuf, (unsigned char *)tbuf, rsa, padding); if (tlen == -1) { PyMem_Free(tbuf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)tbuf, tlen); PyMem_Free(tbuf); return ret; } #if OPENSSL_VERSION_NUMBER >= 0x0090708fL PyObject *rsa_padding_add_pkcs1_pss(RSA *rsa, PyObject *digest, EVP_MD *hash, int salt_length) { const void *dbuf; unsigned char *tbuf; int dlen, result, tlen; PyObject *ret; if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1) return NULL; tlen = RSA_size(rsa); if (!(tbuf = OPENSSL_malloc(tlen))) { PyErr_SetString(PyExc_MemoryError, "rsa_padding_add_pkcs1_pss"); return NULL; } result = RSA_padding_add_PKCS1_PSS( rsa, tbuf, (unsigned char *)dbuf, hash, salt_length); if (result == -1) { OPENSSL_cleanse(tbuf, tlen); OPENSSL_free(tbuf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ret = PyString_FromStringAndSize((const char *)tbuf, tlen); OPENSSL_cleanse(tbuf, tlen); OPENSSL_free(tbuf); return ret; } int rsa_verify_pkcs1_pss(RSA *rsa, PyObject *digest, PyObject *signature, EVP_MD *hash, int salt_length) { const void *dbuf; const void *sbuf; int dlen, slen, ret; if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1) { return 0; } if (m2_PyObject_AsReadBufferInt(signature, &sbuf, &slen) == -1) { return 0; } ret = RSA_verify_PKCS1_PSS( rsa, (unsigned char *)dbuf, hash, (unsigned char *)sbuf, salt_length); return ret; } #endif PyObject *rsa_sign(RSA *rsa, PyObject *py_digest_string, int method_type) { int digest_len = 0; int buf_len = 0; int ret = 0; unsigned int real_buf_len = 0; char *digest_string = NULL; unsigned char * sign_buf = NULL; PyObject *signature; ret = m2_PyString_AsStringAndSizeInt(py_digest_string, &digest_string, &digest_len); if (ret == -1) { /* PyString_AsStringAndSize raises the correct exceptions. */ return NULL; } buf_len = RSA_size(rsa); sign_buf = (unsigned char *)PyMem_Malloc(buf_len); ret = RSA_sign(method_type, (const unsigned char *)digest_string, digest_len, sign_buf, &real_buf_len, rsa); if (!ret) { PyMem_Free(sign_buf); PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } signature = PyString_FromStringAndSize((const char*) sign_buf, buf_len); PyMem_Free(sign_buf); return signature; } int rsa_verify(RSA *rsa, PyObject *py_verify_string, PyObject* py_sign_string, int method_type){ int ret = 0; char * sign_string = NULL; char * verify_string = NULL; int verify_len = 0; int sign_len = 0; ret = m2_PyString_AsStringAndSizeInt(py_verify_string, &verify_string, &verify_len); if (ret == -1) { /* PyString_AsStringAndSize raises the correct exceptions. */ return 0; } ret = m2_PyString_AsStringAndSizeInt(py_sign_string, &sign_string, &sign_len); if (ret == -1) { return 0; } ret = RSA_verify(method_type, (unsigned char *) verify_string, verify_len, (unsigned char *) sign_string, sign_len, rsa); if (!ret) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); } return ret; } void genrsa_callback(int p, int n, void *arg) { PyObject *argv, *ret, *cbfunc; cbfunc = (PyObject *)arg; argv = Py_BuildValue("(ii)", p, n); ret = PyEval_CallObject(cbfunc, argv); PyErr_Clear(); Py_DECREF(argv); Py_XDECREF(ret); } PyObject *rsa_generate_key(int bits, unsigned long e, PyObject *pyfunc) { RSA *rsa; PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ Py_INCREF(pyfunc); rsa = RSA_generate_key(bits, e, genrsa_callback, (void *)pyfunc); Py_DECREF(pyfunc); if (!rsa) { PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error())); return NULL; } return SWIG_NewPointerObj((void *)rsa, SWIGTYPE_p_RSA, 0); } int rsa_type_check(RSA *rsa) { return 1; } int rsa_check_pub_key(RSA *rsa) { return (rsa->e) && (rsa->n); } %} %threadallow rsa_write_key_der; %inline %{ int rsa_write_key_der(RSA *rsa, BIO *bio) { return i2d_RSAPrivateKey_bio(bio, rsa); } %} M2Crypto-0.22.6rc4/SWIG/_ssl.i0000664000175000017500000006301012611255457016010 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ /* ** Portions created by Open Source Applications Foundation (OSAF) are ** Copyright (C) 2004-2005 OSAF. All Rights Reserved. ** ** Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. ** */ /* $Id$ */ %{ #include #include #include #include #include #include #include #include #include %} %apply Pointer NONNULL { SSL_CTX * }; %apply Pointer NONNULL { SSL * }; %apply Pointer NONNULL { SSL_CIPHER * }; %apply Pointer NONNULL { STACK_OF(SSL_CIPHER) * }; %apply Pointer NONNULL { STACK_OF(X509) * }; %apply Pointer NONNULL { BIO * }; %apply Pointer NONNULL { DH * }; %apply Pointer NONNULL { RSA * }; %apply Pointer NONNULL { EVP_PKEY *}; %apply Pointer NONNULL { PyObject *pyfunc }; %rename(ssl_get_ciphers) SSL_get_ciphers; extern STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl); %rename(ssl_get_version) SSL_get_version; extern const char *SSL_get_version(CONST SSL *); %rename(ssl_get_error) SSL_get_error; extern int SSL_get_error(CONST SSL *, int); %rename(ssl_get_state) SSL_state_string; extern const char *SSL_state_string(const SSL *); %rename(ssl_get_state_v) SSL_state_string_long; extern const char *SSL_state_string_long(const SSL *); %rename(ssl_get_alert_type) SSL_alert_type_string; extern const char *SSL_alert_type_string(int); %rename(ssl_get_alert_type_v) SSL_alert_type_string_long; extern const char *SSL_alert_type_string_long(int); %rename(ssl_get_alert_desc) SSL_alert_desc_string; extern const char *SSL_alert_desc_string(int); %rename(ssl_get_alert_desc_v) SSL_alert_desc_string_long; extern const char *SSL_alert_desc_string_long(int); #ifndef OPENSSL_NO_SSL2 %rename(sslv2_method) SSLv2_method; extern SSL_METHOD *SSLv2_method(void); #endif %rename(sslv3_method) SSLv3_method; extern SSL_METHOD *SSLv3_method(void); %rename(sslv23_method) SSLv23_method; extern SSL_METHOD *SSLv23_method(void); %rename(tlsv1_method) TLSv1_method; extern SSL_METHOD *TLSv1_method(void); %typemap(out) SSL_CTX * { PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ if ($1 != NULL) $result = SWIG_NewPointerObj($1, $1_descriptor, 0); else { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); $result = NULL; } } %rename(ssl_ctx_new) SSL_CTX_new; extern SSL_CTX *SSL_CTX_new(SSL_METHOD *); %typemap(out) SSL_CTX *; %rename(ssl_ctx_free) SSL_CTX_free; extern void SSL_CTX_free(SSL_CTX *); %rename(ssl_ctx_set_verify_depth) SSL_CTX_set_verify_depth; extern void SSL_CTX_set_verify_depth(SSL_CTX *, int); %rename(ssl_ctx_get_verify_depth) SSL_CTX_get_verify_depth; extern int SSL_CTX_get_verify_depth(CONST SSL_CTX *); %rename(ssl_ctx_get_verify_mode) SSL_CTX_get_verify_mode; extern int SSL_CTX_get_verify_mode(CONST SSL_CTX *); %rename(ssl_ctx_set_cipher_list) SSL_CTX_set_cipher_list; extern int SSL_CTX_set_cipher_list(SSL_CTX *, const char *); %rename(ssl_ctx_add_session) SSL_CTX_add_session; extern int SSL_CTX_add_session(SSL_CTX *, SSL_SESSION *); %rename(ssl_ctx_remove_session) SSL_CTX_remove_session; extern int SSL_CTX_remove_session(SSL_CTX *, SSL_SESSION *); %rename(ssl_ctx_set_session_timeout) SSL_CTX_set_timeout; extern long SSL_CTX_set_timeout(SSL_CTX *, long); %rename(ssl_ctx_get_session_timeout) SSL_CTX_get_timeout; extern long SSL_CTX_get_timeout(CONST SSL_CTX *); %rename(ssl_ctx_get_cert_store) SSL_CTX_get_cert_store; extern X509_STORE *SSL_CTX_get_cert_store(CONST SSL_CTX *); %rename(bio_new_ssl) BIO_new_ssl; extern BIO *BIO_new_ssl(SSL_CTX *, int); %rename(ssl_new) SSL_new; extern SSL *SSL_new(SSL_CTX *); %rename(ssl_free) SSL_free; %threadallow SSL_free; extern void SSL_free(SSL *); %rename(ssl_dup) SSL_dup; extern SSL *SSL_dup(SSL *); %rename(ssl_set_bio) SSL_set_bio; extern void SSL_set_bio(SSL *, BIO *, BIO *); %rename(ssl_set_accept_state) SSL_set_accept_state; extern void SSL_set_accept_state(SSL *); %rename(ssl_set_connect_state) SSL_set_connect_state; extern void SSL_set_connect_state(SSL *); %rename(ssl_get_shutdown) SSL_get_shutdown; extern int SSL_get_shutdown(CONST SSL *); %rename(ssl_set_shutdown) SSL_set_shutdown; extern void SSL_set_shutdown(SSL *, int); %rename(ssl_shutdown) SSL_shutdown; %threadallow SSL_shutdown; extern int SSL_shutdown(SSL *); %rename(ssl_clear) SSL_clear; extern int SSL_clear(SSL *); %rename(ssl_do_handshake) SSL_do_handshake; %threadallow SSL_do_handshake; extern int SSL_do_handshake(SSL *); %rename(ssl_renegotiate) SSL_renegotiate; %threadallow SSL_renegotiate; extern int SSL_renegotiate(SSL *); %rename(ssl_pending) SSL_pending; extern int SSL_pending(CONST SSL *); %rename(ssl_get_peer_cert) SSL_get_peer_certificate; extern X509 *SSL_get_peer_certificate(CONST SSL *); %rename(ssl_get_current_cipher) SSL_get_current_cipher; extern SSL_CIPHER *SSL_get_current_cipher(CONST SSL *); %rename(ssl_get_verify_mode) SSL_get_verify_mode; extern int SSL_get_verify_mode(CONST SSL *); %rename(ssl_get_verify_depth) SSL_get_verify_depth; extern int SSL_get_verify_depth(CONST SSL *); %rename(ssl_get_verify_result) SSL_get_verify_result; extern long SSL_get_verify_result(CONST SSL *); %rename(ssl_get_ssl_ctx) SSL_get_SSL_CTX; extern SSL_CTX *SSL_get_SSL_CTX(CONST SSL *); %rename(ssl_get_default_session_timeout) SSL_get_default_timeout; extern long SSL_get_default_timeout(CONST SSL *); %rename(ssl_set_cipher_list) SSL_set_cipher_list; extern int SSL_set_cipher_list(SSL *, const char *); %rename(ssl_get_cipher_list) SSL_get_cipher_list; extern const char *SSL_get_cipher_list(CONST SSL *, int); %rename(ssl_cipher_get_name) SSL_CIPHER_get_name; extern const char *SSL_CIPHER_get_name(CONST SSL_CIPHER *); %rename(ssl_cipher_get_version) SSL_CIPHER_get_version; extern char *SSL_CIPHER_get_version(CONST SSL_CIPHER *); %rename(ssl_get_session) SSL_get_session; extern SSL_SESSION *SSL_get_session(CONST SSL *); %rename(ssl_get1_session) SSL_get1_session; extern SSL_SESSION *SSL_get1_session(SSL *); %rename(ssl_set_session) SSL_set_session; extern int SSL_set_session(SSL *, SSL_SESSION *); %rename(ssl_session_free) SSL_SESSION_free; extern void SSL_SESSION_free(SSL_SESSION *); %rename(ssl_session_print) SSL_SESSION_print; %threadallow SSL_SESSION_print; extern int SSL_SESSION_print(BIO *, CONST SSL_SESSION *); %rename(ssl_session_set_timeout) SSL_SESSION_set_timeout; extern long SSL_SESSION_set_timeout(SSL_SESSION *, long); %rename(ssl_session_get_timeout) SSL_SESSION_get_timeout; extern long SSL_SESSION_get_timeout(CONST SSL_SESSION *); extern PyObject *ssl_accept(SSL *ssl, double timeout = -1); extern PyObject *ssl_connect(SSL *ssl, double timeout = -1); extern PyObject *ssl_read(SSL *ssl, int num, double timeout = -1); extern int ssl_write(SSL *ssl, PyObject *blob, double timeout = -1); %constant int ssl_error_none = SSL_ERROR_NONE; %constant int ssl_error_ssl = SSL_ERROR_SSL; %constant int ssl_error_want_read = SSL_ERROR_WANT_READ; %constant int ssl_error_want_write = SSL_ERROR_WANT_WRITE; %constant int ssl_error_want_x509_lookup = SSL_ERROR_WANT_X509_LOOKUP; %constant int ssl_error_syscall = SSL_ERROR_SYSCALL; %constant int ssl_error_zero_return = SSL_ERROR_ZERO_RETURN; %constant int ssl_error_want_connect = SSL_ERROR_WANT_CONNECT; %constant int SSL_VERIFY_NONE = 0x00; %constant int SSL_VERIFY_PEER = 0x01; %constant int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 0x02; %constant int SSL_VERIFY_CLIENT_ONCE = 0x04; %constant int SSL_ST_CONNECT = 0x1000; %constant int SSL_ST_ACCEPT = 0x2000; %constant int SSL_ST_MASK = 0x0FFF; %constant int SSL_ST_INIT = (SSL_ST_CONNECT|SSL_ST_ACCEPT); %constant int SSL_ST_BEFORE = 0x4000; %constant int SSL_ST_OK = 0x03; %constant int SSL_ST_RENEGOTIATE = (0x04|SSL_ST_INIT); %constant int SSL_CB_LOOP = 0x01; %constant int SSL_CB_EXIT = 0x02; %constant int SSL_CB_READ = 0x04; %constant int SSL_CB_WRITE = 0x08; %constant int SSL_CB_ALERT = 0x4000; /* used in callback */ %constant int SSL_CB_READ_ALERT = (SSL_CB_ALERT|SSL_CB_READ); %constant int SSL_CB_WRITE_ALERT = (SSL_CB_ALERT|SSL_CB_WRITE); %constant int SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT|SSL_CB_LOOP); %constant int SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT|SSL_CB_EXIT); %constant int SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT|SSL_CB_LOOP); %constant int SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT|SSL_CB_EXIT); %constant int SSL_CB_HANDSHAKE_START = 0x10; %constant int SSL_CB_HANDSHAKE_DONE = 0x20; %constant int SSL_SENT_SHUTDOWN = 1; %constant int SSL_RECEIVED_SHUTDOWN = 2; %constant int SSL_SESS_CACHE_OFF = 0x000; %constant int SSL_SESS_CACHE_CLIENT = 0x001; %constant int SSL_SESS_CACHE_SERVER = 0x002; %constant int SSL_SESS_CACHE_BOTH = (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER); %constant int SSL_OP_ALL = 0x00000FFFL; %constant int SSL_OP_NO_SSLv2 = 0x01000000L; %constant int SSL_OP_NO_SSLv3 = 0x02000000L; %constant int SSL_OP_NO_TLSv1 = 0x04000000L; %constant int SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800L; %constant int SSL_MODE_ENABLE_PARTIAL_WRITE = SSL_MODE_ENABLE_PARTIAL_WRITE; %constant int SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = SSL_MODE_ENABLE_PARTIAL_WRITE; %constant int SSL_MODE_AUTO_RETRY = SSL_MODE_AUTO_RETRY; %ignore ssl_handle_error; %ignore ssl_sleep_with_timeout; %inline %{ static PyObject *_ssl_err; static PyObject *_ssl_timeout_err; void ssl_init(PyObject *ssl_err, PyObject *ssl_timeout_err) { SSL_library_init(); SSL_load_error_strings(); Py_INCREF(ssl_err); Py_INCREF(ssl_timeout_err); _ssl_err = ssl_err; _ssl_timeout_err = ssl_timeout_err; } void ssl_ctx_passphrase_callback(SSL_CTX *ctx, PyObject *pyfunc) { SSL_CTX_set_default_passwd_cb(ctx, passphrase_callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)pyfunc); Py_INCREF(pyfunc); } int ssl_ctx_use_x509(SSL_CTX *ctx, X509 *x) { int i; if (!(i = SSL_CTX_use_certificate(ctx, x))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_use_cert(SSL_CTX *ctx, char *file) { int i; if (!(i = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_use_cert_chain(SSL_CTX *ctx, char *file) { int i; if (!(i = SSL_CTX_use_certificate_chain_file(ctx, file))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_use_privkey(SSL_CTX *ctx, char *file) { int i; if (!(i = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_use_rsa_privkey(SSL_CTX *ctx, RSA *rsakey) { int i; if (!(i = SSL_CTX_use_RSAPrivateKey(ctx, rsakey))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_use_pkey_privkey(SSL_CTX *ctx, EVP_PKEY *pkey) { int i; if (!(i = SSL_CTX_use_PrivateKey(ctx, pkey))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return i; } int ssl_ctx_check_privkey(SSL_CTX *ctx) { int ret; if (!(ret = SSL_CTX_check_private_key(ctx))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return ret; } void ssl_ctx_set_client_CA_list_from_file(SSL_CTX *ctx, const char *ca_file) { SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file)); } void ssl_ctx_set_verify_default(SSL_CTX *ctx, int mode) { SSL_CTX_set_verify(ctx, mode, NULL); } void ssl_ctx_set_verify(SSL_CTX *ctx, int mode, PyObject *pyfunc) { Py_XDECREF(ssl_verify_cb_func); Py_INCREF(pyfunc); ssl_verify_cb_func = pyfunc; SSL_CTX_set_verify(ctx, mode, ssl_verify_callback); } int ssl_ctx_set_session_id_context(SSL_CTX *ctx, PyObject *sid_ctx) { const void *buf; int len; if (m2_PyObject_AsReadBufferInt(sid_ctx, &buf, &len) == -1) return -1; return SSL_CTX_set_session_id_context(ctx, buf, len); } void ssl_ctx_set_info_callback(SSL_CTX *ctx, PyObject *pyfunc) { Py_XDECREF(ssl_info_cb_func); Py_INCREF(pyfunc); ssl_info_cb_func = pyfunc; SSL_CTX_set_info_callback(ctx, ssl_info_callback); } long ssl_ctx_set_tmp_dh(SSL_CTX *ctx, DH* dh) { return SSL_CTX_set_tmp_dh(ctx, dh); } void ssl_ctx_set_tmp_dh_callback(SSL_CTX *ctx, PyObject *pyfunc) { Py_XDECREF(ssl_set_tmp_dh_cb_func); Py_INCREF(pyfunc); ssl_set_tmp_dh_cb_func = pyfunc; SSL_CTX_set_tmp_dh_callback(ctx, ssl_set_tmp_dh_callback); } long ssl_ctx_set_tmp_rsa(SSL_CTX *ctx, RSA* rsa) { return SSL_CTX_set_tmp_rsa(ctx, rsa); } void ssl_ctx_set_tmp_rsa_callback(SSL_CTX *ctx, PyObject *pyfunc) { Py_XDECREF(ssl_set_tmp_rsa_cb_func); Py_INCREF(pyfunc); ssl_set_tmp_rsa_cb_func = pyfunc; SSL_CTX_set_tmp_rsa_callback(ctx, ssl_set_tmp_rsa_callback); } int ssl_ctx_load_verify_locations(SSL_CTX *ctx, const char *cafile, const char *capath) { return SSL_CTX_load_verify_locations(ctx, cafile, capath); } /* SSL_CTX_set_options is a macro. */ long ssl_ctx_set_options(SSL_CTX *ctx, long op) { return SSL_CTX_set_options(ctx, op); } int bio_set_ssl(BIO *bio, SSL *ssl, int flag) { SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); return BIO_ctrl(bio, BIO_C_SET_SSL, flag, (char *)ssl); } long ssl_set_mode(SSL *ssl, long mode) { return SSL_set_mode(ssl, mode); } long ssl_get_mode(SSL *ssl) { return SSL_get_mode(ssl); } int ssl_set_tlsext_host_name(SSL *ssl, const char *name) { long l; if (!(l = SSL_set_tlsext_host_name(ssl, name))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } /* Return an "int" to match the 'typemap(out) int' in _lib.i */ return 1; } void ssl_set_client_CA_list_from_file(SSL *ssl, const char *ca_file) { SSL_set_client_CA_list(ssl, SSL_load_client_CA_file(ca_file)); } void ssl_set_client_CA_list_from_context(SSL *ssl, SSL_CTX *ctx) { SSL_set_client_CA_list(ssl, SSL_CTX_get_client_CA_list(ctx)); } int ssl_set_session_id_context(SSL *ssl, PyObject *sid_ctx) { const void *buf; int len; if (m2_PyObject_AsReadBufferInt(sid_ctx, &buf, &len) == -1) return -1; return SSL_set_session_id_context(ssl, buf, len); } int ssl_set_fd(SSL *ssl, int fd) { int ret; if (!(ret = SSL_set_fd(ssl, fd))) { PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); return -1; } return ret; } static void ssl_handle_error(int ssl_err, int ret) { int err; switch (ssl_err) { case SSL_ERROR_SSL: PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); break; case SSL_ERROR_SYSCALL: err = ERR_get_error(); if (err) PyErr_SetString(_ssl_err, ERR_reason_error_string(err)); else if (ret == 0) PyErr_SetString(_ssl_err, "unexpected eof"); else if (ret == -1) PyErr_SetFromErrno(_ssl_err); else assert(0); break; default: PyErr_SetString(_ssl_err, "unexpected SSL error"); } } static int ssl_sleep_with_timeout(SSL *ssl, const struct timeval *start, double timeout, int ssl_err) { struct pollfd fd; struct timeval tv; int ms, tmp; assert(timeout > 0); again: gettimeofday(&tv, NULL); /* tv >= start */ if ((timeout + start->tv_sec - tv.tv_sec) > INT_MAX / 1000) ms = -1; else { int fract; ms = ((start->tv_sec + (int)timeout) - tv.tv_sec) * 1000; fract = (start->tv_usec + (timeout - (int)timeout) * 1000000 - tv.tv_usec + 999) / 1000; if (ms > 0 && fract > INT_MAX - ms) ms = -1; else { ms += fract; if (ms <= 0) goto timeout; } } switch (ssl_err) { case SSL_ERROR_WANT_READ: fd.fd = SSL_get_rfd(ssl); fd.events = POLLIN; break; case SSL_ERROR_WANT_WRITE: fd.fd = SSL_get_wfd(ssl); fd.events = POLLOUT; break; case SSL_ERROR_WANT_X509_LOOKUP: return 0; /* FIXME: is this correct? */ default: assert(0); } if (fd.fd == -1) { PyErr_SetString(_ssl_err, "timeout on a non-FD SSL"); return -1; } Py_BEGIN_ALLOW_THREADS tmp = poll(&fd, 1, ms); Py_END_ALLOW_THREADS switch (tmp) { case 1: return 0; case 0: goto timeout; case -1: if (errno == EINTR) goto again; PyErr_SetFromErrno(_ssl_err); return -1; } return 0; timeout: PyErr_SetString(_ssl_timeout_err, "timed out"); return -1; } PyObject *ssl_accept(SSL *ssl, double timeout) { PyObject *obj = NULL; int r, ssl_err; struct timeval tv; if (timeout > 0) gettimeofday(&tv, NULL); again: Py_BEGIN_ALLOW_THREADS r = SSL_accept(ssl); ssl_err = SSL_get_error(ssl, r); Py_END_ALLOW_THREADS switch (ssl_err) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: obj = PyInt_FromLong((long)1); break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: if (timeout <= 0) { obj = PyInt_FromLong((long)0); break; } if (ssl_sleep_with_timeout(ssl, &tv, timeout, ssl_err) == 0) goto again; obj = NULL; break; case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: ssl_handle_error(ssl_err, r); obj = NULL; break; } return obj; } PyObject *ssl_connect(SSL *ssl, double timeout) { PyObject *obj = NULL; int r, ssl_err; struct timeval tv; if (timeout > 0) gettimeofday(&tv, NULL); again: Py_BEGIN_ALLOW_THREADS r = SSL_connect(ssl); ssl_err = SSL_get_error(ssl, r); Py_END_ALLOW_THREADS switch (ssl_err) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: obj = PyInt_FromLong((long)1); break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: if (timeout <= 0) { obj = PyInt_FromLong((long)0); break; } if (ssl_sleep_with_timeout(ssl, &tv, timeout, ssl_err) == 0) goto again; obj = NULL; break; case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: ssl_handle_error(ssl_err, r); obj = NULL; break; } return obj; } void ssl_set_shutdown1(SSL *ssl, int mode) { SSL_set_shutdown(ssl, mode); } PyObject *ssl_read(SSL *ssl, int num, double timeout) { PyObject *obj = NULL; void *buf; int r; struct timeval tv; if (!(buf = PyMem_Malloc(num))) { PyErr_SetString(PyExc_MemoryError, "ssl_read"); return NULL; } if (timeout > 0) gettimeofday(&tv, NULL); again: Py_BEGIN_ALLOW_THREADS r = SSL_read(ssl, buf, num); Py_END_ALLOW_THREADS if (r >= 0) { buf = PyMem_Realloc(buf, r); obj = PyString_FromStringAndSize(buf, r); } else { int ssl_err; ssl_err = SSL_get_error(ssl, r); switch (ssl_err) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: assert(0); case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: if (timeout <= 0) { Py_INCREF(Py_None); obj = Py_None; break; } if (ssl_sleep_with_timeout(ssl, &tv, timeout, ssl_err) == 0) goto again; obj = NULL; break; case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: ssl_handle_error(ssl_err, r); obj = NULL; break; } } PyMem_Free(buf); return obj; } PyObject *ssl_read_nbio(SSL *ssl, int num) { PyObject *obj = NULL; void *buf; int r, err; if (!(buf = PyMem_Malloc(num))) { PyErr_SetString(PyExc_MemoryError, "ssl_read"); return NULL; } Py_BEGIN_ALLOW_THREADS r = SSL_read(ssl, buf, num); Py_END_ALLOW_THREADS switch (SSL_get_error(ssl, r)) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: buf = PyMem_Realloc(buf, r); obj = PyString_FromStringAndSize(buf, r); break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: Py_INCREF(Py_None); obj = Py_None; break; case SSL_ERROR_SSL: PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); obj = NULL; break; case SSL_ERROR_SYSCALL: err = ERR_get_error(); if (err) PyErr_SetString(_ssl_err, ERR_reason_error_string(err)); else if (r == 0) PyErr_SetString(_ssl_err, "unexpected eof"); else if (r == -1) PyErr_SetFromErrno(_ssl_err); obj = NULL; break; } PyMem_Free(buf); return obj; } int ssl_write(SSL *ssl, PyObject *blob, double timeout) { Py_buffer buf; int r, ssl_err, ret; struct timeval tv; if (m2_PyObject_GetBufferInt(blob, &buf, PyBUF_CONTIG_RO) == -1) { return -1; } if (timeout > 0) gettimeofday(&tv, NULL); again: Py_BEGIN_ALLOW_THREADS r = SSL_write(ssl, buf.buf, buf.len); ssl_err = SSL_get_error(ssl, r); Py_END_ALLOW_THREADS switch (ssl_err) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: ret = r; break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: if (timeout <= 0) { ret = -1; break; } if (ssl_sleep_with_timeout(ssl, &tv, timeout, ssl_err) == 0) goto again; ret = -1; break; case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: ssl_handle_error(ssl_err, r); default: ret = -1; } m2_PyBuffer_Release(blob, &buf); return ret; } int ssl_write_nbio(SSL *ssl, PyObject *blob) { Py_buffer buf; int r, err, ret; if (m2_PyObject_GetBufferInt(blob, &buf, PyBUF_CONTIG_RO) == -1) { return -1; } Py_BEGIN_ALLOW_THREADS r = SSL_write(ssl, buf.buf, buf.len); Py_END_ALLOW_THREADS switch (SSL_get_error(ssl, r)) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: ret = r; break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: ret = -1; break; case SSL_ERROR_SSL: ret = -1; break; case SSL_ERROR_SYSCALL: err = ERR_get_error(); if (err) PyErr_SetString(_ssl_err, ERR_reason_error_string(err)); else if (r == 0) PyErr_SetString(_ssl_err, "unexpected eof"); else if (r == -1) PyErr_SetFromErrno(_ssl_err); default: ret = -1; } m2_PyBuffer_Release(blob, &buf); return ret; } int ssl_cipher_get_bits(SSL_CIPHER *c) { return SSL_CIPHER_get_bits(c, NULL); } int sk_ssl_cipher_num(STACK_OF(SSL_CIPHER) *stack) { return sk_SSL_CIPHER_num(stack); } SSL_CIPHER *sk_ssl_cipher_value(STACK_OF(SSL_CIPHER) *stack, int idx) { return sk_SSL_CIPHER_value(stack, idx); } STACK_OF(X509) *ssl_get_peer_cert_chain(SSL *ssl) { return SSL_get_peer_cert_chain(ssl); } int sk_x509_num(STACK_OF(X509) *stack) { return sk_X509_num(stack); } X509 *sk_x509_value(STACK_OF(X509) *stack, int idx) { return sk_X509_value(stack, idx); } %} %threadallow i2d_ssl_session; %inline %{ void i2d_ssl_session(BIO *bio, SSL_SESSION *sess) { i2d_SSL_SESSION_bio(bio, sess); } %} %threadallow ssl_session_read_pem; %inline %{ SSL_SESSION *ssl_session_read_pem(BIO *bio) { return PEM_read_bio_SSL_SESSION(bio, NULL, NULL, NULL); } %} %threadallow ssl_session_write_pem; %inline %{ int ssl_session_write_pem(SSL_SESSION *sess, BIO *bio) { return PEM_write_bio_SSL_SESSION(bio, sess); } int ssl_ctx_set_session_cache_mode(SSL_CTX *ctx, int mode) { return SSL_CTX_set_session_cache_mode(ctx, mode); } int ssl_ctx_get_session_cache_mode(SSL_CTX *ctx) { return SSL_CTX_get_session_cache_mode(ctx); } static long ssl_ctx_set_cache_size(SSL_CTX *ctx, long arg) { return SSL_CTX_sess_set_cache_size(ctx, arg); } int ssl_is_init_finished(SSL *ssl) { return SSL_is_init_finished(ssl); } %} M2Crypto-0.22.6rc4/SWIG/_threads.i0000664000175000017500000000276212212052026016630 0ustar matejmatej00000000000000/* Copyright (c) 1999 Ng Pheng Siong. All rights reserved. */ /* $Id$ */ %{ #include #include #ifdef THREADING static PyThread_type_lock lock_cs[CRYPTO_NUM_LOCKS]; static long lock_count[CRYPTO_NUM_LOCKS]; static int thread_mode = 0; #endif void threading_locking_callback(int mode, int type, const char *file, int line) { #ifdef THREADING if (mode & CRYPTO_LOCK) { PyThread_acquire_lock(lock_cs[type], WAIT_LOCK); lock_count[type]++; } else { PyThread_release_lock(lock_cs[type]); lock_count[type]--; } #endif } unsigned long threading_id_callback(void) { #ifdef THREADING return (unsigned long)PyThread_get_thread_ident(); #else return (unsigned long)0; #endif } %} %inline %{ void threading_init(void) { #ifdef THREADING int i; if (!thread_mode) { for (i=0; i %} %inline %{ static PyObject *_util_err; void util_init(PyObject *util_err) { Py_INCREF(util_err); _util_err = util_err; } PyObject *util_hex_to_string(PyObject *blob) { PyObject *obj; const void *buf; char *ret; Py_ssize_t len; if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) return NULL; ret = hex_to_string((unsigned char *)buf, len); if (!ret) { PyErr_SetString(_util_err, ERR_reason_error_string(ERR_get_error())); return NULL; } obj = PyString_FromString(ret); OPENSSL_free(ret); return obj; } PyObject *util_string_to_hex(PyObject *blob) { PyObject *obj; const void *buf; unsigned char *ret; Py_ssize_t len0; long len; if (PyObject_AsReadBuffer(blob, &buf, &len0) == -1) return NULL; len = len0; ret = string_to_hex((char *)buf, &len); if (ret == NULL) { PyErr_SetString(_util_err, ERR_reason_error_string(ERR_get_error())); return NULL; } obj = PyString_FromStringAndSize((char*)ret, len); OPENSSL_free(ret); return obj; } %} M2Crypto-0.22.6rc4/SWIG/_x509.i0000664000175000017500000005532712607370517015730 0ustar matejmatej00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ /* ** Portions created by Open Source Applications Foundation (OSAF) are ** Copyright (C) 2004-2005 OSAF. All Rights Reserved. ** ** Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. ** */ /* $Id$ */ %{ #include #include %} %apply Pointer NONNULL { BIO * }; %apply Pointer NONNULL { X509 * }; %apply Pointer NONNULL { X509_CRL * }; %apply Pointer NONNULL { X509_REQ * }; %apply Pointer NONNULL { X509_NAME * }; %apply Pointer NONNULL { X509_NAME_ENTRY * }; %apply Pointer NONNULL { EVP_PKEY * }; #if OPENSSL_VERSION_NUMBER >= 0x0090800fL %rename(x509_check_ca) X509_check_ca; extern int X509_check_ca(X509 *); #endif %rename(x509_new) X509_new; extern X509 *X509_new( void ); %rename(x509_dup) X509_dup; extern X509 *X509_dup(X509 *); %rename(x509_free) X509_free; extern void X509_free(X509 *); %rename(x509_crl_free) X509_CRL_free; extern void X509_CRL_free(X509_CRL *); %rename(x509_crl_new) X509_CRL_new; extern X509_CRL * X509_CRL_new(); %rename(x509_print) X509_print; %threadallow X509_print; extern int X509_print(BIO *, X509 *); %rename(x509_crl_print) X509_CRL_print; %threadallow X509_CRL_print; extern int X509_CRL_print(BIO *, X509_CRL *); %rename(x509_get_serial_number) X509_get_serialNumber; extern ASN1_INTEGER *X509_get_serialNumber(X509 *); %rename(x509_set_serial_number) X509_set_serialNumber; extern int X509_set_serialNumber(X509 *, ASN1_INTEGER *); %rename(x509_get_pubkey) X509_get_pubkey; extern EVP_PKEY *X509_get_pubkey(X509 *); %rename(x509_set_pubkey) X509_set_pubkey; extern int X509_set_pubkey(X509 *, EVP_PKEY *); %rename(x509_get_issuer_name) X509_get_issuer_name; extern X509_NAME *X509_get_issuer_name(X509 *); %rename(x509_set_issuer_name) X509_set_issuer_name; extern int X509_set_issuer_name(X509 *, X509_NAME *); %rename(x509_get_subject_name) X509_get_subject_name; extern X509_NAME *X509_get_subject_name(X509 *); %rename(x509_set_subject_name) X509_set_subject_name; extern int X509_set_subject_name(X509 *, X509_NAME *); %rename(x509_cmp_current_time) X509_cmp_current_time; extern int X509_cmp_current_time(ASN1_UTCTIME *); /* From x509.h */ /* standard trust ids */ %constant int X509_TRUST_DEFAULT = -1; %constant int X509_TRUST_COMPAT = 1; %constant int X509_TRUST_SSL_CLIENT = 2; %constant int X509_TRUST_SSL_SERVER = 3; %constant int X509_TRUST_EMAIL = 4; %constant int X509_TRUST_OBJECT_SIGN = 5; %constant int X509_TRUST_OCSP_SIGN = 6; %constant int X509_TRUST_OCSP_REQUEST = 7; /* trust_flags values */ %constant int X509_TRUST_DYNAMIC = 1; %constant int X509_TRUST_DYNAMIC_NAME = 2; /* check_trust return codes */ %constant int X509_TRUST_TRUSTED = 1; %constant int X509_TRUST_REJECTED = 2; %constant int X509_TRUST_UNTRUSTED = 3; /* From x509v3.h */ %constant int X509_PURPOSE_SSL_CLIENT = 1; %constant int X509_PURPOSE_SSL_SERVER = 2; %constant int X509_PURPOSE_NS_SSL_SERVER = 3; %constant int X509_PURPOSE_SMIME_SIGN = 4; %constant int X509_PURPOSE_SMIME_ENCRYPT = 5; %constant int X509_PURPOSE_CRL_SIGN = 6; %constant int X509_PURPOSE_ANY = 7; %constant int X509_PURPOSE_OCSP_HELPER = 8; %rename(x509_check_purpose) X509_check_purpose; extern int X509_check_purpose(X509 *, int, int); %rename(x509_check_trust) X509_check_trust; extern int X509_check_trust(X509 *, int, int); %rename(x509_write_pem) PEM_write_bio_X509; %threadallow PEM_write_bio_X509; extern int PEM_write_bio_X509(BIO *, X509 *); %rename(x509_write_pem_file) PEM_write_X509; extern int PEM_write_X509(FILE *, X509 *); %rename(x509_verify) X509_verify; extern int X509_verify(X509 *a, EVP_PKEY *r); %rename(x509_get_verify_error) X509_verify_cert_error_string; extern const char *X509_verify_cert_error_string(long); %constant long X509V3_EXT_UNKNOWN_MASK = (0xfL << 16); %constant long X509V3_EXT_DEFAULT = 0; %constant long X509V3_EXT_ERROR_UNKNOWN = (1L << 16); %constant long X509V3_EXT_PARSE_UNKNOWN = (2L << 16); %constant long X509V3_EXT_DUMP_UNKNOWN = (3L << 16); %rename(x509_add_ext) X509_add_ext; extern int X509_add_ext(X509 *, X509_EXTENSION *, int); %rename(x509_get_ext_count) X509_get_ext_count; extern int X509_get_ext_count(X509 *); %rename(x509_get_ext) X509_get_ext; extern X509_EXTENSION *X509_get_ext(X509 *, int); %rename(x509_ext_print) X509V3_EXT_print; %threadallow X509V3_EXT_print; extern int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int); %rename(x509_name_new) X509_NAME_new; extern X509_NAME *X509_NAME_new( void ); %rename(x509_name_free) X509_NAME_free; extern void X509_NAME_free(X509_NAME *); %rename(x509_name_print) X509_NAME_print; %threadallow X509_NAME_print; extern int X509_NAME_print(BIO *, X509_NAME *, int); %rename(x509_name_get_entry) X509_NAME_get_entry; extern X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *, int); %rename(x509_name_entry_count) X509_NAME_entry_count; extern int X509_NAME_entry_count(X509_NAME *); %rename(x509_name_delete_entry) X509_NAME_delete_entry; extern X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int); %rename(x509_name_add_entry) X509_NAME_add_entry; extern int X509_NAME_add_entry(X509_NAME *, X509_NAME_ENTRY *, int, int); %rename(x509_name_add_entry_by_obj) X509_NAME_add_entry_by_OBJ; extern int X509_NAME_add_entry_by_OBJ(X509_NAME *, ASN1_OBJECT *, int, unsigned char *, int, int, int ); %rename(x509_name_add_entry_by_nid) X509_NAME_add_entry_by_NID; extern int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *, int, int, int ); %rename(x509_name_print_ex) X509_NAME_print_ex; %threadallow X509_NAME_print_ex; extern int X509_NAME_print_ex(BIO *, X509_NAME *, int, unsigned long); %rename(x509_name_print_ex_fp) X509_NAME_print_ex_fp; extern int X509_NAME_print_ex_fp(FILE *, X509_NAME *, int, unsigned long); #if OPENSSL_VERSION_NUMBER >= 0x10000000L %rename(x509_name_hash) X509_NAME_hash_old; extern unsigned long X509_NAME_hash_old(X509_NAME *); #else %rename(x509_name_hash) X509_NAME_hash; extern unsigned long X509_NAME_hash(X509_NAME *); #endif %rename(x509_name_get_index_by_nid) X509_NAME_get_index_by_NID; extern int X509_NAME_get_index_by_NID(X509_NAME *, int, int); %rename(x509_name_entry_new) X509_NAME_ENTRY_new; extern X509_NAME_ENTRY *X509_NAME_ENTRY_new( void ); %rename(x509_name_entry_free) X509_NAME_ENTRY_free; extern void X509_NAME_ENTRY_free( X509_NAME_ENTRY *); /*XXX This is probably bogus:*/ %rename(x509_name_entry_create_by_nid) X509_NAME_ENTRY_create_by_NID; extern X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID( X509_NAME_ENTRY **, int, int, unsigned char *, int); %rename(x509_name_entry_set_object) X509_NAME_ENTRY_set_object; extern int X509_NAME_ENTRY_set_object( X509_NAME_ENTRY *, ASN1_OBJECT *); %rename(x509_name_entry_get_object) X509_NAME_ENTRY_get_object; extern ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *); %rename(x509_name_entry_get_data) X509_NAME_ENTRY_get_data; extern ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *); %typemap(in) (CONST unsigned char *, int) { if (PyString_Check($input)) { Py_ssize_t len; $1 = (unsigned char *)PyString_AsString($input); len = PyString_Size($input); if (len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); return NULL; } $2 = len; } else { PyErr_SetString(PyExc_TypeError, "expected string"); return NULL; } } %rename(x509_name_entry_set_data) X509_NAME_ENTRY_set_data; extern int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *, int, CONST unsigned char *, int); %typemap(in) (CONST unsigned char *, int); %rename(x509_req_new) X509_REQ_new; extern X509_REQ * X509_REQ_new(); %rename(x509_req_free) X509_REQ_free; extern void X509_REQ_free(X509_REQ *); %rename(x509_req_print) X509_REQ_print; %threadallow X509_REQ_print; extern int X509_REQ_print(BIO *, X509_REQ *); %rename(x509_req_get_pubkey) X509_REQ_get_pubkey; extern EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *); %rename(x509_req_set_pubkey) X509_REQ_set_pubkey; extern int X509_REQ_set_pubkey(X509_REQ *, EVP_PKEY *); %rename(x509_req_set_subject_name) X509_REQ_set_subject_name; extern int X509_REQ_set_subject_name(X509_REQ *, X509_NAME *); %rename(x509_req_verify) X509_REQ_verify; extern int X509_REQ_verify(X509_REQ *, EVP_PKEY *); %rename(x509_req_sign) X509_REQ_sign; extern int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *); %rename(i2d_x509_bio) i2d_X509_bio; %threadallow i2d_X509_bio; extern int i2d_X509_bio(BIO *, X509 *); %rename(i2d_x509_req_bio) i2d_X509_REQ_bio; %threadallow i2d_X509_REQ_bio; extern int i2d_X509_REQ_bio(BIO *, X509_REQ *); %rename(x509_store_new) X509_STORE_new; extern X509_STORE *X509_STORE_new(void); %rename(x509_store_free) X509_STORE_free; extern void X509_STORE_free(X509_STORE *); %rename(x509_store_add_cert) X509_STORE_add_cert; extern int X509_STORE_add_cert(X509_STORE *, X509 *); %rename(x509_store_ctx_get_current_cert) X509_STORE_CTX_get_current_cert; extern X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *); %rename(x509_store_ctx_get_error) X509_STORE_CTX_get_error; extern int X509_STORE_CTX_get_error(X509_STORE_CTX *); %rename(x509_store_ctx_get_error_depth) X509_STORE_CTX_get_error_depth; extern int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *); %rename(x509_store_ctx_free) X509_STORE_CTX_free; extern void X509_STORE_CTX_free(X509_STORE_CTX *); %rename(x509_store_ctx_get1_chain) X509_STORE_CTX_get1_chain; extern STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *); %rename(x509_extension_get_critical) X509_EXTENSION_get_critical; extern int X509_EXTENSION_get_critical(X509_EXTENSION *); %rename(x509_extension_set_critical) X509_EXTENSION_set_critical; extern int X509_EXTENSION_set_critical(X509_EXTENSION *, int); %constant int NID_commonName = 13; %constant int NID_countryName = 14; %constant int NID_localityName = 15; %constant int NID_stateOrProvinceName = 16; %constant int NID_organizationName = 17; %constant int NID_organizationalUnitName = 18; %constant int NID_serialNumber = 105; %constant int NID_surname = 100; %constant int NID_givenName = 99; %constant int NID_pkcs9_emailAddress = 48; /* Cribbed from x509_vfy.h. */ %constant int X509_V_OK = 0; %constant int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2; %constant int X509_V_ERR_UNABLE_TO_GET_CRL = 3; %constant int X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4; %constant int X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5; %constant int X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6; %constant int X509_V_ERR_CERT_SIGNATURE_FAILURE = 7; %constant int X509_V_ERR_CRL_SIGNATURE_FAILURE = 8; %constant int X509_V_ERR_CERT_NOT_YET_VALID = 9; %constant int X509_V_ERR_CERT_HAS_EXPIRED = 10; %constant int X509_V_ERR_CRL_NOT_YET_VALID = 11; %constant int X509_V_ERR_CRL_HAS_EXPIRED = 12; %constant int X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13; %constant int X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14; %constant int X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15; %constant int X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16; %constant int X509_V_ERR_OUT_OF_MEM = 17; %constant int X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18; %constant int X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19; %constant int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20; %constant int X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21; %constant int X509_V_ERR_CERT_CHAIN_TOO_LONG = 22; %constant int X509_V_ERR_CERT_REVOKED = 23; %constant int X509_V_ERR_INVALID_CA = 24; %constant int X509_V_ERR_PATH_LENGTH_EXCEEDED = 25; %constant int X509_V_ERR_INVALID_PURPOSE = 26; %constant int X509_V_ERR_CERT_UNTRUSTED = 27; %constant int X509_V_ERR_CERT_REJECTED = 28; %constant int X509_V_ERR_APPLICATION_VERIFICATION = 50; /* x509.h */ %constant int XN_FLAG_COMPAT = 0; %constant int XN_FLAG_SEP_COMMA_PLUS = (1 << 16); %constant int XN_FLAG_SEP_CPLUS_SPC = (2 << 16); %constant int XN_FLAG_SEP_MULTILINE = (4 << 16); %constant int XN_FLAG_DN_REV = (1 << 20); %constant int XN_FLAG_FN_LN = (1 << 21); %constant int XN_FLAG_SPC_EQ = (1 << 23); %constant int XN_FLAG_DUMP_UNKNOWN_FIELDS = (1 << 24); %constant int XN_FLAG_FN_ALIGN = (1 << 25); %constant int XN_FLAG_ONELINE =(ASN1_STRFLGS_RFC2253 | \ ASN1_STRFLGS_ESC_QUOTE | \ XN_FLAG_SEP_CPLUS_SPC | \ XN_FLAG_SPC_EQ); %constant int XN_FLAG_MULTILINE = (ASN1_STRFLGS_ESC_CTRL | \ ASN1_STRFLGS_ESC_MSB | \ XN_FLAG_SEP_MULTILINE | \ XN_FLAG_SPC_EQ | \ XN_FLAG_FN_LN | \ XN_FLAG_FN_ALIGN); %constant int XN_FLAG_RFC2253 = (ASN1_STRFLGS_RFC2253 | \ XN_FLAG_SEP_COMMA_PLUS | \ XN_FLAG_DN_REV | \ XN_FLAG_DUMP_UNKNOWN_FIELDS); /* Cribbed from rsa.h. */ %constant int RSA_3 = 0x3L; %constant int RSA_F4 = 0x10001L; %inline %{ static PyObject *_x509_err; void x509_init(PyObject *x509_err) { Py_INCREF(x509_err); _x509_err = x509_err; } %} %threadallow x509_read_pem; %inline %{ X509 *x509_read_pem(BIO *bio) { return PEM_read_bio_X509(bio, NULL, NULL, NULL); } %} %threadallow d2i_x509; %inline %{ X509 *d2i_x509(BIO *bio) { return d2i_X509_bio(bio, NULL); } %} %threadallow d2i_x509_req; %inline %{ X509_REQ *d2i_x509_req(BIO *bio) { return d2i_X509_REQ_bio(bio, NULL); } PyObject *i2d_x509(X509 *x) { int len; PyObject *ret = NULL; unsigned char *buf = NULL; len = i2d_X509(x, &buf); if (len < 0) { PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error())); } else { ret = PyString_FromStringAndSize((char*)buf, len); OPENSSL_free(buf); } return ret; } %} %threadallow x509_req_read_pem; %inline %{ X509_REQ *x509_req_read_pem(BIO *bio) { return PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL); } %} %threadallow x509_req_write_pem; %inline %{ int x509_req_write_pem(BIO *bio, X509_REQ *x) { return PEM_write_bio_X509_REQ(bio, x); } %} %threadallow x509_crl_read_pem; %inline %{ X509_CRL *x509_crl_read_pem(BIO *bio) { return PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL); } /* X509_set_version() is a macro. */ int x509_set_version(X509 *x, long version) { return X509_set_version(x, version); } /* X509_get_version() is a macro. */ long x509_get_version(X509 *x) { return X509_get_version(x); } /* X509_set_notBefore() is a macro. */ int x509_set_not_before(X509 *x, ASN1_UTCTIME *tm) { return X509_set_notBefore(x, tm); } /* X509_get_notBefore() is a macro. */ ASN1_UTCTIME *x509_get_not_before(X509 *x) { return X509_get_notBefore(x); } /* X509_set_notAfter() is a macro. */ int x509_set_not_after(X509 *x, ASN1_UTCTIME *tm) { return X509_set_notAfter(x, tm); } /* X509_get_notAfter() is a macro. */ ASN1_UTCTIME *x509_get_not_after(X509 *x) { return X509_get_notAfter(x); } int x509_sign(X509 *x, EVP_PKEY *pkey, EVP_MD *md) { return X509_sign(x, pkey, md); } /* XXX The first parameter is really ASN1_TIME, does it matter? */ ASN1_TIME *x509_gmtime_adj(ASN1_UTCTIME *s, long adj) { return X509_gmtime_adj(s, adj); } PyObject *x509_name_by_nid(X509_NAME *name, int nid) { void *buf; int len, xlen; PyObject *ret; if ((len = X509_NAME_get_text_by_NID(name, nid, NULL, 0)) == -1) { Py_INCREF(Py_None); return Py_None; } len++; if (!(buf = PyMem_Malloc(len))) { PyErr_SetString(PyExc_MemoryError, "x509_name_by_nid"); return NULL; } xlen = X509_NAME_get_text_by_NID(name, nid, buf, len); ret = PyString_FromStringAndSize(buf, xlen); PyMem_Free(buf); return ret; } int x509_name_set_by_nid(X509_NAME *name, int nid, PyObject *obj) { return X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC, (unsigned char *)PyString_AsString(obj), -1, -1, 0); } /* x509_name_add_entry_by_txt */ int x509_name_add_entry_by_txt(X509_NAME *name, char *field, int type, char *bytes, int len, int loc, int set) { return X509_NAME_add_entry_by_txt(name, field, type, (unsigned char *)bytes, len, loc, set); } PyObject *x509_name_get_der(X509_NAME *name) { i2d_X509_NAME(name, 0); return PyString_FromStringAndSize(name->bytes->data, name->bytes->length); } /* sk_X509_new_null() is a macro returning "STACK_OF(X509) *". */ STACK_OF(X509) *sk_x509_new_null(void) { return sk_X509_new_null(); } /* sk_X509_free() is a macro. */ void sk_x509_free(STACK_OF(X509) *stack) { sk_X509_free(stack); } /* sk_X509_push() is a macro. */ int sk_x509_push(STACK_OF(X509) *stack, X509 *x509) { return sk_X509_push(stack, x509); } /* sk_X509_pop() is a macro. */ X509 *sk_x509_pop(STACK_OF(X509) *stack) { return sk_X509_pop(stack); } int x509_store_load_locations(X509_STORE *store, const char *file) { return X509_STORE_load_locations(store, file, NULL); } int x509_type_check(X509 *x509) { return 1; } int x509_name_type_check(X509_NAME *name) { return 1; } X509_NAME *x509_req_get_subject_name(X509_REQ *x) { return X509_REQ_get_subject_name(x); } long x509_req_get_version(X509_REQ *x) { return X509_REQ_get_version(x); } int x509_req_set_version(X509_REQ *x, long version) { return X509_REQ_set_version(x, version); } int x509_req_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) { return X509_REQ_add_extensions(req, exts); } X509_NAME_ENTRY *x509_name_entry_create_by_txt(X509_NAME_ENTRY **ne, char *field, int type, char *bytes, int len) { return X509_NAME_ENTRY_create_by_txt( ne, field, type, (unsigned char *)bytes, len); } #if OPENSSL_VERSION_NUMBER >= 0x10000000L LHASH_OF(CONF_VALUE) #else LHASH #endif *x509v3_lhash() { return lh_new(NULL, NULL); /* Should probably be lh_CONF_VALUE_new but won't compile. */ } X509V3_CTX * #if OPENSSL_VERSION_NUMBER >= 0x10000000L x509v3_set_conf_lhash(LHASH_OF(CONF_VALUE) * lhash) { #else x509v3_set_conf_lhash(LHASH * lhash) { #endif X509V3_CTX * ctx; if (!(ctx=(X509V3_CTX *)PyMem_Malloc(sizeof(X509V3_CTX)))) { PyErr_SetString(PyExc_MemoryError, "x509v3_set_conf_lhash"); return NULL; } X509V3_set_conf_lhash(ctx, lhash); return ctx; } X509_EXTENSION * #if OPENSSL_VERSION_NUMBER >= 0x10000000L x509v3_ext_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, char *name, char *value) { #else x509v3_ext_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value) { #endif X509_EXTENSION * ext = NULL; ext = X509V3_EXT_conf(conf, ctx, name, value); PyMem_Free(ctx); #if OPENSSL_VERSION_NUMBER >= 0x10000000L lh_CONF_VALUE_free(conf); #else lh_free(conf); #endif return ext; } /* X509_EXTENSION_free() might be a macro, didn't find definition. */ void x509_extension_free(X509_EXTENSION *ext) { X509_EXTENSION_free(ext); } PyObject *x509_extension_get_name(X509_EXTENSION *ext) { PyObject * ext_name; const char * ext_name_str; ext_name_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if (!ext_name_str) { PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error())); return NULL; } ext_name = PyString_FromStringAndSize(ext_name_str, strlen(ext_name_str)); return ext_name; } /* sk_X509_EXTENSION_new_null is a macro. */ STACK_OF(X509_EXTENSION) *sk_x509_extension_new_null(void) { return sk_X509_EXTENSION_new_null(); } /* sk_X509_EXTENSION_free() is a macro. */ void sk_x509_extension_free(STACK_OF(X509_EXTENSION) *stack) { sk_X509_EXTENSION_free(stack); } /* sk_X509_EXTENSION_push() is a macro. */ int sk_x509_extension_push(STACK_OF(X509_EXTENSION) *stack, X509_EXTENSION *x509_ext) { return sk_X509_EXTENSION_push(stack, x509_ext); } /* sk_X509_EXTENSION_pop() is a macro. */ X509_EXTENSION *sk_x509_extension_pop(STACK_OF(X509_EXTENSION) *stack) { return sk_X509_EXTENSION_pop(stack); } /* sk_X509_EXTENSION_num() is a macro. */ int sk_x509_extension_num(STACK_OF(X509_EXTENSION) *stack) { return sk_X509_EXTENSION_num(stack); } /* sk_X509_EXTENSION_value() is a macro. */ X509_EXTENSION *sk_x509_extension_value(STACK_OF(X509_EXTENSION) *stack, int i) { return sk_X509_EXTENSION_value(stack, i); } /* X509_STORE_CTX_get_app_data is a macro. */ void *x509_store_ctx_get_app_data(X509_STORE_CTX *ctx) { return X509_STORE_CTX_get_app_data(ctx); } /*#defines for i2d and d2i types, which are typed differently in openssl-0.9.8 than they are in openssl-0.9.7. This will be picked up by the C preprocessor, not the SWIG preprocessor. Used in the wrapping of ASN1_seq_unpack and ASN1_seq_pack functions. */ #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #define D2ITYPE d2i_of_void * #define I2DTYPE i2d_of_void * #else #define D2ITYPE char *(*)() #define I2DTYPE int (*)() #endif STACK_OF(X509) * make_stack_from_der_sequence(PyObject * pyEncodedString){ STACK_OF(X509) *certs; Py_ssize_t encoded_string_len; char *encoded_string; encoded_string_len = PyString_Size(pyEncodedString); if (encoded_string_len > INT_MAX) { PyErr_SetString(PyExc_ValueError, "object too large"); return NULL; } encoded_string = PyString_AsString(pyEncodedString); if (!encoded_string) { return NULL; } certs = ASN1_seq_unpack_X509((unsigned char *)encoded_string, encoded_string_len, d2i_X509, X509_free ); if (!certs) { PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error())); return NULL; } return certs; } PyObject * get_der_encoding_stack(STACK_OF(X509) *stack){ PyObject * encodedString; unsigned char * encoding; int len; encoding = ASN1_seq_pack_X509(stack, i2d_X509, NULL, &len); if (!encoding) { PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error())); return NULL; } encodedString = PyString_FromStringAndSize((const char *)encoding, len); OPENSSL_free(encoding); return encodedString; } %} /* Free malloc'ed return value for x509_name_oneline */ %typemap(ret) char * { if ($1 != NULL) OPENSSL_free($1); } %inline %{ char *x509_name_oneline(X509_NAME *x) { return X509_NAME_oneline(x, NULL, 0); } %} %typemap(ret) char *; M2Crypto-0.22.6rc4/contrib/0000775000175000017500000000000012613362233015556 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/contrib/README0000664000175000017500000000021512212052026016423 0ustar matejmatej00000000000000This directory contains contributions by users of M2Crypto. Some of these may get folded into the main distribution in time. Thanks guys! M2Crypto-0.22.6rc4/contrib/SimpleX509create.README0000664000175000017500000000017112212052026021426 0ustar matejmatej00000000000000Contributed by Peter Teniz as a demonstration of PKI functionality, also contributed by him. M2Crypto-0.22.6rc4/contrib/SimpleX509create.py0000664000175000017500000001144312607370517021145 0ustar matejmatej00000000000000#!/usr/bin/env python # #vim: ts=4 sw=4 nowrap # """PKI demo by Peter Teniz """ import M2Crypto MBSTRING_FLAG = 0x1000 MBSTRING_ASC = MBSTRING_FLAG | 1 MBSTRING_BMP = MBSTRING_FLAG | 2 class Cert: def __init__ ( self ): self.RsaKey = { 'KeyLength' : 1024, 'PubExponent' : 0x10001, # -> 65537 'keygen_callback' : self.callback } self.KeyPair = None self.PKey = None self.X509Request = None self.X509Certificate = None def callback ( self, *args ): return 'p' def CreatePKey ( self ): self.KeyPair = M2Crypto.RSA.gen_key( self.RsaKey['KeyLength'], self.RsaKey['PubExponent'], self.RsaKey['keygen_callback'] ) #PubKey = M2Crypto.RSA.new_pub_key( self.KeyPair.pub () ) self.KeyPair.save_key( 'KeyPair.pem', cipher='des_ede3_cbc', callback=self.callback ) self.PKey = M2Crypto.EVP.PKey ( md='sha1') self.PKey.assign_rsa ( self.KeyPair ) def CreateX509Request ( self ): # # X509 REQUEST # self.X509Request = M2Crypto.X509.Request () # # subject # X509Name = M2Crypto.X509.X509_Name () X509Name.add_entry_by_txt ( field='C', type=MBSTRING_ASC, entry='austria', len=-1, loc=-1, set=0 ) # country name X509Name.add_entry_by_txt ( field='SP', type=MBSTRING_ASC, entry='kernten', len=-1, loc=-1, set=0 ) # state of province name X509Name.add_entry_by_txt ( field='L', type=MBSTRING_ASC, entry='stgallen', len=-1, loc=-1, set=0 ) # locality name X509Name.add_entry_by_txt ( field='O', type=MBSTRING_ASC, entry='labor', len=-1, loc=-1, set=0 ) # organization name X509Name.add_entry_by_txt ( field='OU', type=MBSTRING_ASC, entry='it-department', len=-1, loc=-1, set=0 ) # organizational unit name X509Name.add_entry_by_txt ( field='CN', type=MBSTRING_ASC, entry='Certificate client', len=-1, loc=-1, set=0 ) # common name X509Name.add_entry_by_txt ( field='Email', type=MBSTRING_ASC, entry='user@localhost', len=-1, loc=-1, set=0 ) # pkcs9 email address X509Name.add_entry_by_txt ( field='emailAddress', type=MBSTRING_ASC, entry='user@localhost', len=-1, loc=-1, set=0 ) # pkcs9 email address self.X509Request.set_subject_name( X509Name ) # # publickey # self.X509Request.set_pubkey ( pkey=self.PKey ) self.X509Request.sign ( pkey=self.PKey, md='sha1' ) #print X509Request.as_text () def CreateX509Certificate ( self ): # # X509 CERTIFICATE # self.X509Certificate = M2Crypto.X509.X509 () # # version # self.X509Certificate.set_version ( 0 ) # # time notBefore # ASN1 = M2Crypto.ASN1.ASN1_UTCTIME () ASN1.set_time ( 500 ) self.X509Certificate.set_not_before( ASN1 ) # # time notAfter # ASN1 = M2Crypto.ASN1.ASN1_UTCTIME () ASN1.set_time ( 500 ) self.X509Certificate.set_not_after( ASN1 ) # # public key # self.X509Certificate.set_pubkey ( pkey=self.PKey ) # # subject # X509Name = self.X509Request.get_subject () #print X509Name.entry_count () #print X509Name.as_text () self.X509Certificate.set_subject_name( X509Name ) # # issuer # X509Name = M2Crypto.X509.X509_Name ( M2Crypto.m2.x509_name_new () ) X509Name.add_entry_by_txt ( field='C', type=MBSTRING_ASC, entry='germany', len=-1, loc=-1, set=0 ) # country name X509Name.add_entry_by_txt ( field='SP', type=MBSTRING_ASC, entry='bavaria', len=-1, loc=-1, set=0 ) # state of province name X509Name.add_entry_by_txt ( field='L', type=MBSTRING_ASC, entry='munich', len=-1, loc=-1, set=0 ) # locality name X509Name.add_entry_by_txt ( field='O', type=MBSTRING_ASC, entry='sbs', len=-1, loc=-1, set=0 ) # organization name X509Name.add_entry_by_txt ( field='OU', type=MBSTRING_ASC, entry='it-department', len=-1, loc=-1, set=0 ) # organizational unit name X509Name.add_entry_by_txt ( field='CN', type=MBSTRING_ASC, entry='Certificate Authority', len=-1, loc=-1, set=0 ) # common name X509Name.add_entry_by_txt ( field='Email', type=MBSTRING_ASC, entry='admin@localhost', len=-1, loc=-1, set=0 ) # pkcs9 email address X509Name.add_entry_by_txt ( field='emailAddress', type=MBSTRING_ASC, entry='admin@localhost', len=-1, loc=-1, set=0 ) # pkcs9 email address #print X509Name.entry_count () #print X509Name.as_text () self.X509Certificate.set_issuer_name( X509Name ) # # signing # self.X509Certificate.sign( pkey=self.PKey, md='sha1' ) print self.X509Certificate.as_text () if __name__ == '__main__': run = Cert () run.CreatePKey () run.CreateX509Request () run.CreateX509Certificate () M2Crypto-0.22.6rc4/contrib/dave.README0000664000175000017500000000530512212052026017346 0ustar matejmatej00000000000000From dave@pythonapocrypha.com Wed Dec 11 07:57:55 2002 Date: Tue, 10 Dec 2002 15:05:26 -0800 (PST) From: Dave Brueck To: ngps@netmemetic.com Subject: M2Crypto problem with asynch sockets Hi and thanks for M2Crypto - great stuff! I wrote an asynchronous socket layer and decided to use M2Crypto to add SSL support to it. Unfortunately, I've found a small problem in _m2crypto_wrap.c - hopefully I'm just not understanding something. The ssl_connect, ssl_read_nbio, etc. calls don't differentiate between SSL_ERROR_WANT_WRITE and SSL_ERROR_WANT_READ when a non-blocking call couldn't finish. But without this information, I don't know whether the socket needs to do more reading or more writing before a subsequent attempt will work without blocking. The demo applications (e.g. echod-async.py) don't seem to care about this but they get around it by simply trying the operation over and over again, which I can't do for performance reasons. Am I missing something? I thought about just calling SSL_get_error when the above calls return None (indicating WANT_READ or WANT_WRITE), but by then the error has already been removed from the SSL error queue. Any help or suggestions would be appreciated. I'd be happy to submit a patch fixing those calls, but by not returning None they would break existing code. Thanks again for M2Crypto though! -Dave From dave@pythonapocrypha.com Fri Dec 13 00:46:39 2002 Date: Thu, 12 Dec 2002 09:52:08 -0800 (PST) From: Dave Brueck To: ngps@netmemetic.com Subject: Re: M2Crypto problem with asynch sockets Hello again, Here is a patch to M2Crypto's _ssl.i that illustrates the fix I had in mind in my previous message. You might not want to use it as is since it changes the error semantics of the affected functions (they now raise an exception that contains the SSL_WANT_READ or SSL_WANT_WRITE flag instead of returning None or whatever), but if you tell me how you'd like it instead then I'd be happy to fix the patch and send it back to you. Just to refresh your memory, this patch fixes the problem where a non-blocking call to accept/connect/etc results in an SSL_NEED_READ/WRITE; currently there's no way for the caller to know _which_ of the two occurred and so it must try again once the socket has become readable OR writeable, instead of waiting specifically for one or the other. For many people this won't matter because their performance requirements are low enough that trying the ssl_accept/etc call again prematurely won't hurt too much, but for servers with lots of connections or high throughput it's much more critical to wait until you know the SSL call has a better chance of success. Thanks! -Dave Brueck M2Crypto-0.22.6rc4/contrib/dave.patch0000664000175000017500000001207112212052026017506 0ustar matejmatej00000000000000--- _ssl.i.orig Tue Sep 18 06:06:34 2001 +++ _ssl.i Thu Dec 12 08:57:39 2002 @@ -238,9 +238,18 @@ return ret; } +void SetWantRWError(int which) { + PyObject *o = Py_BuildValue("(is)", which, + ERR_reason_error_string(ERR_get_error())); + if (o != NULL) { + PyErr_SetObject(_ssl_err, o); + Py_DECREF(o); + } +} + PyObject *ssl_accept(SSL *ssl) { PyObject *obj; - int r, err; + int r, err, which; PyThreadState *_save; if (thread_mode) { @@ -252,14 +261,15 @@ _save = (PyThreadState *)SSL_get_app_data(ssl); PyEval_RestoreThread(_save); } - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: obj = PyInt_FromLong((long)1); break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: - obj = PyInt_FromLong((long)0); + SetWantRWError(which); + obj = NULL; break; case SSL_ERROR_SSL: PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); @@ -281,7 +291,7 @@ PyObject *ssl_connect(SSL *ssl) { PyObject *obj; - int r, err; + int r, err, which; PyThreadState *_save; if (thread_mode) { @@ -293,14 +303,15 @@ _save = (PyThreadState *)SSL_get_app_data(ssl); PyEval_RestoreThread(_save); } - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: obj = PyInt_FromLong((long)1); break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: - obj = PyInt_FromLong((long)0); + SetWantRWError(which); + obj = NULL; break; case SSL_ERROR_SSL: PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); @@ -327,7 +338,7 @@ PyObject *ssl_read(SSL *ssl, int num) { PyObject *obj; void *buf; - int r, err; + int r, err, which; PyThreadState *_save; if (!(buf = PyMem_Malloc(num))) { @@ -343,7 +354,7 @@ _save = (PyThreadState *)SSL_get_app_data(ssl); PyEval_RestoreThread(_save); } - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: buf = PyMem_Realloc(buf, r); @@ -352,8 +363,8 @@ case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: - Py_INCREF(Py_None); - obj = Py_None; + SetWantRWError(which); + obj = NULL; break; case SSL_ERROR_SSL: PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error())); @@ -377,14 +388,14 @@ PyObject *ssl_read_nbio(SSL *ssl, int num) { PyObject *obj; void *buf; - int r, err; + int r, err, which; if (!(buf = PyMem_Malloc(num))) { PyErr_SetString(PyExc_MemoryError, "ssl_read"); return NULL; } r = SSL_read(ssl, buf, num); - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: buf = PyMem_Realloc(buf, r); @@ -392,6 +403,9 @@ break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: + SetWantRWError(which); + obj = NULL; + break; case SSL_ERROR_WANT_X509_LOOKUP: Py_INCREF(Py_None); obj = Py_None; @@ -417,7 +431,7 @@ int ssl_write(SSL *ssl, PyObject *blob) { const void *buf; - int len, r, err; + int len, r, err, which; PyThreadState *_save; #if PYTHON_API_VERSION >= 1009 @@ -440,12 +454,14 @@ _save = (PyThreadState *)SSL_get_app_data(ssl); PyEval_RestoreThread(_save); } - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: return r; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: + SetWantRWError(which); + return -1; case SSL_ERROR_WANT_X509_LOOKUP: return -1; case SSL_ERROR_SSL: @@ -466,7 +482,7 @@ int ssl_write_nbio(SSL *ssl, PyObject *blob) { const void *buf; - int len, r, err; + int len, r, err, which; #if PYTHON_API_VERSION >= 1009 if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) @@ -480,12 +496,14 @@ buf = (const void *)PyString_AsString(blob); #endif r = SSL_write(ssl, buf, len); - switch (SSL_get_error(ssl, r)) { + switch ((which = SSL_get_error(ssl, r))) { case SSL_ERROR_NONE: case SSL_ERROR_ZERO_RETURN: return r; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: + SetWantRWError(which); + return -1; case SSL_ERROR_WANT_X509_LOOKUP: return -1; case SSL_ERROR_SSL: M2Crypto-0.22.6rc4/contrib/dispatcher.README0000664000175000017500000000157612212052026020563 0ustar matejmatej00000000000000Date: Thu, 31 May 2001 17:11:45 +0400 (MSD) From: Ilya Etingof To: ngps@post1.com Cc: Ilya Etingof Subject: Another kind of non-blocking SSL dispatcher --1922505501-409592217-991314705=:1995 Content-Type: TEXT/PLAIN; charset=US-ASCII Hi, Thanks for writing M2Crypto! I've been trying to use the ssl_dispatcher.py though I felt like the bundled version is not absolutely non-blocking. Precisely, it looks like the Connection.connect() method does not handle the case when socket.connect() returns the WOULDBLOCK error. Another suspicious thing is that there seems to be no SSL "want read" and "want write" error return codes of SSL read and write functions. The attached [quick and dirty] code hopefully fixes these two problems. Please, let me know if I'm missing some important clue about all this. Thanks, ilya --1922505501-409592217-991314705=:1995 M2Crypto-0.22.6rc4/contrib/dispatcher.py0000664000175000017500000001202012607370517020260 0ustar matejmatej00000000000000#!/usr/local/bin/python -O """ Implements a [hopefully] non-blocking SSL dispatcher on top of M2Crypto package. Written by Ilya Etingof , 05/2001 """ import asyncore, socket # M2Crypto from M2Crypto import SSL class _nb_connection (SSL.Connection): """Functional equivalent of SSL.Connection class. Facilitates possibly delayed socket.connect() and socket.accept() termination. """ def __init__ (self, ctx, sock): SSL.Connection.__init__ (self, ctx, sock) def connect(self, addr): self._setup_ssl(addr) return self._check_ssl_return(SSL.m2.ssl_connect(self.ssl)) def accept(self, addr): self._setup_ssl(addr) self.accept_ssl() class dispatcher(asyncore.dispatcher_with_send): """A non-blocking SSL dispatcher that mimics the asyncode.dispatcher API. """ def __init__ (self, cert, key, sock=None, serving=None): asyncore.dispatcher_with_send.__init__ (self) self.__serving = serving # XXX if sock: if self.__serving: self.set_socket(sock) else: self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.ctx = SSL.Context('sslv23') self.ctx.set_verify(SSL.verify_none, 10) self.ctx.load_cert(cert, key) self.ctx.set_info_callback() self.ssl = _nb_connection(self.ctx, self.socket) self.__output = '' self.__want_write = 1 # # The following are asyncore overloaded methods # def handle_connect (self): """Initiate SSL connection negotiation """ if self.__serving: self.ssl.accept (self.addr) self.peer = self.ssl.get_peer_cert() self.handle_ssl_accept() else: self.ssl.connect (self.addr) self.handle_ssl_connect() def handle_read(self): """Read user and/or SSL protocol data from SSL connection """ ret = self.ssl._read_nbio() if ret: self.handle_ssl_read(ret) else: # Assume write is wanted self.__want_write = 1 def handle_write(self): """Write pending user and/or SSL protocol data down to SSL connection """ self.__want_write = 0 ret = self.ssl._write_nbio(self.__output) if ret < 0: try: err = SSL.m2.ssl_get_error(self.ssl.ssl, ret) except SSL.SSLError: return if err == SSL.m2.ssl_error_want_write: self.__want_write = 1 else: self.__output = self.__output[ret:] def writable (self): """Indicate that write is desired if here're some user and/or SSL protocol data. """ if self.__output or self.__want_write: return 1 return self.ssl_writable() def handle_close (self): """Shutdown SSL connection. """ self.ssl = None self.ctx = None self.close () self.handle_ssl_close() def handle_error (self, *info): """A trap for asyncore errors """ self.handle_ssl_error(info) # # The following are ssl.dispatcher API # def ssl_connect(self, server): """Initiate SSL connection """ self.connect(server) def ssl_write(self, data): """Write data to SSL connection """ self.__output = self.__output + data def ssl_close(self): """Close SSL connection """ self.handle_close() def handle_ssl_connect(self): """Invoked on SSL connection establishment (whilst in client mode) """ print 'Unhandled handle_ssl_connect()' def handle_ssl_accept(self): """Invoked on SSL connection establishment (whilst in server mode) """ print 'Unhandled handle_ssl_accept()' def handle_ssl_read(self, data): """Invoked on new data arrival to SSL connection """ print 'Unhandled handle_ssl_read event' def handle_ssl_close(self): """Invoked on SSL connection termination """ pass def ssl_writable(self): """Invoked prior to every select() call """ return 0 if __name__=='__main__': """Give it a test run """ class client(dispatcher): """SSL client class """ def __init__ (self, cert, key): dispatcher.__init__(self, cert, key) def handle_ssl_read(self, data): print data self.ssl_write('test write') ssl = client('test.cert', 'test.key') ssl.ssl_connect(('localhost', 7777)) asyncore.loop() M2Crypto-0.22.6rc4/contrib/isaac.README0000664000175000017500000000122712212052026017506 0ustar matejmatej00000000000000This is Isaac Salzberg's application of Mihai Ibanescu's patch (available on SF) that allows HTTPS tunneling through an authenticating proxy. This one's a double whammy: it works with IIS through the authenticating proxy, whereas the one on SF, which uses Python's built-in SSL, doesn't. This code is not folded into the main distribution because: 1. Apparently Mihai is still working on it. 2. Mihai uses Python's built-in SSL. Isaac patched it to use M2Crypto.SSL. The stuff is essentially #ifdef'ed code. 3. I don't have an authenticating proxy nor an IIS server to test against, so I can't clean up the code. Volunteers welcome. ;-) Thanks Isaac. M2Crypto-0.22.6rc4/contrib/isaac.httpslib.py0000664000175000017500000002347512607370517021062 0ustar matejmatej00000000000000"""M2Crypto support for Python 1.5.2 and Python 2.x's httplib. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" import string, sys from httplib import * import SSL if sys.version[0] == '2': if sys.version[:3] in ['2.1', '2.2']: # In 2.1 and above, httplib exports "HTTP" only. from httplib import HTTPConnection, HTTPS_PORT # ISS Added: from httplib import HTTPResponse,FakeSocket class HTTPSConnection(HTTPConnection): """ This class allows communication via SSL using M2Crypto. """ default_port = HTTPS_PORT def __init__(self, host, port=None, **ssl): keys = ssl.keys() try: keys.remove('key_file') except ValueError: pass try: keys.remove('cert_file') except ValueError: pass try: keys.remove('ssl_context') except ValueError: pass if keys: raise IllegalKeywordArgument() try: self.ssl_ctx = ssl['ssl_context'] assert isinstance(self.ssl_ctx, SSL.Context) except KeyError: self.ssl_ctx = SSL.Context('sslv23') HTTPConnection.__init__(self, host, port) def connect(self): self.sock = SSL.Connection(self.ssl_ctx) self.sock.connect((self.host, self.port)) def close(self): # This kludges around line 545 of httplib.py, # which closes the connection in this object; # the connection remains open in the response # object. # # M2Crypto doesn't close-here-keep-open-there, # so, in effect, we don't close until the whole # business is over and gc kicks in. # # Long-running callers beware leakage. # # 05-Jan-2002: This module works with Python 2.2, # but I've not investigated if the above conditions # remain. pass class HTTPS(HTTP): _connection_class = HTTPSConnection def __init__(self, host='', port=None, **ssl): HTTP.__init__(self, host, port) try: self.ssl_ctx = ssl['ssl_context'] except KeyError: self.ssl_ctx = SSL.Context('sslv23') elif sys.version[:3] == '1.5': class HTTPS(HTTP): def __init__(self, ssl_context, host='', port=None): assert isinstance(ssl_context, SSL.Context) self.debuglevel=0 self.file=None self.ssl_ctx=ssl_context if host: self.connect(host, port) def connect(self, host, port=None): # Cribbed from httplib.HTTP. if not port: i = string.find(host, ':') if i >= 0: host, port = host[:i], host[i+1:] try: port = string.atoi(port) except string.atoi_error: raise socket.error, "nonnumeric port" if not port: port = HTTPS_PORT self.sock = SSL.Connection(self.ssl_ctx) if self.debuglevel > 0: print 'connect:', (host, port) self.sock.connect((host, port)) # ISS Added. # From here, starts the proxy patch class HTTPProxyConnection(HTTPConnection): """ This class provides HTTP access through (authenticated) proxies. Example: If the HTTP proxy address is proxy.your.org:8080, an authenticated proxy (one which requires a username/password combination in order to serve requests), one can fetch HTTP documents from 'www.webserver.net', port 81: conn = HTTPProxyConnection('proxy.your.org:8080', 'www.webserver.net', port=81, username='username', password='password') conn.connect() conn.request("HEAD", "/index.html", headers={'X-Custom-Header-1' : 'Value-1'}) resp = conn.getresponse() ... """ def __init__(self, proxy, host, port=None, username=None, password=None): # The connection goes through the proxy HTTPConnection.__init__(self, proxy) # save the proxy connection settings self.__proxy, self.__proxy_port = self.host, self.port # self.host and self.port will point to the real host self._set_hostport(host, port) # save the host and port self._host, self._port = self.host, self.port # Authenticated proxies support self.__username = username self.__password = password def connect(self): """Connect to the host and port specified in __init__ (through a proxy).""" # We are connecting to the proxy, so use the proxy settings self._set_hostport(self.__proxy, self.__proxy_port) HTTPConnection.connect(self) # Restore the real host and port self._set_hostport(self._host, self._port) def putrequest(self, method, url): """Send a request to the server. `method' specifies an HTTP request method, e.g. 'GET'. `url' specifies the object being requested, e.g. '/index.html'. """ # The URL has to include the real host hostname = self._host if self._port != self.default_port: hostname = hostname + ':' + str(self._port) newurl = "http://%s%s" % (hostname, url) # Piggyback on the parent class HTTPConnection.putrequest(self, method, newurl) # Add proxy-specific headers self._add_auth_proxy_header() def _add_auth_proxy_header(self): """Adds an HTTP header for authenticated proxies """ if not self.__username: # No username, so assume not an authenticated proxy return # Authenticated proxy import base64 userpass = "%s:%s" % (self.__username, self.__password) enc_userpass = string.strip(base64.encodestring(userpass)) self.putheader("Proxy-Authorization", "Basic %s" % enc_userpass) class HTTPSProxyResponse(HTTPResponse): """ Replacement class for HTTPResponse Proxy responses (made through SSL) have to keep the connection open after the initial request, since the connection is tunneled to the SSL host with the CONNECT method. """ def begin(self): HTTPResponse.begin(self) self.will_close = 0 class HTTPSProxyConnection(HTTPProxyConnection): """This class provides HTTP access through (authenticated) proxies. Example: If the HTTP proxy address is proxy.your.org:8080, an authenticated proxy (one which requires a username/password combination in order to serve requests), one can fetch HTTP documents from 'www.webserver.net', port 81: conn = HTTPProxyConnection('proxy.your.org:8080', 'www.webserver.net', port=81, username='username', password='password') conn.connect() conn.request("HEAD", "/index.html", headers={'X-Custom-Header-1' : 'Value-1'}) resp = conn.getresponse() ... To avoid dealing with multiple inheritance, this class only inherits from HTTPProxyConnection. """ default_port = HTTPSConnection.default_port def __init__(self, proxy, host, port=None, username=None, password=None, **x509): for key in x509.keys(): if key not in ['cert_file', 'key_file','ssl_context']: raise IllegalKeywordArgument() self.key_file = x509.get('key_file') self.cert_file = x509.get('cert_file') #ISS Added self.ssl_ctx = x509.get('ssl_context') # Piggybacking on HTTPProxyConnection HTTPProxyConnection.__init__(self, proxy, host, port, username, password) def connect(self): """Connect (using SSL) to the host and port specified in __init__ (through a proxy).""" import socket # Set the connection with the proxy HTTPProxyConnection.connect(self) # Use the stock HTTPConnection putrequest host = "%s:%s" % (self._host, self._port) HTTPConnection.putrequest(self, "CONNECT", host) # Add proxy-specific stuff self._add_auth_proxy_header() # And send the request HTTPConnection.endheaders(self) # Save the response class response_class = self.response_class # And replace the response class with our own one, which does not # close the connection self.response_class = HTTPSProxyResponse response = HTTPConnection.getresponse(self) # Restore the response class self.response_class = response_class # Close the response object manually response.close() if response.status != 200: # Close the connection manually self.close() # XXX Find the appropriate error code raise socket.error(1001, response.status, response.value) # NgPS: I haven't read the code recently, but I think it is # reasonable to assume that self.sock is a connected TCP socket at # this point. # Use the real stuff. ;-) if self.ssl_ctx and isinstance(self.ssl_ctx, SSL.Context): self.sock = SSL.Connection(self.ssl_ctx) self.sock.connect((self.host, self.port)) else: # Fake the socket ssl = socket.ssl(self.sock, self.key_file, self.cert_file) self.sock = FakeSocket(self.sock, ssl) if self.debuglevel > 0: print 'socket type:', self.sock def putrequest(self, method, url): """Send a request to the server. `method' specifies an HTTP request method, e.g. 'GET'. `url' specifies the object being requested, e.g. '/index.html'. """ # bypass the parent class's putrequest: use the grandparent's one :-) return HTTPConnection.putrequest(self, method, url) M2Crypto-0.22.6rc4/contrib/m2crypto.spec0000664000175000017500000000255312212052026020205 0ustar matejmatej00000000000000%define name m2crypto %define version 0.06 %define snap snap5 %define release %{snap}.1 %define prefix %{_prefix} Summary: Python crypto library Name: %{name} Version: %{version} Release: %{release} Copyright: tummy.com, ltd. Group: Applications/Crypto Source: %{name}-%{version}-%{snap}.zip Packager: Sean Reifschneider BuildRoot: /var/tmp/%{name}-root Requires: openssl >= 0.9.6a Patch0: m2crypto-makefile.patch BuildPrereq: openssl-devel >= 0.9.6a BuildPrereq: swig >= 1.1p5 %description M2Crypto makes available to the Python programmer the following: RSA, DH, DSA, HMACs, message digests, symmetric ciphers. SSL functionality to implement clients and servers. HTTPS extensions to Python's httplib, urllib, and the eff-bot's xmlrpclib. S/MIME v2. %prep %setup -n %{name}-%{version}-%{snap} %patch0 -p1 %build ( cd swig; make -f Makefile.py1 ) %install [ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT" mkdir -p "$RPM_BUILD_ROOT"/usr/lib/python1.5/site-packages cp -a M2Crypto "$RPM_BUILD_ROOT"/usr/lib/python1.5/site-packages %clean [ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT" %files %defattr(755,root,root) %doc BUGS CHANGES INSTALL LICENCE README STORIES doc demo tests patches /usr/lib/python1.5/site-packages M2Crypto-0.22.6rc4/contrib/smimeplus.README0000664000175000017500000000024512212052026020443 0ustar matejmatej00000000000000Contributed by Bernard Yue: A high level smime interface. "It works for Python 2.2 and above, and requires the email module from Python 2.2.3 to work on Python 2.1. M2Crypto-0.22.6rc4/contrib/smimeplus.py0000664000175000017500000001327212611255457020162 0ustar matejmatej00000000000000import sys, os, tempfile import UserDict from email import Message import M2Crypto if not (sys.version_info[0] >= 2 and sys.version_info[1] >= 2): class object: pass True=1 False=0 class smimeplus(object): def __init__(self, cert, privkey, passphrase, cacert, randfile=None): self.cipher = 'des_ede3_cbc' # XXX make it configable?? self.setsender(cert, privkey, passphrase) self.setcacert(cacert) self.randfile = randfile self.__loadrand() def __passcallback(self, v): """private key passphrase callback function""" return self.passphrase def __loadrand(self): """Load random number file""" if self.randfile: M2Crypto.Rand.load_file(self.randfile, -1) def __saverand(self): """Save random number file""" if self.randfile: M2Crypto.Rand.save_file(self.randfile) def __gettext(self, msg): """Return a string representation of 'msg'""" _data = '' if isinstance(msg, Message.Message): for _p in msg.walk(): _data = _data + _p.as_string() else: _data = str(msg) return _data def __pack(self, msg): """Convert 'msg' to string and put it into an memory buffer for openssl operation""" return M2Crypto.BIO.MemoryBuffer(self.__gettext(msg)) def setsender(self, cert=None, privkey=None, passphrase=None): if cert: self.cert = cert if privkey: self.key = privkey if passphrase: self.passphrase = passphrase def setcacert(self, cacert): self.cacert = cacert def sign(self, msg): """Sign a message""" _sender = M2Crypto.SMIME.SMIME() _sender.load_key_bio(self.__pack(self.key), self.__pack(self.cert), callback=self.__passcallback) _signed = _sender.sign(self.__pack(msg), M2Crypto.SMIME.PKCS7_DETACHED) _out = self.__pack(None) _sender.write(_out, _signed, self.__pack(msg)) return _out.read() def verify(self, smsg, scert): """Verify to see if 'smsg' was signed by 'scert', and scert was issued by cacert of this object. Return message signed if success, None otherwise""" # Load signer's cert. _x509 = M2Crypto.X509.load_cert_bio(self.__pack(scert)) _stack = M2Crypto.X509.X509_Stack() _stack.push(_x509) # Load CA cert. _tmpfile = persistdata(self.cacert) _store = M2Crypto.X509.X509_Store() _store.load_info(_tmpfile) os.remove(_tmpfile) # prepare SMIME object _sender = M2Crypto.SMIME.SMIME() _sender.set_x509_stack(_stack) _sender.set_x509_store(_store) # Load signed message, verify it, and return result _p7, _data = M2Crypto.SMIME.smime_load_pkcs7_bio(self.__pack(smsg)) try: return _sender.verify(_p7, _data, flags=M2Crypto.SMIME.PKCS7_SIGNED) except M2Crypto.SMIME.SMIME_Error, _msg: return None def encrypt(self, rcert, msg): # Instantiate an SMIME object. _sender = M2Crypto.SMIME.SMIME() # Load target cert to encrypt to. _x509 = M2Crypto.X509.load_cert_bio(self.__pack(rcert)) _stack = M2Crypto.X509.X509_Stack() _stack.push(_x509) _sender.set_x509_stack(_stack) _sender.set_cipher(M2Crypto.SMIME.Cipher(self.cipher)) # Encrypt the buffer. _buf = self.__pack(self.__gettext(msg)) _p7 = _sender.encrypt(_buf) # Output p7 in mail-friendly format. _out = self.__pack('') _sender.write(_out, _p7) # Save the PRNG's state. self.__saverand() return _out.read() def decrypt(self, emsg): """decrypt 'msg'. Return decrypt message if success, None otherwise""" # Load private key and cert. _sender = M2Crypto.SMIME.SMIME() _sender.load_key_bio(self.__pack(self.key), self.__pack(self.cert), callback=self.__passcallback) # Load the encrypted data. _p7, _data = M2Crypto.SMIME.smime_load_pkcs7_bio(self.__pack(emsg)) # Decrypt p7. try: return _sender.decrypt(_p7) except M2Crypto.SMIME.SMIME_Error, _msg: return None def addHeader(self, rcert, content, subject=''): """Add To, From, Subject Header to 'content'""" _scert = M2Crypto.X509.load_cert_bio(self.__pack(self.cert)) _scertsubj = X509_Subject(str(_scert.get_subject())) _rcert = M2Crypto.X509.load_cert_bio(self.__pack(rcert)) _rcertsubj = X509_Subject(str(_rcert.get_subject())) _out = 'From: "%(CN)s" <%(emailAddress)s>\n' % _scertsubj _out = _out + 'To: "%(CN)s" <%(emailAddress)s>\n' % _rcertsubj _out = _out + 'Subject: %s\n' % subject _out = _out + content return _out class X509_Subject(UserDict.UserDict): # This class needed to be rewritten or merge with X509_Name def __init__(self, substr): UserDict.UserDict.__init__(self) try: _data = substr.strip().split('/') except AttributeError, _msg: pass else: for _i in _data: try: _k, _v = _i.split('=') self[_k] = _v except ValueError, _msg: pass def persistdata(data, file=None, isbinary=False): if not file: file = tempfile.mktemp() if isbinary: _flag = 'wb' else: _flag = 'w' _fh = open(file, _flag) _fh.write(data) _fh.close() return file M2Crypto-0.22.6rc4/demo/0000775000175000017500000000000012613362233015042 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/CipherSaber/0000775000175000017500000000000012613362233017231 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/CipherSaber/CipherSaber.py0000664000175000017500000000250012607370517021776 0ustar matejmatej00000000000000#!/usr/bin/env python """CipherSaber, http://ciphersaber.gurus.com. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # XXX getopt handling has bugs. from M2Crypto import RC4, Rand import getopt, getpass, sys class argerr(Exception): pass cmd = -1 inf = sys.stdin outf = sys.stdout optlist, optarg = getopt.getopt(sys.argv[1:], 'dei:o:') for opt in optlist: if '-d' in opt: cmd = cmd + 1 elif '-e' in opt: cmd = cmd + 2 elif '-i' in opt: i = opt[1] if i == '-': inf = sys.stdin else: inf = open(i, 'rb') elif '-o' in opt: o = opt[1] if o == '-': outf = sys.stdout else: outf = open(o, 'wb') if cmd < 0: raise argerr, "either -d or -e" if cmd > 1: raise argerr, "either -d or -e, not both" if cmd == 0: iv = inf.read(10) pp = getpass.getpass('Enter decryption passphrase: ') else: iv = Rand.rand_bytes(10) outf.write(iv) pp = getpass.getpass('Enter encryption passphrase: ') pp2 = getpass.getpass('Enter passphrase again: ') if pp != pp2: raise SystemExit, 'passphrase mismatch, I\'m outta here...' ci = RC4.RC4(pp + iv) del pp, iv while 1: buf = inf.read() if not buf: break outf.write(ci.update(buf)) outf.write(ci.final()) M2Crypto-0.22.6rc4/demo/CipherSaber/cstest1.cs10000664000175000017500000000005012605232411021215 0ustar matejmatej00000000000000om g0wt縅CVH|OO_M2Crypto-0.22.6rc4/demo/Zope/0000775000175000017500000000000012613362233015757 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/ZServer/0000775000175000017500000000000012613362233017357 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/ZServer/medusa/0000775000175000017500000000000012613362233020635 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/ZServer/medusa/ftps_server.py0000664000175000017500000003576612607370517023601 0ustar matejmatej00000000000000"""An FTP/TLS server built on Medusa's ftp_server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # Python import socket, string, sys, time # Medusa from counter import counter import asynchat, asyncore, ftp_server, logger # M2Crypto from M2Crypto import SSL VERSION_STRING='0.09' class ftp_tls_channel(ftp_server.ftp_channel): """FTP/TLS server channel for Medusa.""" def __init__(self, server, ssl_ctx, conn, addr): """Initialise the channel.""" self.ssl_ctx = ssl_ctx self.server = server self.current_mode = 'a' self.addr = addr asynchat.async_chat.__init__(self, conn) self.set_terminator('\r\n') self.client_addr = (addr[0], 21) self.client_dc = None self.in_buffer = '' self.closing = 0 self.passive_acceptor = None self.passive_connection = None self.filesystem = None self.authorized = 0 self._ssl_accepting = 0 self._ssl_accepted = 0 self._pbsz = None self._prot = None resp = '220 %s M2Crypto (Medusa) FTP/TLS server v%s ready.' self.respond(resp % (self.server.hostname, VERSION_STRING)) def writable(self): return self._ssl_accepting or self._ssl_accepted def handle_read(self): """Handle a read event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_read(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def handle_write(self): """Handle a write event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_write(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' def found_terminator(self): """Dispatch the FTP command.""" line = self.in_buffer if not len(line): return sp = string.find(line, ' ') if sp != -1: line = [line[:sp], line[sp+1:]] else: line = [line] command = string.lower(line[0]) if string.find(command, 'stor') != -1: while command and command[0] not in string.letters: command = command[1:] func_name = 'cmd_%s' % command if command != 'pass': self.log('<== %s' % repr(self.in_buffer)[1:-1]) else: self.log('<== %s' % line[0]+' ') self.in_buffer = '' if not hasattr(self, func_name): self.command_not_understood(line[0]) return func = getattr(self, func_name) if not self.check_command_authorization(command): self.command_not_authorized(command) else: try: result = apply(func, (line,)) except: self.server.total_exceptions.increment() (file, func, line), t, v, tbinfo = asyncore.compact_traceback() if self.client_dc: try: self.client_dc_close() except: pass resp = '451 Server error: %s, %s: file %s line: %s' self.respond(resp % (t, v, file, line)) def make_xmit_channel(self): """Create a connection for sending data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_xmit_channel(self, conn, self.ssl_ctx, addr) else: cdc = ftp_server.xmit_channel(self, addr) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, None) else: cdc = ftp_server.xmit_channel(self) else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, self.client_addr) else: cdc = ftp_server.xmit_channel(self, self.client_addr) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) if self.bind_local_minus_one: cdc.bind(('', self.server.port - 1)) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def make_recv_channel(self, fd): """Create a connection for receiving data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_recv_channel(self, conn, self.ssl_ctx, addr, fd) else: cdc = ftp_server.recv_channel(self, addr, fd) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, None, fd) else: cdc = ftp_server.recv_channel(self, None, fd) else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, self._prot, self.client_addr, fd) else: cdc = ftp_server.recv_channel(self, self.client_addr, fd) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def cmd_auth(self, line): """Prepare for TLS operation.""" # XXX Handle variations. if line[1] != 'TLS': self.command_not_understood (string.join(line)) else: self.respond('234 AUTH TLS successful') self._ssl_accepting = 1 self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.addr) self.socket.setup_ssl() self.socket.set_accept_state() self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 def cmd_pbsz(self, line): """Negotiate size of buffer for secure data transfer. For FTP/TLS the only valid value for the parameter is '0'; any other value is accepted but ignored.""" if not (self._ssl_accepting or self._ssl_accepted): return self.respond('503 AUTH TLS must be issued prior to PBSZ') self._pbsz = 1 self.respond('200 PBSZ=0 successful.') def cmd_prot(self, line): """Negotiate the security level of the data connection.""" if self._pbsz is None: return self.respond('503 PBSZ must be issued prior to PROT') if line[1] == 'C': self.respond('200 Protection set to Clear') self._pbsz = None self._prot = None elif line[1] == 'P': self.respond('200 Protection set to Private') self._prot = 1 elif line[1] in ('S', 'E'): self.respond('536 PROT %s unsupported' % line[1]) else: self.respond('504 PROT %s unsupported' % line[1]) class ftp_tls_server(ftp_server.ftp_server): """FTP/TLS server for Medusa.""" SERVER_IDENT = 'M2Crypto FTP/TLS Server (v%s)' % VERSION_STRING ftp_channel_class = ftp_tls_channel def __init__(self, authz, ssl_ctx, host=None, ip='', port=21, resolver=None, log_obj=None): """Initialise the server.""" self.ssl_ctx = ssl_ctx self.ip = ip self.port = port self.authorizer = authz if host is None: self.hostname = socket.gethostname() else: self.hostname = host self.total_sessions = counter() self.closed_sessions = counter() self.total_files_out = counter() self.total_files_in = counter() self.total_bytes_out = counter() self.total_bytes_in = counter() self.total_exceptions = counter() asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((self.ip, self.port)) self.listen(5) if log_obj is None: log_obj = sys.stdout if resolver: self.logger = logger.resolving_logger(resolver, log_obj) else: self.logger = logger.unresolving_logger(logger.file_logger(sys.stdout)) l = 'M2Crypto (Medusa) FTP/TLS server started at %s\n\tAuthz: %s\n\tHostname: %s\n\tPort: %d' self.log_info(l % (time.ctime(time.time()), repr(self.authorizer), self.hostname, self.port)) def handle_accept(self): """Accept a socket and dispatch a channel to handle it.""" conn, addr = self.accept() self.total_sessions.increment() self.log_info('Connection from %s:%d' % addr) self.ftp_channel_class(self, self.ssl_ctx, conn, addr) class nbio_ftp_tls_actor: """TLS protocol negotiation mixin for FTP/TLS.""" def tls_init(self, sock, ssl_ctx, client_addr): """Perform TLS protocol negotiation.""" self.ssl_ctx = ssl_ctx self.client_addr = client_addr self._ssl_handshaking = 1 self._ssl_handshake_ok = 0 if sock: self.socket = SSL.Connection(self.ssl_ctx, sock) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() # else the client hasn't connected yet; when that happens, # handle_connect() will be triggered. def tls_neg_ok(self): """Return status of TLS protocol negotiation.""" if self._ssl_handshaking: self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 return self._ssl_handshake_ok def handle_connect(self): """Handle a data connection that occurs after this instance came into being. When this handler is triggered, self.socket has been created and refers to the underlying connected socket.""" self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' class tls_xmit_channel(nbio_ftp_tls_actor, ftp_server.xmit_channel): """TLS driver for a send-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr=None): """Initialise the driver.""" ftp_server.xmit_channel.__init__(self, channel, client_addr) self.tls_init(conn, ssl_ctx, client_addr) def readable(self): """This channel is readable iff TLS negotiation is in progress. (Which implies a connected channel, of course.)""" if not self.connected: return 0 else: return self._ssl_handshaking def writable(self): """This channel is writable iff TLS negotiation is in progress or the application has data to send.""" if self._ssl_handshaking: return 1 else: return ftp_server.xmit_channel.writable(self) def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_write(self) class tls_recv_channel(nbio_ftp_tls_actor, ftp_server.recv_channel): """TLS driver for a receive-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr, fd): """Initialise the driver.""" ftp_server.recv_channel.__init__(self, channel, client_addr, fd) self.tls_init(conn, ssl_ctx, client_addr) def writable(self): """This channel is writable iff TLS negotiation is in progress.""" return self._ssl_handshaking def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_write(self) M2Crypto-0.22.6rc4/demo/Zope/ZServer/medusa/https_server.py0000664000175000017500000000503512607370517023751 0ustar matejmatej00000000000000#!/usr/bin/env python """A https server built on Medusa's http_server. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import asynchat, asyncore, http_server, socket, sys from M2Crypto import SSL, version VERSION_STRING=version class https_channel(http_server.http_channel): ac_in_buffer_size = 1 << 16 def __init__(self, server, conn, addr): http_server.http_channel.__init__(self, server, conn, addr) def send(self, data): try: result = self.socket._write_nbio(data) if result <= 0: return 0 else: self.server.bytes_out.increment(result) return result except SSL.SSLError, why: self.close() self.log_info('send: closing channel %s %s' % (repr(self), why)) return 0 def recv(self, buffer_size): try: result = self.socket._read_nbio(buffer_size) if result is None: return '' elif result == '': self.close() return '' else: self.server.bytes_in.increment(len(result)) return result except SSL.SSLError, why: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), why)) return '' class https_server(http_server.http_server): SERVER_IDENT='M2Crypto HTTPS Server (v%s)' % VERSION_STRING channel_class=https_channel def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): http_server.http_server.__init__(self, ip, port, resolver, logger_object) self.ssl_ctx=ssl_ctx def handle_accept(self): # Cribbed from http_server. self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. sys.stderr.write ('warning: server accept() threw an exception\n') return # Turn the vanilla socket into an SSL connection. try: ssl_conn=SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr) except SSL.SSLError: pass def writeable(self): return 0 M2Crypto-0.22.6rc4/demo/Zope/ZServer/HTTPS_Server.py0000664000175000017500000001431212607370517022171 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2000-2004, Ng Pheng Siong. All Rights Reserved. # This file is derived from Zope's ZServer/HTTPServer.py. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """ Medusa HTTPS server for Zope changes from Medusa's http_server: Request Threads -- Requests are processed by threads from a thread pool. Output Handling -- Output is pushed directly into the producer fifo by the request-handling thread. The HTTP server does not do any post-processing such as chunking. Pipelineable -- This is needed for protocols such as HTTP/1.1 in which mutiple requests come in on the same channel, before responses are sent back. When requests are pipelined, the client doesn't wait for the response before sending another request. The server must ensure that responses are sent back in the same order as requests are received. changes from Zope's HTTP server: Well, this is a *HTTPS* server :) X.509 certificate-based authentication -- When this is in force, zhttps_handler, a subclass of zhttp_handler, is installed. The https server is configured to request an X.509 certificate from the client. When the request reaches zhttps_handler, it sets REMOTE_USER to the client's subject distinguished name (DN) from the certificate. Zope's REMOTE_USER machinery takes care of the rest, e.g., in conjunction with the RemoteUserFolder product. """ import sys, time, types from PubCore import handle from medusa import asyncore from ZServer import CONNECTION_LIMIT, ZOPE_VERSION from HTTPServer import zhttp_handler from zLOG import register_subsystem from M2Crypto import SSL, version from medusa.https_server import https_server, https_channel from medusa.asyncore import dispatcher ZSERVER_SSL_VERSION=version register_subsystem('ZServer HTTPS_Server') class zhttps0_handler(zhttp_handler): "zhttps0 handler - sets SSL request headers a la mod_ssl" def __init__ (self, module, uri_base=None, env=None): zhttp_handler.__init__(self, module, uri_base, env) def get_environment(self, request): env = zhttp_handler.get_environment(self, request) env['SSL_CIPHER'] = request.channel.get_cipher() return env class zhttps_handler(zhttps0_handler): "zhttps handler - sets REMOTE_USER to user's X.509 certificate Subject DN" def __init__ (self, module, uri_base=None, env=None): zhttps0_handler.__init__(self, module, uri_base, env) def get_environment(self, request): env = zhttps0_handler.get_environment(self, request) peer = request.channel.get_peer_cert() if peer is not None: env['REMOTE_USER'] = str(peer.get_subject()) return env class zhttps_channel(https_channel): "https channel" closed=0 zombie_timeout=100*60 # 100 minutes def __init__(self, server, conn, addr): https_channel.__init__(self, server, conn, addr) self.queue=[] self.working=0 self.peer_found=0 def push(self, producer, send=1): # this is thread-safe when send is false # note, that strings are not wrapped in # producers by default if self.closed: return self.producer_fifo.push(producer) if send: self.initiate_send() push_with_producer=push def work(self): "try to handle a request" if not self.working: if self.queue: self.working=1 try: module_name, request, response=self.queue.pop(0) except: return handle(module_name, request, response) def close(self): self.closed=1 while self.queue: self.queue.pop() if self.current_request is not None: self.current_request.channel=None # break circ refs self.current_request=None while self.producer_fifo: p=self.producer_fifo.first() if p is not None and type(p) != types.StringType: p.more() # free up resources held by producer self.producer_fifo.pop() self.del_channel() #self.socket.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN) self.socket.close() def done(self): "Called when a publishing request is finished" self.working=0 self.work() def kill_zombies(self): now = int (time.time()) for channel in asyncore.socket_map.values(): if channel.__class__ == self.__class__: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() class zhttps_server(https_server): "https server" SERVER_IDENT='ZServerSSL/%s' % (ZSERVER_SSL_VERSION,) channel_class = zhttps_channel shutup = 0 def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): self.shutup = 1 https_server.__init__(self, ip, port, ssl_ctx, resolver, logger_object) self.ssl_ctx = ssl_ctx self.shutup = 0 self.log_info('(%s) HTTPS server started at %s\n' '\tHostname: %s\n\tPort: %d' % ( self.SERVER_IDENT, time.ctime(time.time()), self.server_name, self.server_port )) def log_info(self, message, type='info'): if self.shutup: return dispatcher.log_info(self, message, type) def readable(self): return self.accepting and \ len(asyncore.socket_map) < CONNECTION_LIMIT def listen(self, num): # override asyncore limits for nt's listen queue size self.accepting = 1 return self.socket.listen (num) M2Crypto-0.22.6rc4/demo/Zope/ZServer/__init__.py0000664000175000017500000000612212605232411021464 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## import sys, os # HACKERY to get around asyncore issues. This ought to go away! We're # currently using the Python 2.2 asyncore bundled with Zope to override # brokenness in the Python 2.1 version. We need to do some funny business # to make this work, as a 2.2-ism crept into the asyncore code. if os.name == 'posix': import fcntl if not hasattr(fcntl, 'F_GETFL'): import FCNTL fcntl.F_GETFL = FCNTL.F_GETFL fcntl.F_SETFL = FCNTL.F_SETFL from medusa import asyncore sys.modules['asyncore'] = asyncore from medusa.test import max_sockets CONNECTION_LIMIT=max_sockets.max_select_sockets() ZSERVER_VERSION='1.1b1' import App.FindHomes try: import App.version_txt ZOPE_VERSION=App.version_txt.version_txt() except: ZOPE_VERSION='experimental' # Try to poke zLOG default logging into asyncore # XXX We should probably should do a better job of this, # however that would mean that ZServer required zLOG. try: from zLOG import LOG, register_subsystem, BLATHER, INFO, WARNING, ERROR register_subsystem('ZServer') severity={'info':INFO, 'warning':WARNING, 'error': ERROR} def log_info(self, message, type='info'): if message[:14]=='adding channel' or \ message[:15]=='closing channel' or \ message == 'Computing default hostname': LOG('ZServer', BLATHER, message) else: LOG('ZServer', severity[type], message) import asyncore asyncore.dispatcher.log_info=log_info except: pass # A routine to try to arrange for request sockets to be closed # on exec. This makes it easier for folks who spawn long running # processes from Zope code. Thanks to Dieter Maurer for this. try: import fcntl try: from fcntl import F_SETFD, FD_CLOEXEC except ImportError: from FCNTL import F_SETFD, FD_CLOEXEC def requestCloseOnExec(sock): try: fcntl.fcntl(sock.fileno(), F_SETFD, FD_CLOEXEC) except: pass except (ImportError, AttributeError): def requestCloseOnExec(sock): pass import asyncore from medusa import resolver, logger from HTTPServer import zhttp_server, zhttp_handler from HTTPS_Server import zhttps_server, zhttps0_handler, zhttps_handler from PCGIServer import PCGIServer from FCGIServer import FCGIServer from FTPServer import FTPServer from PubCore import setNumberOfThreads from medusa.monitor import secure_monitor_server # override the service name in logger.syslog_logger logger.syslog_logger.svc_name='ZServer' M2Crypto-0.22.6rc4/demo/Zope/lib/0000775000175000017500000000000012613362233016525 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/0000775000175000017500000000000012613362233020046 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/0000775000175000017500000000000012613362233021651 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/0000775000175000017500000000000012613362233024024 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/GuardedFile.py0000664000175000017500000000336612607370517026570 0ustar matejmatej00000000000000"""GuardedFile.GuardedFile Copyright (c) 2000-2003 Ng Pheng Siong. All rights reserved. This software is released under the ZPL. Usual disclaimers apply.""" __version__ = '1.3' from AccessControl import getSecurityManager from Globals import HTMLFile, MessageDialog from OFS.Image import File, cookId manage_addForm = HTMLFile('add', globals(),Kind='GuardedFile',kind='GuardedFile') def manage_addGuardedFile(self, id, file, title='', precondition='', content_type='', REQUEST=None): """ Add a new GuardedFile object. Creates a new GuardedFile object 'id' with the content of 'file'. """ # Object creation stuff, cribbed from OFS.Image.manage_addFile(). id, title = cookId(id, title, file) self = self.this() self._setObject(id, GuardedFile(id, title, '', content_type, precondition)) obj = self._getOb(id) obj.manage_upload(file) # Unset permission acquisition. obj.manage_acquiredPermissions() # Create a proxy role and set a specific permission for it. proxy_role = "proxy_for_%s" % id self._addRole(proxy_role) obj.manage_role(proxy_role, ['View']) uname = getSecurityManager().getUser().getUserName() self.manage_addLocalRoles(uname, (proxy_role,), REQUEST) # Feedback. if REQUEST: return MessageDialog( title ='Success!', message='GuardedFile "%s" has been created.' % id, action ='manage_main') class GuardedFile(File): """A File object accessible by proxy only.""" meta_type = "GuardedFile" def manage_beforeDelete(self, item, container): """Delete self's proxy role.""" role = "proxy_for_%s" % self.__name__ container._delRoles([role], None) self.manage_delLocalRoles(self.users_with_local_role(role)) M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/README.txt0000664000175000017500000000065412605232411025522 0ustar matejmatej00000000000000GuardedFile A GuardedFile is a Zope File that is accessible *by proxy* only. When a GuardedFile is created, all acquired permissions are unset. A proxy role is created in its container with the sole permission "View". When the GuardedFile is deleted, its associated proxy role is also removed. In all other aspects a GuardedFile behaves exactly like a File. $Id$ $Revision: 1.2 $ M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/TODO.txt0000664000175000017500000000001112605232411025315 0ustar matejmatej000000000000001. Icon. M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/__init__.py0000664000175000017500000000124412605232411026131 0ustar matejmatej00000000000000"""GuardedFile.__init__ Copyright (c) 2000 Ng Pheng Siong. All rights reserved. This software is released under the ZPL.""" __version__ = '1.1' import GuardedFile def initialize(context): try: context.registerClass( GuardedFile.GuardedFile, constructors=(GuardedFile.manage_addForm, GuardedFile.manage_addGuardedFile) #icon='folder.gif' ) context.registerBaseClass(GuardedFile.GuardedFile) except: import sys, traceback, string type, val, tb = sys.exc_info() sys.stderr.write(string.join( traceback.format_exception(type, val, tb),'')) del type, val, tb M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/add.dtml0000664000175000017500000000350512605232411025434 0ustar matejmatej00000000000000

A GuardedFile is a Zope File that is accessible by proxy only.

When a GuardedFile is created, all acquired permissions are unset. A proxy role is created in its container with the sole permission "View".

When the GuardedFile is deleted, its associated proxy role is also removed.

In all other aspects a GuardedFile behaves exactly like a File.

You can create a new using the form below. Select a file from your local computer by clicking the Browse button. The file you select will be uploaded to Zope as a .

Id
Title
File
M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/refresh.txt0000664000175000017500000000000012605232411026204 0ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/GuardedFile/version.txt0000664000175000017500000000002212605232411026237 0ustar matejmatej00000000000000GuardedFile-1-1-0 M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/ZSmime/0000775000175000017500000000000012613362233023055 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/ZSmime/README.txt0000664000175000017500000000127212605232411024550 0ustar matejmatej00000000000000ZSmime enables Zope to generate S/MIME-signed/encrypted messages. ZSmime is useful where Zope accepts confidential information over the web, e.g., credit card information, Swiss bank account instructions, etc. Such information can be protected by ZSmime and relayed off-site immediately. This reduces the value of the information carried on-site and in turn reduces the effect of a successful attack against the site. Even if the S/MIME-protected information remains on-site, it is now encrypted - this introduces additional cost in defeating the protection and may mitigate the impact of a successful site penetration. ZSmime adds a DTML tag "dtml-smime" to Zope. $Id$ $Revision: 1.1 $ M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/ZSmime/SmimeTag.py0000664000175000017500000000563012607370517025150 0ustar matejmatej00000000000000"""ZSmime.SmimeTag Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved. This software is released under the ZPL. Usual disclaimers apply.""" __version__ = '1.2' # Zope tag stuff. from DocumentTemplate.DT_String import String from DocumentTemplate.DT_Util import * from DocumentTemplate.DT_Var import Var, Call # M2Crypto. from M2Crypto import BIO, SMIME, X509 SmimeError = "SmimeTag Error" class SmimeTag: """""" name = 'smime' blockContinuations = () def __init__(self, blocks): tname, args, section = blocks[0] self.section = section args = parse_params(args, signer=None, recipients=None) has_key = args.has_key if has_key('signer'): self.signer = args['signer'] try: Call(self.signer) except ParseError: raise SmimeError, ('Invalid parameter "signer".') else: raise SmimeError, ('The parameter "signer" was not specified in tag.') if has_key('recipients'): self.recipients = args['recipients'] try: Call(self.recipients) except ParseError: raise SmimeError, ('Invalid parameter "recipients".') else: raise SmimeError, ('The parameter "recipients" was not specified in tag.') def render(self, md): # Render the dtml block. data = render_blocks(self.section.blocks, md) data_bio = BIO.MemoryBuffer(data) # Prepare to S/MIME. s = SMIME.SMIME() # Render the signer key, load into BIO. try: signer = Var(self.signer).render(md) except ParseError: raise SmimeError, ('Invalid parameter "signer".') signer_key_bio = BIO.MemoryBuffer(signer) signer_cert_bio = BIO.MemoryBuffer(signer) # XXX Kludge. # Sign the data. s.load_key_bio(signer_key_bio, signer_cert_bio) p7 = s.sign(data_bio, flags=SMIME.PKCS7_TEXT) # Recreate coz sign() has consumed the MemoryBuffer. # May be cheaper to seek to start. data_bio = BIO.MemoryBuffer(data) # Render recipients, load into BIO. try: recip = Var(self.recipients).render(md) except ParseError: raise SmimeError, ('Invalid parameter "recipients".') recip_bio = BIO.MemoryBuffer(recip) # Load recipient certificates. sk = X509.X509_Stack() sk.push(X509.load_cert_bio(recip_bio)) s.set_x509_stack(sk) # Set a cipher. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Encrypt. tmp_bio = BIO.MemoryBuffer() s.write(tmp_bio, p7) p7 = s.encrypt(tmp_bio) # Finally, return the now signed/encrypted PKCS7. out = BIO.MemoryBuffer() s.write(out, p7) return out.getvalue() __call__ = render String.commands['smime'] = SmimeTag M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/ZSmime/__init__.py0000664000175000017500000000026612605232411025165 0ustar matejmatej00000000000000"""ZSmime.__init__ Copyright (c) 2000 Ng Pheng Siong. All rights reserved. This software is released under the ZPL. Usual disclaimers apply.""" __version__='1.1' import SmimeTag M2Crypto-0.22.6rc4/demo/Zope/lib/python/Products/ZSmime/version.txt0000664000175000017500000000001512605232411025272 0ustar matejmatej00000000000000ZSmime-1-0-1 M2Crypto-0.22.6rc4/demo/Zope/utilities/0000775000175000017500000000000012613362233017772 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope/utilities/x509_user.py0000664000175000017500000000351512607370517022122 0ustar matejmatej00000000000000#!/usr/bin/env python """ This is a very simple program to manage the access_x509 database. The overriding goal is program portability, hence its use of 'anydbm'. Invoke it thusly: x509_user.py -u [ -x ] [ -f ] is the Zope username; it must be present. is the X.509 certificate's subject distinguished name to associate with the user. If it is present, the association is created or updated. If it is absent, the association is removed. defaults to 'access_x509'. (I told you this is a dumb program.) To read the subject distinguished name from the certificate 'client.pem', invoke 'openssl' thusly: openssl x509 -subject -noout -in client.pem This produces the output: subject=/C=SG/O=M2Crypto Client/CN=M2Crypto Client/Email=ngps@post1.com Next, invoke this tool: x509_user.py -u superuser \\ -f "/C=SG/O=M2Crypto Client/CN=M2Crypto Client/Email=ngps@post1.com" This associates the user who owns client.pem to the Zope "superuser". Copyright (c) 2000 Ng Pheng Siong. This program is released under the ZPL. """ import anydbm, getopt, sys x509_db = 'access_x509' username = subject_dn = None argerr='Usage' optlist, optarg=getopt.getopt(sys.argv[1:], 'f:u:x:') # ;-) for opt in optlist: if '-f' in opt: x509_db = opt[1] elif '-u' in opt: username = opt[1] elif '-x' in opt: subject_dn = opt[1] if username is None: raise argerr, '\n' + __doc__ db = anydbm.open(x509_db, 'cw') if subject_dn is None: # Remove the association... try: subject_dn = db[username] del db[subject_dn] del db[username] except: pass else: # Create/update the association. db[subject_dn] = username db[username] = subject_dn db.close() M2Crypto-0.22.6rc4/demo/Zope/ca.pem0000664000175000017500000000230412605232411017037 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/Zope/dh1024.pem0000664000175000017500000000036512605232411017363 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/Zope/server.pem0000664000175000017500000000411012605232411017757 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/Zope/starts0000664000175000017500000000111012605232411017206 0ustar matejmatej00000000000000#!/bin/sh umask 077 reldir=`dirname $0` cwd=`cd $reldir; pwd` # Zope's event logger is controlled by the "EVENT_LOG_FILE" environment # variable. If you don't have a "EVENT_LOG_FILE" environment variable # (or its older alias "STUPID_LOG_FILE") set, Zope will log to the standard # output. For more information on EVENT_LOG_FILE, see doc/ENVIRONMENT.txt. ZLOGFILE=$EVENT_LOG_FILE if [ -z "$ZLOGFILE" ]; then ZLOGFILE=$STUPID_LOG_FILE fi if [ -z "$ZLOGFILE" ]; then EVENT_LOG_FILE="" export EVENT_LOG_FILE fi exec /usr/local/bin/python2.1 $cwd/z2s.py -D "$@" M2Crypto-0.22.6rc4/demo/Zope/starts.bat0000775000175000017500000000012612605232411017764 0ustar matejmatej00000000000000"C:\pkg\zope260\bin\python.exe" "C:\pkg\zope260\z2s.py" -D %1 %2 %3 %4 %5 %6 %7 %8 %9 M2Crypto-0.22.6rc4/demo/Zope/z2s.py0000664000175000017500000011130512607370517017057 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """Zope 2 ZServer start-up file Usage: %(program)s [options] [environment settings] Options: -h Output this text. -z path The location of the Zope installation. The default is the location of this script, %(here)s. -Z 0 or 1 UNIX only! This option is ignored on Windows. This option controls whether a management process will be created that restarts Zope after a shutdown or crash. If the argument to -Z is non-null (e.g. "-Z1" or "-Zyes"), a management process will be used. If the argument to -Z is "-", or "0", (e.g. "-Z-" or "-Z0"), a management process will not be used. On UNIX, the default behavior is to create a separate management process (e.g. -Z1) if the -Z option is not specified. (Note: the -Z option in Zopes before Zope 2.6 used to be used to specify a pidfile name for the management process. This pidfile no longer exists). -t n The number of threads to use, if ZODB3 is used. The default is %(NUMBER_OF_THREADS)s. -i n Set the interpreter check interval. This integer value determines how often the interpreter checks for periodic things such as thread switches and signal handlers. The Zope default is 500, but you may want to experiment with other values that may increase performance in your particular environment. -D Run in Zope debug mode. This causes the Zope process not to detach from the controlling terminal, and is equivalent to supplying the environment variable setting Z_DEBUG_MODE=1 -a ipaddress The IP address to listen on. If this is an empty string (e.g. -a ''), then all addresses on the machine are used. The default is %(IP_ADDRESS)s. -d ipaddress IP address of your DNS server. If this is an empty string (e.g. -d ''), then IP addresses will not be logged. If you have DNS service on your local machine then you can set this to 127.0.0.1. The default is: %(DNS_IP)s. -u username or uid number The username to run ZServer as. You may want to run ZServer as a dedicated user. This only works under Unix, and if ZServer is started as root, and is required in that case. -P [ipaddress:]number Set the web, ftp and monitor port numbers simultaneously as offsets from the number. The web port number will be number+80. The FTP port number will be number+21. The monitor port number will be number+99. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -P options can be provided to run multiple sets of servers. -w port The Web server (HTTP) port. This defaults to %(HTTP_PORT)s. The standard port for HTTP services is 80. If this is a dash (e.g. -w -), then HTTP is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -w options can be provided to run multiple servers. -y port The SSL Web server (HTTPS) port. This defaults to %(HTTPS_PORT)s. The standard port for HTTPS services is 443. If this is a dash (e.g. -y -), then HTTPS is disabled. The number can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -y options can be provided to run multiple servers. -W port The "WebDAV source" port. If this is a dash (e.g. -W -), then "WebDAV source" is disabled. The default is disabled. Note that this feature is a workaround for the lack of "source-link" support in standard WebDAV clients. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -W options can be provided to run multiple servers. -Y port The "WebDAV source over HTTPS" port. If this is a dash (e.g. -Y -), then "WebDAV source over HTTPS" is disabled. The default is disabled. Note that this feature is a workaround for the lack of "source-link" support in standard WebDAV clients. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -Y options can be provided to run multiple servers. -x If present, this option causes Zope to run in X.509 certificate-based authentication mode. -C --force-http-connection-close If present, this option causes Zope to close all HTTP connections, regardless of the 'Connection:' header (or lack of one) sent by the client. -f port The FTP port. If this is a dash (e.g. -f -), then FTP is disabled. The standard port for FTP services is 21. The default is %(FTP_PORT)s. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -f options can be provided to run multiple servers. -p path Path to the PCGI resource file. The default value is %(PCGI_FILE)s, relative to the Zope location. If this is a dash (-p -) or the file does not exist, then PCGI is disabled. -F path_or_port Either a port number (for inet sockets) or a path name (for unix domain sockets) for the FastCGI Server. If the flag and value are not specified then the FastCGI Server is disabled. -m port The secure monitor server port. If this is a dash (-m -), then the monitor server is disabled. The monitor server allows interactive Python style access to a running ZServer. To access the server see medusa/monitor_client.py or medusa/monitor_client_win32.py. The monitor server password is the same as the Zope emergency user password set in the 'access' file. The default is to not start up a monitor server. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple -m options can be provided to run multiple servers. --icp port The ICP port. ICP can be used to distribute load between back-end zope servers, if you are using an ICP-aware front-end proxy such as Squid. The port can be preeceeded by an ip address follwed by a colon to specify an address to listen on. This allows different servers to listen on different addresses. Multiple --icp options can be provided to run multiple servers. -l path Path to the ZServer log file. If this is a relative path then the log file will be written to the 'var' directory. The default is %(LOG_FILE)s. -r Run ZServer is read-only mode. ZServer won't write anything to disk. No log files, no pid files, nothing. This means that you can't do a lot of stuff like use PCGI, and zdaemon. ZServer will log hits to STDOUT and zLOG will log to STDERR. -L Enable locale (internationalization) support. The value passed for this option should be the name of the locale to be used (see your operating system documentation for locale information specific to your system). If an empty string is passed for this option (-L ''), Zope will set the locale to the user's default setting (typically specified in the $LANG environment variable). If your Python installation does not support the locale module, the requested locale is not supported by your system or an empty string was passed but no default locale can be found, an error will be raised and Zope will not start. -X Disable servers. This might be used to effectively disable all default server settings or previous server settings in the option list before providing new settings. For example to provide just a web server: %(program)s -X -w80 -M file Save detailed logging information to the given file. This log includes separate entries for: - The start of a request, - The start of processing the request in an application thread, - The start of response output, and - The end of the request. Environment settings are of the form: NAME=VALUE. Note: you *must* use Python 2.1 or later! """ # This is required path hackery for the win32 binary distribution # that ensures that the bundled python libraries are used. In a # win32 binary distribution, the installer will have replaced the # marker string with the actual software home. If that has not # happened, then the path munging code is skipped. swhome=r'INSERT_SOFTWARE_HOME' if swhome != 'INSERT_SOFTWARE_HOME': import sys sys.path.insert(0, '%s/lib/python' % swhome) sys.path.insert(1, '%s/bin/lib' % swhome) sys.path.insert(2, '%s/bin/lib/plat-win' % swhome) sys.path.insert(3, '%s/bin/lib/win32' % swhome) sys.path.insert(4, '%s/bin/lib/win32/lib' % swhome) sys.path.insert(5, '%s' % swhome) import os, sys, getopt, codecs, string import socket from types import StringType, IntType # workaround to allow unicode encoding conversions in DTML dummy = codecs.lookup('iso-8859-1') sys.setcheckinterval(500) program=sys.argv[0] here=os.path.join(os.getcwd(), os.path.split(program)[0]) ######################################################################## # Configuration section ## General configuration options ## # This is the IP address of the network interface you want your servers to # be visible from. This can be changed to '' to listen on all interfaces. IP_ADDRESS='' # IP address of your DNS server. Set to '' if you do not want to resolve # IP addresses. If you have DNS service on your local machine then you can # set this to '127.0.0.1' DNS_IP='' # User id to run ZServer as. Note that this only works under Unix, and if # ZServer is started by root. This no longer defaults to 'nobody' since # that can lead to a Zope file compromise. UID=None # Log file location. If this is a relative path, then it is joined the # the 'var' directory. LOG_FILE='Z2.log' ## HTTP configuration ## # Port for HTTP Server. The standard port for HTTP services is 80. HTTP_PORT=8080 # Port for HTTPS Server. The standard port for HTTPS services is 443. HTTPS_PORT=8443 # HTTP enivornment settings. HTTP_ENV={} # HTTPS enivornment settings. HTTPS_ENV={} # Should we close all HTTP connections, ignoring the (usually absent) # 'Connection:' header? FORCE_HTTP_CONNECTION_CLOSE=0 # Port for the special "WebDAV source view" HTTP handler. There is no # standard port for this handler, which is disabled by default. WEBDAV_SOURCE_PORT=[] # Port for the special "WebDAV source view over SSL" HTTP handler. There is no # standard port for this handler, which is disabled by default. WEBDAV_SSL_SOURCE_PORT=[] # Should we use client X.509 certificate-based authentication? X509_REMOTE_USER=None ## FTP configuration # Port for the FTP Server. The standard port for FTP services is 21. FTP_PORT=8021 ## PCGI configuration # You can configure the PCGI server manually, or have it read its # configuration information from a PCGI info file. PCGI_FILE='Zope.cgi' ## Monitor configuration MONITOR_PORT=0 ## ICP configuration ICP_PORT=0 # Module to be published, which must be Main or Zope MODULE='Zope' # The size of the thread pool, if ZODB3 is used. NUMBER_OF_THREADS=4 # Localization support LOCALE_ID=None # Socket path or port for the FastCGI Server FCGI_PORT=None # Detailed log file DETAILED_LOG_FILE='' # Use a daemon process USE_DAEMON = 1 # ######################################################################## ######################################################################## # Handle command-line arguments: def server_info(old, v, offset=0): # interpret v as a port or address/port and get new value if v == '-': v='' l=v.find(':') if l >= 0: a=v[:l] v=v[l+1:] else: a=IP_ADDRESS if not v: return v try: v=int(v) if v < 0: raise 'Invalid port', v v=v+offset except: raise 'Invalid port', v if isinstance(old, IntType): old=[(a,v)] else: old.append((a,v)) return old try: python_version = sys.version.split()[0] if python_version < '2.1': raise 'Invalid python version', python_version if python_version[:3] == '2.1': if python_version[4:5] < '3': import warnings err = ('You are running Python version %s. This Python version ' 'has known bugs that may cause Zope to run improperly. ' 'Consider upgrading to a Python in the 2.1 series ' 'with at least version number 2.1.3. (Note that Zope does ' 'not yet run under any Python 2.2 version).' % python_version) warnings.warn(err) if python_version[:3] == '2.2': import warnings err = ('You are running Python version %s. This Python version ' 'has not yet been tested with Zope and you may experience ' 'operational problems as a result. Consider using ' 'Python 2.1.3 instead.' % python_version) warnings.warn(err) opts, args = getopt.getopt(sys.argv[1:], 'hz:Z:t:i:a:d:u:w:W:y:Y:x:f:p:m:Sl:2DP:rF:L:XM:C', ['icp=', 'force-http-connection-close' ]) DEBUG=0 READ_ONLY=0 if sys.platform == 'win32': USE_DAEMON = 0 # Get environment variables for a in args: if a.find('='): a=a.split('=') o=a[0] v='='.join(a[1:]) if o: os.environ[o]=v HTTP_ENV[o]=v else: raise 'Invalid argument', a for o, v in opts: if o=='-z': here=v elif o=='-Z': if v in ('-', '0', ''): USE_DAEMON=0 elif sys.platform != 'win32': USE_DAEMON = 1 elif o=='-r': READ_ONLY=1 elif o=='-t': try: v=int(v) except: raise 'Invalid number of threads', v NUMBER_OF_THREADS=v elif o=='-i': try: v=int(v) except: raise 'Invalid value for -i option', v sys.setcheckinterval(v) elif o=='-a': IP_ADDRESS=v elif o=='-d': if v=='-': v='' DNS_IP=v elif o=='-u': UID=v elif o=='-D': os.environ['Z_DEBUG_MODE']='1' DEBUG=1 elif o=='-S': sys.ZMANAGED=1 elif o=='-X': MONITOR_PORT=HTTP_PORT=FTP_PORT=FCGI_PORT=ICP_PORT=0 WEBDAV_SOURCE_PORT=0 PCGI_FILE='' elif o=='-m': MONITOR_PORT=server_info(MONITOR_PORT, v) elif o=='-w': HTTP_PORT=server_info(HTTP_PORT, v) elif o=='-y': HTTPS_PORT=server_info(HTTPS_PORT, v) elif o=='-C' or o=='--force-http-connection-close': FORCE_HTTP_CONNECTION_CLOSE=1 elif o=='-W': WEBDAV_SOURCE_PORT=server_info(WEBDAV_SOURCE_PORT, v) elif o=='-Y': WEBDAV_SSL_SOURCE_PORT=server_info(WEBDAV_SSL_SOURCE_PORT, v) elif o=='-x': if v in ('-', '0', ''): X509_REMOTE_USER=None else: X509_REMOTE_USER=1 elif o=='-f': FTP_PORT=server_info(FTP_PORT, v) elif o=='-P': HTTP_PORT=server_info(HTTP_PORT, v, 80) FTP_PORT=server_info(FTP_PORT, v, 21) elif o=='--icp': ICP_PORT=server_info(ICP_PORT, v) elif o=='-p': if v=='-': v='' PCGI_FILE=v elif o=='-h': print __doc__ % vars() sys.exit(0) elif o=='-2': MODULE='Main' elif o=='-l': LOG_FILE=v elif o=='-L': if v: LOCALE_ID=v else: LOCALE_ID='' elif o=='-F': if v=='-': v='' FCGI_PORT=v elif o=='-M': DETAILED_LOG_FILE=v except SystemExit: sys.exit(0) except: print __doc__ % vars() print print 'Error:' print "%s: %s" % (sys.exc_type, sys.exc_value) sys.exit(1) # ######################################################################## ######################################################################## # OK, let's get going! # Jigger path: sys.path=[os.path.join(here,'lib','python'),here ]+filter(None, sys.path) # Try to set the locale if specified on the command # line. If the locale module is not available or the # requested locale is not supported by the local # machine, raise an error so that the user is made # aware of the problem. def set_locale(val): try: import locale except: raise SystemExit, ( 'The locale module could not be imported.\n' 'To use localization options, you must ensure\n' 'that the locale module is compiled into your\n' 'Python installation.' ) try: locale.setlocale(locale.LC_ALL, val) except: raise SystemExit, ( 'The specified locale is not supported by your system.\n' 'See your operating system documentation for more\n' 'information on locale support.' ) if LOCALE_ID is not None: set_locale(LOCALE_ID) import zdaemon # from this point forward we can use the zope logger # importing ZDaemon before importing ZServer causes ZServer logging # not to work. # Import ZServer before we open the database or get at interesting # application code so that ZServer's asyncore gets to be the # official one. Also gets SOFTWARE_HOME, INSTANCE_HOME, and CLIENT_HOME import ZServer # install signal handlers if on posix if os.name == 'posix': from Signals import Signals Signals.registerZopeSignals() # Location of the ZServer pid file. When Zope starts up it will write # its PID to this file. If Zope is run under zdaemon control, zdaemon # will write to this pidfile instead of Zope. PID_FILE=os.path.join(CLIENT_HOME, 'Z2.pid') if USE_DAEMON and not READ_ONLY: import App.FindHomes sys.ZMANAGED=1 # zdaemon.run creates a process which "manages" the actual Zope # process (restarts it if it dies). The management process passes along # signals that it receives to its child. zdaemon.run(sys.argv, os.path.join(CLIENT_HOME, PID_FILE)) os.chdir(CLIENT_HOME) def _warn_nobody(): zLOG.LOG("z2", zLOG.INFO, ("Running Zope as 'nobody' can compromise " "your Zope files; consider using a " "dedicated user account for Zope") ) try: # Import logging support import zLOG import ZLogger if READ_ONLY: if hasattr(zLOG, '_set_stupid_dest'): zLOG._set_stupid_dest(sys.stderr) else: zLOG._stupid_dest = sys.stderr else: zLOG.log_write = ZLogger.ZLogger.log_write if DETAILED_LOG_FILE: from ZServer import DebugLogger logfile=os.path.join(CLIENT_HOME, DETAILED_LOG_FILE) zLOG.LOG('z2', zLOG.BLATHER, 'Using detailed request log file %s' % logfile) DL=DebugLogger.DebugLogger(logfile) DebugLogger.log=DL.log DebugLogger.reopen=DL.reopen sys.__detailedlog=DL # Import Zope (or Main) if MODULE == 'Zope': import Zope Zope.startup() else: exec "import "+MODULE in {} # Location of the ZServer log file. This file logs all ZServer activity. # You may wish to create different logs for different servers. See # medusa/logger.py for more information. if not os.path.isabs(LOG_FILE): LOG_PATH=os.path.join(CLIENT_HOME, LOG_FILE) else: LOG_PATH=LOG_FILE # import ZServer stuff # First, we need to increase the number of threads if MODULE=='Zope': from ZServer import setNumberOfThreads setNumberOfThreads(NUMBER_OF_THREADS) from ZServer import resolver, logger, asyncore from ZServer import zhttp_server, zhttp_handler from ZServer import zhttps_server, zhttps0_handler, zhttps_handler from ZServer.WebDAVSrcHandler import WebDAVSrcHandler from ZServer import PCGIServer,FTPServer,FCGIServer from ZServer import secure_monitor_server from M2Crypto import SSL, Rand ## ZServer startup ## ## In X509_REMOTE_USER mode, we log the client cert's subject DN. if X509_REMOTE_USER: import base64, string, time def log (self, bytes): user_agent=self.get_header('user-agent') if not user_agent: user_agent='' referer=self.get_header('referer') if not referer: referer='' get_peer_cert = getattr(self.channel, 'get_peer_cert', None) if get_peer_cert is not None: name = str(get_peer_cert().get_subject()) else: name = 'Anonymous' auth=self.get_header('Authorization') if auth is not None: if string.lower(auth[:6]) == 'basic ': try: decoded=base64.decodestring(auth[6:]) except base64.binascii.Error: decoded='' t = string.split(decoded, ':', 1) if len(t) < 2: name = 'Unknown (bad auth string)' else: name = t[0] self.channel.server.logger.log ( self.channel.addr[0], ' - %s [%s] "%s" %d %d "%s" "%s"\n' % ( name, self.log_date_string (time.time()), self.request, self.reply_code, bytes, referer, user_agent ) ) from ZServer.medusa import http_server http_server.http_request.log = log # Resolver and Logger, used by other servers if DNS_IP: rs = resolver.caching_resolver(DNS_IP) else: rs=None if READ_ONLY: lg = logger.file_logger('-') # log to stdout zLOG.LOG('z2', zLOG.BLATHER, 'Logging access log to stdout') elif os.environ.has_key('ZSYSLOG_ACCESS'): if os.environ.has_key("ZSYSLOG_ACCESS_FACILITY"): lg = logger.syslog_logger( os.environ['ZSYSLOG_ACCESS'], facility=os.environ['ZSYSLOG_ACCESS_FACILITY']) else: lg = logger.syslog_logger(os.environ['ZSYSLOG_ACCESS']) zLOG.LOG('z2', zLOG.BLATHER, 'Using local syslog access log') elif os.environ.has_key('ZSYSLOG_ACCESS_SERVER'): (addr, port) = os.environ['ZSYSLOG_ACCESS_SERVER'].split( ':') lg = logger.syslog_logger((addr, int(port))) zLOG.LOG('z2', zLOG.BLATHER, 'Using remote syslog access log') else: lg = logger.file_logger(LOG_PATH) zLOG.LOG('z2', zLOG.BLATHER, 'Using access log file %s' % LOG_PATH) sys.__lg = lg port_err=('\n\nZope wants to use %(socktype)s port %(port)s for its ' '%(protocol)s service, but it is already in use by another ' 'application on this machine. Either shut the application down ' 'which is using this port, or start Zope with a different ' '%(protocol)s port via the "%(switch)s" command-line switch.\n') # HTTP Server if HTTP_PORT: if isinstance(HTTP_PORT, IntType): HTTP_PORT=((IP_ADDRESS, HTTP_PORT),) for address, port in HTTP_PORT: try: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'HTTP', 'switch':'-w'} raise # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. try: del HTTP_ENV['HTTPS'] except KeyError: pass zh = zhttp_handler(MODULE, '', HTTP_ENV) if FORCE_HTTP_CONNECTION_CLOSE: zh._force_connection_close = 1 hs.install_handler(zh) # HTTPS Server if HTTPS_PORT: ssl_ctx = SSL.Context('sslv23') ssl_ctx.load_cert_chain('%s/server.pem' % INSTANCE_HOME) ssl_ctx.load_verify_locations('%s/ca.pem' % INSTANCE_HOME) ssl_ctx.load_client_CA('%s/ca.pem' % INSTANCE_HOME) #ssl_ctx.set_allow_unknown_ca(1) ssl_ctx.set_session_id_ctx(MODULE) ssl_ctx.set_tmp_dh('%s/dh1024.pem' % INSTANCE_HOME) if X509_REMOTE_USER: ssl_ctx.set_verify(SSL.verify_peer, 10) else: ssl_ctx.set_verify(SSL.verify_none, 10) if type(HTTPS_PORT) is type(0): HTTPS_PORT=((IP_ADDRESS, HTTPS_PORT),) for address, port in HTTPS_PORT: hss = zhttps_server( ip=address, port=port, ssl_ctx=ssl_ctx, resolver=rs, logger_object=lg) try: del HTTPS_ENV['HTTP'] except KeyError: pass HTTPS_ENV['HTTPS']='ON' if X509_REMOTE_USER: zsh = zhttps_handler(MODULE, '', HTTPS_ENV) else: zsh = zhttps0_handler(MODULE, '', HTTPS_ENV) hss.install_handler(zsh) # WebDAV source Server (runs HTTP, but munges request to return # 'manage_FTPget'). if WEBDAV_SOURCE_PORT: if isinstance(WEBDAV_SOURCE_PORT, IntType): WEBDAV_SOURCE_PORT=((IP_ADDRESS, WEBDAV_SOURCE_PORT),) for address, port in WEBDAV_SOURCE_PORT: try: hs = zhttp_server( ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'WebDAV source', 'switch':'-W'} raise # Handler for a published module. zhttp_handler takes 3 arguments: # The name of the module to publish, and optionally the URI base # which is basically the SCRIPT_NAME, and optionally a dictionary # with CGI environment variables which override default # settings. The URI base setting is useful when you want to # publish more than one module with the same HTTP server. The CGI # environment setting is useful when you want to proxy requests # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. zh = WebDAVSrcHandler(MODULE, '', HTTP_ENV) hs.install_handler(zh) # enable document retrieval of the document source on the # standard HTTP port clients = os.environ.get('WEBDAV_SOURCE_PORT_CLIENTS') if clients: import re sys.WEBDAV_SOURCE_PORT_CLIENTS = re.compile(clients).search else: sys.WEBDAV_SOURCE_PORT_CLIENTS = None # WebDAV-over-SSL source Server (runs HTTPS, but munges request to return # 'manage_FTPget'). if WEBDAV_SSL_SOURCE_PORT: ssl_ctx = SSL.Context('sslv23') ssl_ctx.load_cert_chain('%s/server.pem' % INSTANCE_HOME) ssl_ctx.load_verify_locations('%s/ca.pem' % INSTANCE_HOME) ssl_ctx.load_client_CA('%s/ca.pem' % INSTANCE_HOME) ssl_ctx.set_verify(SSL.verify_none, 10) ssl_ctx.set_session_id_ctx(MODULE) ssl_ctx.set_tmp_dh('%s/dh1024.pem' % INSTANCE_HOME) if type(WEBDAV_SSL_SOURCE_PORT) is type(0): WEBDAV_SSL_SOURCE_PORT=((IP_ADDRESS, WEBDAV_SSL_SOURCE_PORT),) for address, port in WEBDAV_SSL_SOURCE_PORT: hss = zhttps_server( ip=address, port=port, ssl_ctx=ssl_ctx, resolver=rs, logger_object=lg) try: del HTTPS_ENV['HTTP'] except KeyError: pass HTTPS_ENV['HTTPS']='ON' zsh = WebDAVSrcHandler(MODULE, '', HTTPS_ENV) hss.install_handler(zsh) # FTP Server if FTP_PORT: if isinstance(FTP_PORT, IntType): FTP_PORT=((IP_ADDRESS, FTP_PORT),) for address, port in FTP_PORT: try: FTPServer( module=MODULE, ip=address, port=port, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'FTP', 'switch':'-f'} raise # PCGI Server if PCGI_FILE and not READ_ONLY: PCGI_FILE=os.path.join(here, PCGI_FILE) if os.path.exists(PCGI_FILE): zpcgi = PCGIServer( module=MODULE, ip=IP_ADDRESS, pcgi_file=PCGI_FILE, resolver=rs, logger_object=lg) # FastCGI Server if FCGI_PORT and not READ_ONLY: fcgiPort = None fcgiPath = None try: fcgiPort = int(FCGI_PORT) except ValueError: fcgiPath = FCGI_PORT try: zfcgi = FCGIServer(module=MODULE, ip=IP_ADDRESS, port=fcgiPort, socket_file=fcgiPath, resolver=rs, logger_object=lg) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':fcgiPort, 'socktype':'TCP', 'protocol':'FastCGI', 'switch':'-F'} raise # Monitor Server if MONITOR_PORT: from AccessControl.User import emergency_user if not hasattr(emergency_user, '__null_user__'): pw = emergency_user._getPassword() else: pw = None zLOG.LOG("z2", zLOG.WARNING, 'Monitor server not started' ' because no emergency user exists.') if pw: if isinstance(MONITOR_PORT, IntType): MONITOR_PORT=((IP_ADDRESS, MONITOR_PORT),) for address, port in MONITOR_PORT: try: monitor=secure_monitor_server( password=pw, hostname=address, port=port) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'TCP', 'protocol':'monitor server', 'switch':'-m'} raise if ICP_PORT: if isinstance(ICP_PORT, IntType): ICP_PORT=((IP_ADDRESS, ICP_PORT),) from ZServer.ICPServer import ICPServer for address, port in ICP_PORT: try: ICPServer(address,port) except socket.error, why: if why[0] == 98: # address in use raise port_err % {'port':port, 'socktype':'UDP', 'protocol':'ICP', 'switch':'--icp'} raise if not USE_DAEMON and not READ_ONLY: if os.path.exists(PID_FILE): os.unlink(PID_FILE) pf = open(PID_FILE, 'w') pid='%s\n' % os.getpid() pf.write(pid) pf.close() # Warn if we were started as nobody. try: import pwd if os.getuid(): if pwd.getpwuid(os.getuid())[0] == 'nobody': _warn_nobody() except: pass # Drop root privileges if we have them, and do some sanity checking # to make sure we're not starting with an obviously insecure setup. try: if os.getuid() == 0: try: import initgroups except: raise SystemExit, 'initgroups is required to safely setuid' if UID == None: raise SystemExit, ('A user was not specified to setuid ' 'to; fix this to start as root (see ' 'doc/SETUID.txt)') import stat client_home_stat = os.stat(CLIENT_HOME) client_home_faults = [] if not (client_home_stat[stat.ST_MODE]&01000): client_home_faults.append('does not have the sticky bit set') if client_home_stat[stat.ST_UID] != 0: client_home_faults.append('is not owned by root') if client_home_faults: client_home_faults.append('fix this to start as root (see ' 'doc/SETUID.txt)') err = '%s %s' % (CLIENT_HOME, ', '.join(client_home_faults)) raise SystemExit, err try: try: UID = string.atoi(UID) except: pass gid = None if isinstance(UID, StringType): uid = pwd.getpwnam(UID)[2] gid = pwd.getpwnam(UID)[3] elif isinstance(UID, IntType): uid = pwd.getpwuid(UID)[2] gid = pwd.getpwuid(UID)[3] UID = pwd.getpwuid(UID)[0] else: raise KeyError if UID == 'nobody': _warn_nobody() try: initgroups.initgroups(UID, gid) if gid is not None: try: os.setgid(gid) except OSError: pass os.setuid(uid) except OSError: pass except KeyError: zLOG.LOG("z2", zLOG.ERROR, ("Can't find UID %s" % UID)) except AttributeError: pass except: raise # Check umask sanity if we're on posix. if os.name == 'posix' and not os.environ.get('Z_DEBUG_MODE'): # umask is silly, blame POSIX. We have to set it to get its value. current_umask = os.umask(0) os.umask(current_umask) if current_umask != 077: current_umask = '%03o' % current_umask zLOG.LOG("z2", zLOG.INFO, ( 'Your umask of %s may be too permissive; for the security of ' 'your Zope data, it is recommended you use 077' % current_umask )) except: # Log startup exception and tell zdaemon not to restart us. try: zLOG.LOG("z2", zLOG.PANIC, "Startup exception", error=sys.exc_info()) except: pass sys.exit(0) # Start Medusa, Ye Hass! Rand.load_file('%s/randpool.dat' % INSTANCE_HOME, -1) sys.ZServerExitCode=0 asyncore.loop() Rand.save_file('%s/randpool.dat' % INSTANCE_HOME) sys.exit(sys.ZServerExitCode) M2Crypto-0.22.6rc4/demo/Zope/z2s.py.diff0000664000175000017500000002226312605232411017756 0ustar matejmatej00000000000000--- z2s.py Sun Oct 26 17:51:00 2003 +++ /usr/local/home/ngps/pkg/zope261/z2.py Thu Jan 30 22:41:42 2003 @@ -105,21 +105,9 @@ Multiple -w options can be provided to run multiple servers. - -y port - - The SSL Web server (HTTPS) port. This defaults to %(HTTPS_PORT)s. The - standard port for HTTPS services is 443. If this is a dash - (e.g. -y -), then HTTPS is disabled. - - The number can be preeceeded by an ip address follwed by a colon - to specify an address to listen on. This allows different servers - to listen on different addresses. - - Multiple -y options can be provided to run multiple servers. - -W port - The "WebDAV source" port. If this is a dash (e.g. -W -), then + The "WebDAV source" port. If this is a dash (e.g. -w -), then "WebDAV source" is disabled. The default is disabled. Note that this feature is a workaround for the lack of "source-link" support in standard WebDAV clients. @@ -130,24 +118,6 @@ Multiple -W options can be provided to run multiple servers. - -Y port - - The "WebDAV source over HTTPS" port. If this is a dash (e.g. -Y -), then - "WebDAV source over HTTPS" is disabled. The default is disabled. Note that - this feature is a workaround for the lack of "source-link" support - in standard WebDAV clients. - - The port can be preeceeded by an ip address follwed by a colon - to specify an address to listen on. This allows different servers - to listen on different addresses. - - Multiple -Y options can be provided to run multiple servers. - - -x - - If present, this option causes Zope to run in X.509 certificate-based - authentication mode. - -C --force-http-connection-close @@ -316,15 +286,9 @@ # Port for HTTP Server. The standard port for HTTP services is 80. HTTP_PORT=8080 -# Port for HTTPS Server. The standard port for HTTPS services is 443. -HTTPS_PORT=8443 - # HTTP enivornment settings. HTTP_ENV={} -# HTTPS enivornment settings. -HTTPS_ENV={} - # Should we close all HTTP connections, ignoring the (usually absent) # 'Connection:' header? FORCE_HTTP_CONNECTION_CLOSE=0 @@ -333,13 +297,6 @@ # standard port for this handler, which is disabled by default. WEBDAV_SOURCE_PORT=[] -# Port for the special "WebDAV source view over SSL" HTTP handler. There is no -# standard port for this handler, which is disabled by default. -WEBDAV_SSL_SOURCE_PORT=[] - -# Should we use client X.509 certificate-based authentication? -X509_REMOTE_USER=None - ## FTP configuration # Port for the FTP Server. The standard port for FTP services is 21. @@ -429,7 +386,7 @@ opts, args = getopt.getopt(sys.argv[1:], - 'hz:Z:t:i:a:d:u:w:W:y:Y:x:f:p:m:Sl:2DP:rF:L:XM:C', + 'hz:Z:t:i:a:d:u:w:W:f:p:m:Sl:2DP:rF:L:XM:C', ['icp=', 'force-http-connection-close' ]) @@ -486,19 +443,10 @@ MONITOR_PORT=server_info(MONITOR_PORT, v) elif o=='-w': HTTP_PORT=server_info(HTTP_PORT, v) - elif o=='-y': - HTTPS_PORT=server_info(HTTPS_PORT, v) elif o=='-C' or o=='--force-http-connection-close': FORCE_HTTP_CONNECTION_CLOSE=1 elif o=='-W': WEBDAV_SOURCE_PORT=server_info(WEBDAV_SOURCE_PORT, v) - elif o=='-Y': - WEBDAV_SSL_SOURCE_PORT=server_info(WEBDAV_SSL_SOURCE_PORT, v) - elif o=='-x': - if v in ('-', '0', ''): - X509_REMOTE_USER=None - else: - X509_REMOTE_USER=1 elif o=='-f': FTP_PORT=server_info(FTP_PORT, v) elif o=='-P': @@ -653,60 +601,14 @@ from ZServer import resolver, logger, asyncore from ZServer import zhttp_server, zhttp_handler - from ZServer import zhttps_server, zhttps0_handler, zhttps_handler from ZServer.WebDAVSrcHandler import WebDAVSrcHandler from ZServer import PCGIServer,FTPServer,FCGIServer from ZServer import secure_monitor_server - from M2Crypto import SSL, Rand - ## ZServer startup ## - ## In X509_REMOTE_USER mode, we log the client cert's subject DN. - if X509_REMOTE_USER: - - import base64, string, time - - def log (self, bytes): - user_agent=self.get_header('user-agent') - if not user_agent: user_agent='' - referer=self.get_header('referer') - if not referer: referer='' - - get_peer_cert = getattr(self.channel, 'get_peer_cert', None) - if get_peer_cert is not None: - name = str(get_peer_cert().get_subject()) - else: - name = 'Anonymous' - auth=self.get_header('Authorization') - if auth is not None: - if string.lower(auth[:6]) == 'basic ': - try: decoded=base64.decodestring(auth[6:]) - except base64.binascii.Error: decoded='' - t = string.split(decoded, ':', 1) - if len(t) < 2: - name = 'Unknown (bad auth string)' - else: - name = t[0] - - self.channel.server.logger.log ( - self.channel.addr[0], - ' - %s [%s] "%s" %d %d "%s" "%s"\n' % ( - name, - self.log_date_string (time.time()), - self.request, - self.reply_code, - bytes, - referer, - user_agent - ) - ) - - from ZServer.medusa import http_server - http_server.http_request.log = log - # Resolver and Logger, used by other servers if DNS_IP: rs = resolver.caching_resolver(DNS_IP) @@ -766,51 +668,11 @@ # from another web server to ZServer, and would like the CGI # environment to reflect the CGI environment of the other web # server. - try: - del HTTP_ENV['HTTPS'] - except KeyError: - pass zh = zhttp_handler(MODULE, '', HTTP_ENV) if FORCE_HTTP_CONNECTION_CLOSE: zh._force_connection_close = 1 hs.install_handler(zh) - # HTTPS Server - if HTTPS_PORT: - ssl_ctx = SSL.Context('sslv23') - ssl_ctx.load_cert_chain('%s/server.pem' % INSTANCE_HOME) - ssl_ctx.load_verify_locations('%s/ca.pem' % INSTANCE_HOME) - ssl_ctx.load_client_CA('%s/ca.pem' % INSTANCE_HOME) - #ssl_ctx.set_allow_unknown_ca(1) - ssl_ctx.set_session_id_ctx(MODULE) - ssl_ctx.set_tmp_dh('%s/dh1024.pem' % INSTANCE_HOME) - if X509_REMOTE_USER: - ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 10) - #ssl_ctx.set_verify(SSL.verify_peer, 10) - else: - ssl_ctx.set_verify(SSL.verify_none, 10) - if type(HTTPS_PORT) is type(0): HTTPS_PORT=((IP_ADDRESS, HTTPS_PORT),) - - for address, port in HTTPS_PORT: - hss = zhttps_server( - ip=address, - port=port, - ssl_ctx=ssl_ctx, - resolver=rs, - logger_object=lg) - - try: - del HTTPS_ENV['HTTP'] - except KeyError: - pass - HTTPS_ENV['HTTPS']='ON' - - if X509_REMOTE_USER: - zsh = zhttps_handler(MODULE, '', HTTPS_ENV) - else: - zsh = zhttps0_handler(MODULE, '', HTTPS_ENV) - hss.install_handler(zsh) - # WebDAV source Server (runs HTTP, but munges request to return # 'manage_FTPget'). if WEBDAV_SOURCE_PORT: @@ -854,34 +716,6 @@ else: sys.WEBDAV_SOURCE_PORT_CLIENTS = None - # WebDAV-over-SSL source Server (runs HTTPS, but munges request to return - # 'manage_FTPget'). - if WEBDAV_SSL_SOURCE_PORT: - ssl_ctx = SSL.Context('sslv23') - ssl_ctx.load_cert_chain('%s/server.pem' % INSTANCE_HOME) - ssl_ctx.load_verify_locations('%s/ca.pem' % INSTANCE_HOME) - ssl_ctx.load_client_CA('%s/ca.pem' % INSTANCE_HOME) - ssl_ctx.set_verify(SSL.verify_none, 10) - ssl_ctx.set_session_id_ctx(MODULE) - ssl_ctx.set_tmp_dh('%s/dh1024.pem' % INSTANCE_HOME) - if type(WEBDAV_SSL_SOURCE_PORT) is type(0): - WEBDAV_SSL_SOURCE_PORT=((IP_ADDRESS, WEBDAV_SSL_SOURCE_PORT),) - for address, port in WEBDAV_SSL_SOURCE_PORT: - hss = zhttps_server( - ip=address, - port=port, - ssl_ctx=ssl_ctx, - resolver=rs, - logger_object=lg) - - try: - del HTTPS_ENV['HTTP'] - except KeyError: - pass - HTTPS_ENV['HTTPS']='ON' - - zsh = WebDAVSrcHandler(MODULE, '', HTTPS_ENV) - hss.install_handler(zsh) # FTP Server if FTP_PORT: @@ -1072,8 +906,6 @@ sys.exit(0) # Start Medusa, Ye Hass! -Rand.load_file('%s/randpool.dat' % INSTANCE_HOME, -1) sys.ZServerExitCode=0 asyncore.loop() -Rand.save_file('%s/randpool.dat' % INSTANCE_HOME) sys.exit(sys.ZServerExitCode) M2Crypto-0.22.6rc4/demo/Zope27/0000775000175000017500000000000012613362233016130 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/0000775000175000017500000000000012613362233020434 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/0000775000175000017500000000000012613362233021202 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/0000775000175000017500000000000012613362233022523 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/0000775000175000017500000000000012613362233024123 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/medusa/0000775000175000017500000000000012613362233025401 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/medusa/https_server.py0000664000175000017500000000503512607370517030515 0ustar matejmatej00000000000000#!/usr/bin/env python """A https server built on Medusa's http_server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import asynchat, asyncore, http_server, socket, sys from M2Crypto import SSL, version VERSION_STRING=version class https_channel(http_server.http_channel): ac_in_buffer_size = 1 << 16 def __init__(self, server, conn, addr): http_server.http_channel.__init__(self, server, conn, addr) def send(self, data): try: result = self.socket._write_nbio(data) if result <= 0: return 0 else: self.server.bytes_out.increment(result) return result except SSL.SSLError, why: self.close() self.log_info('send: closing channel %s %s' % (repr(self), why)) return 0 def recv(self, buffer_size): try: result = self.socket._read_nbio(buffer_size) if result is None: return '' elif result == '': self.close() return '' else: self.server.bytes_in.increment(len(result)) return result except SSL.SSLError, why: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), why)) return '' class https_server(http_server.http_server): SERVER_IDENT='M2Crypto HTTPS Server (v%s)' % VERSION_STRING channel_class=https_channel def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): http_server.http_server.__init__(self, ip, port, resolver, logger_object) self.ssl_ctx=ssl_ctx def handle_accept(self): # Cribbed from http_server. self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. sys.stderr.write ('warning: server accept() threw an exception\n') return # Turn the vanilla socket into an SSL connection. try: ssl_conn=SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr) except SSL.SSLError: pass def writeable(self): return 0 M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/HTTPS_Server.py0000664000175000017500000001425512607370517026743 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2000-2003, Ng Pheng Siong. All Rights Reserved. # This file is derived from Zope's ZServer/HTTPServer.py. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """ Medusa HTTPS server for Zope changes from Medusa's http_server: Request Threads -- Requests are processed by threads from a thread pool. Output Handling -- Output is pushed directly into the producer fifo by the request-handling thread. The HTTP server does not do any post-processing such as chunking. Pipelineable -- This is needed for protocols such as HTTP/1.1 in which mutiple requests come in on the same channel, before responses are sent back. When requests are pipelined, the client doesn't wait for the response before sending another request. The server must ensure that responses are sent back in the same order as requests are received. changes from Zope's HTTP server: Well, this is a *HTTPS* server :) X.509 certificate-based authentication -- When this is in force, zhttps_handler, a subclass of zhttp_handler, is installed. The https server is configured to request an X.509 certificate from the client. When the request reaches zhttps_handler, it sets REMOTE_USER to the client's subject distinguished name (DN) from the certificate. Zope's REMOTE_USER machinery takes care of the rest, e.g., in conjunction with the RemoteUserFolder product. """ import sys, time, types from PubCore import handle import asyncore from ZServer import CONNECTION_LIMIT, ZOPE_VERSION from HTTPServer import zhttp_handler from zLOG import register_subsystem from M2Crypto import SSL from medusa.https_server import https_server, https_channel from asyncore import dispatcher ZSERVER_SSL_VERSION='0.12' register_subsystem('ZServer HTTPS_Server') class zhttps0_handler(zhttp_handler): "zhttps0 handler - sets SSL request headers a la mod_ssl" def __init__ (self, module, uri_base=None, env=None): zhttp_handler.__init__(self, module, uri_base, env) def get_environment(self, request): env = zhttp_handler.get_environment(self, request) env['SSL_CIPHER'] = request.channel.get_cipher() return env class zhttps_handler(zhttps0_handler): "zhttps handler - sets REMOTE_USER to user's X.509 certificate Subject DN" def __init__ (self, module, uri_base=None, env=None): zhttps0_handler.__init__(self, module, uri_base, env) def get_environment(self, request): env = zhttps0_handler.get_environment(self, request) peer = request.channel.get_peer_cert() if peer is not None: env['REMOTE_USER'] = str(peer.get_subject()) return env class zhttps_channel(https_channel): "https channel" closed=0 zombie_timeout=100*60 # 100 minutes def __init__(self, server, conn, addr): https_channel.__init__(self, server, conn, addr) self.queue=[] self.working=0 self.peer_found=0 def push(self, producer, send=1): # this is thread-safe when send is false # note, that strings are not wrapped in # producers by default if self.closed: return self.producer_fifo.push(producer) if send: self.initiate_send() push_with_producer=push def work(self): "try to handle a request" if not self.working: if self.queue: self.working=1 try: module_name, request, response=self.queue.pop(0) except: return handle(module_name, request, response) def close(self): self.closed=1 while self.queue: self.queue.pop() if self.current_request is not None: self.current_request.channel=None # break circ refs self.current_request=None while self.producer_fifo: p=self.producer_fifo.first() if p is not None and type(p) != types.StringType: p.more() # free up resources held by producer self.producer_fifo.pop() self.del_channel() #self.socket.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN) self.socket.close() def done(self): "Called when a publishing request is finished" self.working=0 self.work() def kill_zombies(self): now = int (time.time()) for channel in asyncore.socket_map.values(): if channel.__class__ == self.__class__: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() class zhttps_server(https_server): "https server" SERVER_IDENT='ZServerSSL/%s' % (ZSERVER_SSL_VERSION,) channel_class = zhttps_channel shutup = 0 def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): self.shutup = 1 https_server.__init__(self, ip, port, ssl_ctx, resolver, logger_object) self.ssl_ctx = ssl_ctx self.shutup = 0 self.log_info('(%s) HTTPS server started at %s\n' '\tHostname: %s\n\tPort: %d' % ( self.SERVER_IDENT, time.ctime(time.time()), self.server_name, self.server_port )) def log_info(self, message, type='info'): if self.shutup: return dispatcher.log_info(self, message, type) def readable(self): return self.accepting and \ len(asyncore.socket_map) < CONNECTION_LIMIT def listen(self, num): # override asyncore limits for nt's listen queue size self.accepting = 1 return self.socket.listen (num) M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/__init__.py.patch0000664000175000017500000000060212605232411027323 0ustar matejmatej00000000000000--- __init__.py.org Sat Sep 27 20:23:00 2003 +++ __init__.py Sun Oct 26 18:01:27 2003 @@ -68,6 +68,7 @@ import asyncore from medusa import resolver, logger from HTTPServer import zhttp_server, zhttp_handler +from HTTPS_Server import zhttps_server, zhttps0_handler, zhttps_handler from PCGIServer import PCGIServer from FCGIServer import FCGIServer from FTPServer import FTPServer M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/component.xml.patch0000664000175000017500000000201412605232411027735 0ustar matejmatej00000000000000--- component.xml.org Sat Sep 27 20:21:22 2003 +++ component.xml Sat Sep 27 21:11:26 2003 @@ -21,6 +21,25 @@ + + + + + + Regular expression used to identify clients who should + receive WebDAV source responses to GET requests. + + + + + If "on", request client X.509 certificate and set REMOTE_USER to + said certificate's Subject Distinguished Name. + + + + M2Crypto-0.22.6rc4/demo/Zope27/install_dir/lib/python/ZServer/datatypes.py.patch0000664000175000017500000000450212605232411027565 0ustar matejmatej00000000000000--- datatypes.py.org Sat Sep 27 20:21:15 2003 +++ datatypes.py Sun Oct 26 21:19:58 2003 @@ -72,7 +72,56 @@ def createHandler(self): from ZServer import HTTPServer + try: + del self.cgienv['HTTPS'] + except KeyError: + pass return HTTPServer.zhttp_handler(self.module, '', self.cgienv) + + +class HTTPS_ServerFactory(HTTPServerFactory): + def __init__(self, section): + HTTPServerFactory.__init__(self, section) + self.x509_remote_user = section.x509_remote_user + from M2Crypto import Rand, SSL + Rand.load_file('%s/randpool.dat' % INSTANCE_HOME, -1) + ssl_ctx = SSL.Context('sslv23') + ssl_ctx.load_cert_chain('%s/ssl/server.pem' % INSTANCE_HOME) + ssl_ctx.load_verify_locations('%s/ssl/ca.pem' % INSTANCE_HOME,'') + ssl_ctx.load_client_CA('%s/ssl/ca.pem' % INSTANCE_HOME) + ssl_ctx.set_session_id_ctx('Zope 2.7.0b2') + ssl_ctx.set_tmp_dh('%s/ssl/dh1024.pem' % INSTANCE_HOME) + if self.x509_remote_user: + ssl_ctx.set_verify(SSL.verify_peer, 10) + else: + ssl_ctx.set_verify(SSL.verify_none, 10) + self.ssl_ctx = ssl_ctx + + def create(self): + from ZServer import HTTPS_Server + from ZServer.AccessLogger import access_logger + handler = self.createHandler() + handler._force_connection_close = self.force_connection_close + if self.webdav_source_clients: + handler.set_webdav_source_clients(self.webdav_source_clients) + server = HTTPS_Server.zhttps_server(ip=self.host, port=self.port, + ssl_ctx=self.ssl_ctx, + resolver=self.dnsresolver, + logger_object=access_logger) + server.install_handler(handler) + return server + + def createHandler(self): + from ZServer import HTTPS_Server + try: + del self.cgienv['HTTP'] + except KeyError: + pass + self.cgienv['HTTPS'] = 'ON' + if self.x509_remote_user: + return HTTPS_Server.zhttps_handler(self.module, '', self.cgienv) + else: + return HTTPS_Server.zhttps0_handler(self.module, '', self.cgienv) class WebDAVSourceServerFactory(HTTPServerFactory): M2Crypto-0.22.6rc4/demo/Zope27/instance_home/0000775000175000017500000000000012613362233020744 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/instance_home/etc/0000775000175000017500000000000012613362233021517 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/instance_home/etc/zope.conf.patch0000664000175000017500000000061212605232411024433 0ustar matejmatej00000000000000--- zope.conf.org Sat Sep 27 21:03:22 2003 +++ zope.conf Sat Sep 27 21:05:08 2003 @@ -650,6 +650,13 @@ # force-connection-close on + + # valid keys are "address", "force-connection-close" and "x509-remote-user" + address 8443 + # force-connection-close on + x509-remote-user on + + # valid key is "address" address 8021 M2Crypto-0.22.6rc4/demo/Zope27/instance_home/ssl/0000775000175000017500000000000012613362233021545 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/Zope27/instance_home/ssl/ca.pem0000664000175000017500000000230412605232411022625 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/Zope27/instance_home/ssl/dh1024.pem0000664000175000017500000000036512605232411023151 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/Zope27/instance_home/ssl/server.pem0000664000175000017500000000411012605232411023545 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/Zope27/instance_home/README.txt.patch0000664000175000017500000000044212605232411023533 0ustar matejmatej00000000000000--- README.txt.org Sat Sep 27 20:56:11 2003 +++ README.txt Sat Sep 27 20:56:44 2003 @@ -7,3 +7,4 @@ log/ Log files Products/ Installed products specific to the instance var/ Run-time data files, including the object database + ssl/ ZServerSSL data files M2Crypto-0.22.6rc4/demo/Zope27/INSTALL.txt0000664000175000017500000001213512605232411017774 0ustar matejmatej00000000000000========================================= ZServerSSL for Zope 2.7.0b2 ========================================= :Author: Ng Pheng Siong :Id: $Id$ :Date: $Date$ :Web-Site: http://sandbox.rulemaker.net/ngps/zope/zssl/ .. contents:: Directories ----------------------- This distribution is contained in ``m2crypto-0.12/demo/Zope27/``. Its directory structure assumes the following: - Zope 2.7.0b2 is installed in . - An instance has been created in . ----------------------- The following files are to be copied to the corresponding directories in your : - install_dir/lib/python/ZServer/HTTPS_Server.py - install_dir/lib/python/ZServer/medusa/https_server.py The following patch files are to be applied to the corresponding directories in your : - install_dir/lib/python/ZServer/__init__.py.patch - install_dir/lib/python/ZServer/component.xml.patch - install_dir/lib/python/ZServer/datatypes.py.patch ----------------------- The following files are to be copied to the corresponding directories in your : - instance_home/ssl/ca.pem - instance_home/ssl/server.pem - instance_home/ssl/dh1024.pem These are example files. For more information on them, consult the ZServerSSL HOWTO for Zope 2.6. The following patch files are to be applied to the corresponding directories in your : - instance_home/README.txt.patch - instance_home/etc/zope.conf.patch (Patching README.txt is optional.) There appears to be a bug in Zope 2.7.0b2, where INSTANCE_HOME in a running Zope points to , not . Workaround this with the following: :: $ (cd ; ln -s /ssl) Launch ZServerSSL ------------------- :: $ /bin/runzope Testing --------- Below, we assume your Zope server is running on ``localhost``. HTTPS ~~~~~~~ This testing is done with Mozilla 1.1 on FreeBSD. 1. With a browser, connect to https://localhost:8443/. Browse around. Check out your browser's HTTPS informational screens. 2. Connect to https://localhost:8443/manage. Verify that you can access Zope's management functionality. WebDAV-over-HTTPS ~~~~~~~~~~~~~~~~~~~ This testing is done with Cadaver 0.21.0 on FreeBSD. :: $ cadaver https://localhost:8443/ WARNING: Untrusted server certificate presented: Issued to: M2Crypto, SG Issued by: M2Crypto, SG Do you wish to accept the certificate? (y/n) y Authentication required for Zope on server `localhost': Username: admin Password: dav:/> ls Listing collection `/': succeeded. Coll: Control_Panel 0 Sep 28 00:38 Coll: temp_folder 0 Sep 28 17:30 acl_users 0 Sep 28 00:38 browser_id_manager 0 Sep 28 00:38 error_log 0 Sep 28 00:38 index_html 28 Sep 28 00:39 session_data_manager 0 Sep 28 00:38 standard_error_message 1189 Sep 28 00:39 standard_html_footer 18 Sep 28 00:39 standard_html_header 82 Sep 28 00:39 standard_template.pt 282 Sep 28 00:39 dav:/> quit Connection to `localhost' closed. $ Python with M2Crypto ~~~~~~~~~~~~~~~~~~~~~~ This testing is done with M2Crypto 0.12 and Python 2.2.3 on FreeBSD. HTTPS ``````` >>> from M2Crypto import Rand, SSL, m2urllib >>> url = m2urllib.FancyURLopener() >>> url.addheader('Connection', 'close') >>> u = url.open('https://127.0.0.1:8443/') send: 'GET / HTTP/1.1\r\nHost: 127.0.0.1:8443\r\nAccept-Encoding: identity\r\nUser-agent: Python-urllib/1.15\r\nConnection: close\r\n\r\n' reply: 'HTTP/1.1 200 OK\r\n' header: Server: ZServerSSL/0.12 header: Date: Sun, 28 Sep 2003 09:40:14 GMT header: Content-Length: 3055 header: Etag: header: Content-Type: text/html header: Connection: close >>> while 1: ... data = u.read() ... if not data: break ... print data ... :: [blah blah blah]

Go directly to the Zope Management Interface if you'd like to start working with Zope right away. NOTE: Some versions of Microsoft Internet Explorer, (specifically IE 5.01 and early versions of IE 5.5) may have problems displaying Zope management pages. If you cannot view the management pages, try upgrading your IE installation to the latest release version, or use a different browser.

  • Find out about Zope Corporation, the publishers of Zope.

  • >>> u.close() >>> XMLRPC-over-HTTPS ``````````````````` >>> from M2Crypto.m2xmlrpclib import Server, SSL_Transport >>> zs = Server('https://127.0.0.1:8443/', SSL_Transport()) >>> print zs.propertyMap() [{'type': 'string', 'id': 'title', 'mode': 'w'}] >>> Conclusion ------------ Yes, it works! ;-) M2Crypto-0.22.6rc4/demo/ZopeX3/0000775000175000017500000000000012613362233016172 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/0000775000175000017500000000000012613362233020476 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/0000775000175000017500000000000012613362233021244 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/0000775000175000017500000000000012613362233022565 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/0000775000175000017500000000000012613362233023542 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/app/0000775000175000017500000000000012613362233024322 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/app/server/0000775000175000017500000000000012613362233025630 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/app/server/configure.zcml.patch0000664000175000017500000000127512605232411031576 0ustar matejmatej00000000000000--- configure.zcml.org Mon Sep 27 16:10:47 2004 +++ configure.zcml Mon Sep 27 16:11:42 2004 @@ -5,6 +5,12 @@ provides="zope.app.applicationcontrol.interfaces.IServerControl" /> + + + + M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/app/server/https.py0000664000175000017500000000174012605232411027341 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2004, Ng Pheng Siong. # All Rights Reserved. # # XXX license TBD; should be Zope 3's ZPL, I just haven't read thru that. # ############################################################################## """HTTPS server factories $Id$ """ from zope.app.publication.httpfactory import HTTPPublicationRequestFactory from zope.app.server.servertype import ServerType from zope.server.http.commonaccesslogger import CommonAccessLogger from zope.server.http.publisherhttps_server import PMDBHTTPS_Server from zope.server.http.publisherhttps_server import PublisherHTTPS_Server https = ServerType(PublisherHTTPS_Server, HTTPPublicationRequestFactory, CommonAccessLogger, 8443, True) pmhttps = ServerType(PMDBHTTPS_Server, HTTPPublicationRequestFactory, CommonAccessLogger, 8376, True) M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/server/0000775000175000017500000000000012613362233025050 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/server/http/0000775000175000017500000000000012613362233026027 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/server/http/https_server.py0000664000175000017500000000706012607370517031143 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2004, Ng Pheng Siong. # All Rights Reserved. # # XXX license TBD; should be Zope 3's ZPL, I just haven't read thru that. # ############################################################################## """HTTPS Server This is a HTTPS version of HTTPServer. $Id$ """ import asyncore, logging, os.path from zope.server.http.httpserver import HTTPServer from zope.server.http.https_serverchannel import HTTPS_ServerChannel from M2Crypto import SSL, version # 2004-09-27, ngps: # 'sslv2' or 'sslv23' interoperates with Firefox and IE. # 'sslv3' or 'tlsv1' doesn't. def make_ssl_context(dir, ssl_proto='sslv23'): sslctx = SSL.Context(ssl_proto) sslctx.load_cert(os.path.join(dir, 'server.pem')) sslctx.load_verify_locations(os.path.join(dir, 'ca.pem')) sslctx.load_client_CA(os.path.join(dir, 'ca.pem')) sslctx.set_verify(SSL.verify_none, 10) sslctx.set_session_id_ctx('someblahblahthing') sslctx.set_tmp_dh(os.path.join(dir, 'dh1024.pem')) #sslctx.set_info_callback() # debugging only; not thread-safe return sslctx class HTTPS_Server(HTTPServer): """This is a generic HTTPS Server.""" channel_class = HTTPS_ServerChannel SERVER_IDENT = 'zope.server.zserverssl_https' def __init__(self, ip, port, ssl_ctx=None, task_dispatcher=None, adj=None, start=1, hit_log=None, verbose=0): HTTPServer.__init__(self, ip, port, task_dispatcher, adj, start, hit_log, verbose) if ssl_ctx is None: self.ssl_ctx = make_ssl_context(os.path.realpath(__file__)) else: self.ssl_ctx = ssl_ctx def executeRequest(self, task): """Execute an HTTP request.""" # This is a default implementation, meant to be overridden. body = "The HTTPS server is running!\r\n" * 10 task.response_headers['Content-Type'] = 'text/plain' task.response_headers['Content-Length'] = str(len(body)) task.write(body) def handle_accept(self): """See zope.server.interfaces.IDispatcherEventHandler""" try: v = self.accept() if v is None: return conn, addr = v except socket.error: # Linux: On rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. if self.adj.log_socket_errors: self.log_info ('warning: server accept() threw an exception', 'warning') return for (level, optname, value) in self.adj.socket_options: conn.setsockopt(level, optname, value) # Turn the vanilla socket into an SSL connection. try: ssl_conn = SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr, self.adj) except SSL.SSLError, why: self.log_info('accept: cannot make SSL connection %s' % (why,), 'warning') pass if __name__ == '__main__': from zope.server.taskthreads import ThreadedTaskDispatcher td = ThreadedTaskDispatcher() td.setThreadCount(4) HTTPS_Server('', 8443, ssl_ctx=None, task_dispatcher=td, verbose=1) try: import asyncore while 1: asyncore.poll(5) except KeyboardInterrupt: print 'shutting down...' td.shutdown() M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/server/http/https_serverchannel.py0000664000175000017500000000323312605232411032456 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2004, Ng Pheng Siong. # All Rights Reserved. # # XXX license TBD; should be Zope 3's ZPL, I just haven't read thru that. # ############################################################################## """HTTPS Server Channel $Id$ """ from zope.server.serverchannelbase import ServerChannelBase from zope.server.http.httptask import HTTPTask from zope.server.http.httprequestparser import HTTPRequestParser from zope.server.http.httpserverchannel import HTTPServerChannel from M2Crypto import SSL class HTTPS_ServerChannel(HTTPServerChannel): """HTTPS-specific Server Channel""" task_class = HTTPTask parser_class = HTTPRequestParser def send(self, data): try: result = self.socket._write_nbio(data) if result <= 0: return 0 else: #self.server.bytes_out.increment(result) return result except SSL.SSLError, why: self.close() self.log_info('send: closing channel %s %s' % (repr(self), why), 'warning') return 0 def recv(self, buffer_size): try: result = self.socket._read_nbio(buffer_size) if result is None: return '' elif result == '': self.close() return '' else: #self.server.bytes_in.increment(len(result)) return result except SSL.SSLError, why: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), why), 'warning') return '' M2Crypto-0.22.6rc4/demo/ZopeX3/install_dir/lib/python/zope/server/http/publisherhttps_server.py0000664000175000017500000000532612605232411033050 0ustar matejmatej00000000000000############################################################################## # # Copyright (c) 2004, Ng Pheng Siong. # All Rights Reserved. # # XXX license TBD; should be Zope 3's ZPL, I just haven't read thru that. # ############################################################################## """HTTPS Server that uses the Zope Publisher for executing a task. $Id$ """ import os.path, sys from zope.server.http.https_server import HTTPS_Server, make_ssl_context from zope.publisher.publish import publish def get_instance_ssldir(): # This is real cheesy: It seems Zope3 doesn't have convenient # programmatic access to INSTANCE_HOME. This code relies on zopectl # setting the first entry of PYTHONPATH to $INSTANCE_HOME/lib/python. return os.path.join(os.path.dirname(os.path.dirname(sys.path[0])), 'ssl') class PublisherHTTPS_Server(HTTPS_Server): """Zope Publisher-specific HTTPS Server""" def __init__(self, request_factory, sub_protocol=None, *args, **kw): # The common HTTP self.request_factory = request_factory # An HTTP server is not limited to serving up HTML; it can be # used for other protocols, like XML-RPC, SOAP and so as well # Here we just allow the logger to output the sub-protocol type. if sub_protocol: self.SERVER_IDENT += ' (%s)' %str(sub_protocol) kw['ssl_ctx'] = make_ssl_context(get_instance_ssldir()) HTTPS_Server.__init__(self, *args, **kw) def executeRequest(self, task): """Overrides HTTPServer.executeRequest().""" env = task.getCGIEnvironment() env['HTTPS'] = 'ON' try: del env['HTTP'] except KeyError: pass instream = task.request_data.getBodyStream() request = self.request_factory(instream, task, env) response = request.response response.setHeaderOutput(task) response.setHTTPTransaction(task) publish(request) class PMDBHTTPS_Server(PublisherHTTPS_Server): """Enter the post-mortem debugger when there's an error""" def executeRequest(self, task): """Overrides HTTPServer.executeRequest().""" env = task.getCGIEnvironment() env['HTTPS'] = 'ON' try: del env['HTTP'] except KeyError: pass instream = task.request_data.getBodyStream() request = self.request_factory(instream, task, env) response = request.response response.setHeaderOutput(task) try: publish(request, handle_errors=False) except: import sys, pdb print "%s:" % sys.exc_info()[0] print sys.exc_info()[1] pdb.post_mortem(sys.exc_info()[2]) raise M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/0000775000175000017500000000000012613362233021006 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/etc/0000775000175000017500000000000012613362233021561 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/etc/zope.conf.patch0000664000175000017500000000110212605232411024470 0ustar matejmatej00000000000000--- zope.conf.org Tue Sep 28 09:49:02 2004 +++ zope.conf Tue Sep 28 09:49:27 2004 @@ -20,6 +20,11 @@ address 8080 + + type HTTPS + address 8443 + + # For debugging purposes, you can use this publisher instead/as well # (obviously if it's as well, use a different port number). If there's # an exception, Zope will drop into pdb at the point of the exception. @@ -27,6 +32,11 @@ # # type PostmortemDebuggingHTTP # address 8080 +# +# +# +# type PostmortemDebuggingHTTPS +# address 8443 # M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/ssl/0000775000175000017500000000000012613362233021607 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/ssl/ca.pem0000664000175000017500000000230412605232411022667 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/ssl/dh1024.pem0000664000175000017500000000036512605232411023213 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/ZopeX3/instance_home/ssl/server.pem0000664000175000017500000000411012605232411023607 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/ZopeX3/INSTALL.txt0000664000175000017500000000302612605232411020035 0ustar matejmatej00000000000000========================================= ZServerSSL for ZopeX3.0.0 ========================================= :Author: Ng Pheng Siong :Id: $Id$ :Date: $Date$ :Web-Site: http://sandbox.rulemaker.net/ngps/zope/zssl/ .. contents:: Directories ----------------------- Directory structure assumes the following: - ZopeX3.0.0 is installed in . - An instance has been created in . ----------------------- The following files are to be copied to the corresponding directories in your : - install_dir/lib/python/zope/server/http/https_server.py - install_dir/lib/python/zope/server/http/https_serverchannel.py - install_dir/lib/python/zope/server/http/publisherhttps_server.py - install_dir/lib/python/zope/app/server/https.py ----------------------- The following files are to be copied to the corresponding directories in your : - instance_home/ssl/ca.pem - instance_home/ssl/server.pem - instance_home/ssl/dh1024.pem These are example files. For more information on them, consult the ZServerSSL HOWTO for Zope 2.6. The following patch files are to be applied to the corresponding directories: - install_dir/lib/python/zope/app/server/configure.zcml.patch - instance_home/etc/zope.conf.patch Launch ZServerSSL ------------------- :: $ /bin/runzope Testing --------- This section TDB. I have tested ZServerSSL for Zope 3 with 'openssl s_client' and 'openssl s_client -nbio' successfully. Conclusion ------------ Yes, it works! ;-) M2Crypto-0.22.6rc4/demo/ec/0000775000175000017500000000000012613362233015431 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ec/ecdhtest.py0000664000175000017500000000142212607370517017614 0ustar matejmatej00000000000000#!/usr/bin/env python """ECDH demonstration. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved.""" from M2Crypto import EC,Rand def test(): print 'generating ec keys:' a=EC.gen_params(EC.NID_sect233k1) a.gen_key() b=EC.gen_params(EC.NID_sect233k1) b.gen_key() a_shared_key = a.compute_dh_key(b.pub()) b_shared_key = b.compute_dh_key(a.pub()) print 'shared key according to a = ', `a_shared_key` print 'shared key according to b = ', `b_shared_key` if a_shared_key == b_shared_key: print 'ok' else: print 'not ok' if __name__=='__main__': Rand.load_file('randpool.dat', -1) test() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/ec/ecdsa_bench.py0000664000175000017500000003062212613276364020235 0ustar matejmatej00000000000000#!/usr/bin/env python """ ECDSA demo and benchmark. Usage: python -O ecdsa_bench.py [option option option ...] where options may include: makenewkey showpubkey showdigest showprofile md5 sha1 sha256 sha512 secp160r1 secp224r1 secp192k1 sect283r1 sect283k1 secp256k1 secp384r1 secp521r1 (other curves and hashes are supported, see below) Larry Bugbee, June 2006 Portions: Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Copyright (c) 2005 Vrije Universiteit Amsterdam. All rights reserved. """ from M2Crypto import EC, EVP, Rand from M2Crypto.EVP import MessageDigest import sys, base64 # -------------------------------------------------------------- # program parameters makenewkey = 0 # 1 = make/save new key, 0 = use existing showpubkey = 0 # 1 = show the public key value showdigest = 0 # 1 = show the digest value showprofile = 0 # 1 = use the python profiler hashalgs = ['md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'] curves = ['secp112r1', 'secp112r2', 'secp128r1', 'secp128r2', 'secp160k1', 'secp160r1', 'secp160r2', 'secp192k1', 'secp224k1', 'secp224r1', 'secp256k1', 'secp384r1', 'secp521r1', 'sect113r1', 'sect113r2', 'sect131r1', 'sect131r2', 'sect163k1', 'sect163r1', 'sect163r2', 'sect193r1', 'sect193r2', 'sect233k1', 'sect233r1', 'sect239k1', 'sect283k1', 'sect283r1', 'sect409k1', 'sect409r1', 'sect571k1', 'sect571r1', 'X9_62_prime192v1', 'X9_62_prime192v2', 'X9_62_prime192v3', 'X9_62_prime239v1', 'X9_62_prime239v2', 'X9_62_prime239v3', 'X9_62_prime256v1', 'X9_62_c2pnb163v1', 'X9_62_c2pnb163v2', 'X9_62_c2pnb163v3', 'X9_62_c2pnb176v1', 'X9_62_c2tnb191v1', 'X9_62_c2tnb191v2', 'X9_62_c2tnb191v3', 'X9_62_c2pnb208w1', 'X9_62_c2tnb239v1', 'X9_62_c2tnb239v2', 'X9_62_c2tnb239v3', 'X9_62_c2pnb272w1', 'X9_62_c2pnb304w1', 'X9_62_c2tnb359v1', 'X9_62_c2pnb368w1', 'X9_62_c2tnb431r1', 'wap_wsg_idm_ecid_wtls1', 'wap_wsg_idm_ecid_wtls3', 'wap_wsg_idm_ecid_wtls4', 'wap_wsg_idm_ecid_wtls5', 'wap_wsg_idm_ecid_wtls6', 'wap_wsg_idm_ecid_wtls7', 'wap_wsg_idm_ecid_wtls8', 'wap_wsg_idm_ecid_wtls9', 'wap_wsg_idm_ecid_wtls10', 'wap_wsg_idm_ecid_wtls11', 'wap_wsg_idm_ecid_wtls12', ] # The following two curves, according to OpenSSL, have a # "Questionable extension field!" and are not supported by # the OpenSSL inverse function. ECError: no inverse. # As such they cannot be used for signing. They might, # however, be usable for encryption but that has not # been tested. Until thir usefulness can be established, # they are not supported at this time. # # Oakley-EC2N-3: # IPSec/IKE/Oakley curve #3 over a 155 bit binary field. # Oakley-EC2N-4: # IPSec/IKE/Oakley curve #4 over a 185 bit binary field. # # aka 'ipsec3' and 'ipsec4' # curves2 is a shorthand convenience so as to not require the # entering the "X9_62_" prefix curves2 = ['prime192v1', 'prime192v2', 'prime192v3', 'prime239v1', 'prime239v2', 'prime239v3', 'prime256v1', 'c2pnb163v1', 'c2pnb163v2', 'c2pnb163v3', 'c2pnb176v1', 'c2tnb191v1', 'c2tnb191v2', 'c2tnb191v3', 'c2pnb208w1', 'c2tnb239v1', 'c2tnb239v2', 'c2tnb239v3', 'c2pnb272w1', 'c2pnb304w1', 'c2tnb359v1', 'c2pnb368w1', 'c2tnb431r1', ] # default hashing algorithm hashalg = 'sha1' # default elliptical curve curve = 'secp160r1' # for a complete list of supported algorithms and curves, see # the bottom of this file # number of speed test loops N1 = N2 = 100 # -------------------------------------------------------------- # functions def test(ec, dgst): print ' testing signing and verification...', try: # ec = EC.gen_params(EC.NID_secp160r1) # ec.gen_key() r,s = ec.sign_dsa(dgst) except Exception, e: print '\n\n *** %s *** \n' % e sys.exit() if not ec.verify_dsa(dgst, r, s): print 'not ok' else: print 'ok' def test_asn1(ec, dgst): print ' testing asn1 signing and verification...', blob = ec.sign_dsa_asn1(dgst) if not ec.verify_dsa_asn1(dgst, blob): print 'not ok' else: print 'ok' def speed(): from time import time t1 = time() for i in range(N1): r,s = ec.sign_dsa(dgst) print ' %d signings: %8.2fs' % (N1, (time() - t1)) t1 = time() for i in range(N2): ec.verify_dsa(dgst, r, s) print ' %d verifications: %8.2fs' % (N2, (time() - t1)) def test_speed(ec, dgst): print ' measuring speed...' if showprofile: import profile profile.run('speed()') else: speed() print # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def main(curve, hashalg): global ec, dgst # this exists ONLY for speed testing Rand.load_file('randpool.dat', -1) if curve in curves2: curve = 'X9_62_' + curve ec_curve = eval('EC.NID_%s' % curve) pvtkeyfilename = '%spvtkey.pem' % (curve) pubkeyfilename = '%spubkey.pem' % (curve) if makenewkey: print ' making and saving a new key' ec = EC.gen_params(ec_curve) ec.gen_key() ec.save_key(pvtkeyfilename, None ) ec.save_pub_key(pubkeyfilename) else: print ' loading an existing key' ec=EC.load_key(pvtkeyfilename) print ' ecdsa key length:', len(ec) print ' curve: %s' % curve if not ec.check_key(): raise 'key is not initialised' if showpubkey: ec_pub = ec.pub() pub_der = ec_pub.get_der() pub_pem = base64.encodestring(pub_der) print ' PEM public key is: \n',pub_pem # since we are testing signing and verification, let's not # be fussy about the digest. Just make one. md = EVP.MessageDigest(hashalg) md.update('can you spell subliminal channel?') dgst = md.digest() print ' hash algorithm: %s' % hashalg if showdigest: print ' %s digest: \n%s' % (base64.encodestring(dgst)) test(ec, dgst) # test_asn1(ec, dgst) test_speed(ec, dgst) Rand.save_file('randpool.dat') # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def print_usage(): print """ Usage: python -O %s [option option option ...] where options may include: makenewkey showpubkey showdigest showprofile md5 sha1 sha256 sha512 secp160r1 secp224r1 secp192k1 sect283r1 sect283k1 secp256k1 secp384r1 secp521r1 (other curves and hashes are supported, check pgm src) """ % sys.argv[0] sys.exit() # -------------------------------------------------------------- # -------------------------------------------------------------- if __name__=='__main__': for arg in sys.argv[1:]: if arg in hashalgs: hashalg = arg; continue if arg in curves + curves2: curve = arg; continue if arg == 'makenewkey': makenewkey = 1; continue if arg == 'showpubkey': showpubkey = 1; continue if arg == 'showdigest': showdigest = 1; continue if arg == 'showprofile': showprofile = 1; continue print '\n *** argument "%s" not understood ***' % arg print_usage() main(curve, hashalg) # -------------------------------------------------------------- # -------------------------------------------------------------- # -------------------------------------------------------------- """ Elliptical curves supported by OpenSSL ====================================== $ openssl ecparam -list_curves secp112r1 : SECG/WTLS curve over a 112 bit prime field secp112r2 : SECG curve over a 112 bit prime field secp128r1 : SECG curve over a 128 bit prime field secp128r2 : SECG curve over a 128 bit prime field secp160k1 : SECG curve over a 160 bit prime field secp160r1 : SECG curve over a 160 bit prime field secp160r2 : SECG/WTLS curve over a 160 bit prime field secp192k1 : SECG curve over a 192 bit prime field secp224k1 : SECG curve over a 224 bit prime field secp224r1 : NIST/SECG curve over a 224 bit prime field secp256k1 : SECG curve over a 256 bit prime field secp384r1 : NIST/SECG curve over a 384 bit prime field secp521r1 : NIST/SECG curve over a 521 bit prime field prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field prime192v2: X9.62 curve over a 192 bit prime field prime192v3: X9.62 curve over a 192 bit prime field prime239v1: X9.62 curve over a 239 bit prime field prime239v2: X9.62 curve over a 239 bit prime field prime239v3: X9.62 curve over a 239 bit prime field prime256v1: X9.62/SECG curve over a 256 bit prime field sect113r1 : SECG curve over a 113 bit binary field sect113r2 : SECG curve over a 113 bit binary field sect131r1 : SECG/WTLS curve over a 131 bit binary field sect131r2 : SECG curve over a 131 bit binary field sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field sect163r1 : SECG curve over a 163 bit binary field sect163r2 : NIST/SECG curve over a 163 bit binary field sect193r1 : SECG curve over a 193 bit binary field sect193r2 : SECG curve over a 193 bit binary field sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field sect239k1 : SECG curve over a 239 bit binary field sect283k1 : NIST/SECG curve over a 283 bit binary field sect283r1 : NIST/SECG curve over a 283 bit binary field sect409k1 : NIST/SECG curve over a 409 bit binary field sect409r1 : NIST/SECG curve over a 409 bit binary field sect571k1 : NIST/SECG curve over a 571 bit binary field sect571r1 : NIST/SECG curve over a 571 bit binary field c2pnb163v1: X9.62 curve over a 163 bit binary field c2pnb163v2: X9.62 curve over a 163 bit binary field c2pnb163v3: X9.62 curve over a 163 bit binary field c2pnb176v1: X9.62 curve over a 176 bit binary field c2tnb191v1: X9.62 curve over a 191 bit binary field c2tnb191v2: X9.62 curve over a 191 bit binary field c2tnb191v3: X9.62 curve over a 191 bit binary field c2pnb208w1: X9.62 curve over a 208 bit binary field c2tnb239v1: X9.62 curve over a 239 bit binary field c2tnb239v2: X9.62 curve over a 239 bit binary field c2tnb239v3: X9.62 curve over a 239 bit binary field c2pnb272w1: X9.62 curve over a 272 bit binary field c2pnb304w1: X9.62 curve over a 304 bit binary field c2tnb359v1: X9.62 curve over a 359 bit binary field c2pnb368w1: X9.62 curve over a 368 bit binary field c2tnb431r1: X9.62 curve over a 431 bit binary field wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field wap-wsg-idm-ecid-wtls12: WTLS curvs over a 224 bit prime field Oakley-EC2N-3: IPSec/IKE/Oakley curve #3 over a 155 bit binary field. Not suitable for ECDSA. Questionable extension field! Oakley-EC2N-4: IPSec/IKE/Oakley curve #4 over a 185 bit binary field. Not suitable for ECDSA. Questionable extension field! """ M2Crypto-0.22.6rc4/demo/ec/ecdsatest.pem0000664000175000017500000000032312605232411020104 0ustar matejmatej00000000000000-----BEGIN EC PRIVATE KEY----- MG0CAQEEHVkQ54w5gN39TScPaC+TTKmJunupCfuNqEcWOZeXoAcGBSuBBAAaoUAD PgAEAIcWBNwIi1fP2Sd33wpayKBuw2oqBVvgvfYiipMcASzxCf6IFUC03IOob/Lu Y3mPHRZKwzSKBlD1ZkXh -----END EC PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/ec/ecdsatest.py0000664000175000017500000000302212607370517017766 0ustar matejmatej00000000000000#!/usr/bin/env python """ECDSA demonstration. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved. """ from M2Crypto import EC, EVP, Rand import base64 md=EVP.MessageDigest('sha1') md.update('can you spell subliminal channel?') dgst=md.digest() ec=EC.load_key('ecdsatest.pem') #ec=EC.gen_params(EC.NID_sect233k1) #ec.gen_key() ec_pub = ec.pub() pub_der = ec_pub.get_der() pub_pem = base64.encodestring(pub_der) print 'PEM public key is',pub_pem ec.save_key( 'ecdsatest.pem', None ) def test(): print 'testing signing...', r,s=ec.sign_dsa(dgst) if not ec.verify_dsa(dgst, r, s): print 'not ok' else: print 'ok' def test_asn1(): # XXX Randomly fails: bug in there somewhere... (0.9.4) print 'testing asn1 signing...', blob=ec.sign_dsa_asn1(dgst) if not ec.verify_dsa_asn1(dgst, blob): print 'not ok' else: print 'ok' def speed(): from time import time N1 = 5242 N2 = 2621 t1 = time() for i in range(N1): r,s = ec.sign(dgst) print '%d signings: %8.2fs' % (N1, (time() - t1)) t1 = time() for i in range(N2): ec.verify(dgst, r, s) print '%d verifications: %8.2fs' % (N2, (time() - t1)) def test_speed(): print 'measuring speed...' import profile profile.run('speed()') if __name__=='__main__': Rand.load_file('randpool.dat', -1) test() test_asn1() #test_speed() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/ec/secp160r1pvtkey.pem0000664000175000017500000000025612605232411021021 0ustar matejmatej00000000000000-----BEGIN EC PRIVATE KEY----- MFACAQEEFN1C7AYNKDl9dBLfm0QW1nB7WGs7oAcGBSuBBAAIoSwDKgEErnCVbfXH 11Ax4AZq4eh8c3gWIBeaRu6tGRpITFCjtHot78c/oVqBrg== -----END EC PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/https.howto/0000775000175000017500000000000012613362233017343 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/https.howto/ca.pem0000664000175000017500000000563712605232411020437 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: 0 (0x0) Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=CA, O=M2Crypto CA, CN=localhost Validity Not Before: Apr 22 04:35:56 2006 GMT Not After : Apr 21 04:35:56 2009 GMT Subject: C=US, ST=CA, O=M2Crypto CA, CN=localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:d8:80:02:8f:b5:7d:9f:9b:79:76:67:a5:66:64: c0:30:0c:71:65:f1:c6:78:01:a0:29:d4:3a:2c:e5: ee:58:4d:db:53:c5:74:6e:4e:f7:b6:a5:8e:ef:ab: e8:7c:f5:5d:2d:18:ba:95:b8:15:43:6e:5a:78:c2: 91:05:08:b2:7e:cf:c4:d3:bb:ac:c7:43:27:fb:8f: 43:0d:7b:d0:d1:32:51:86:11:6e:3e:aa:68:19:88: b9:cf:d5:72:f0:a4:73:d1:69:c4:65:14:0e:12:64: 7e:1f:df:18:09:0b:6a:4b:cd:bf:ae:59:82:15:1c: 90:0f:c3:e5:cb:b3:ed:86:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:TRUE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 5C:F9:C5:9B:B0:02:37:3C:66:73:4D:0E:CB:5A:3D:BB:3A:46:22:DD X509v3 Authority Key Identifier: keyid:5C:F9:C5:9B:B0:02:37:3C:66:73:4D:0E:CB:5A:3D:BB:3A:46:22:DD Signature Algorithm: sha1WithRSAEncryption 6b:9e:71:4a:ad:d2:1c:b7:58:1a:6e:8b:89:92:8d:4e:62:61: 06:2e:e8:11:f8:9c:a0:e2:11:7c:b6:e2:be:ef:b9:b1:35:20: d1:81:62:c5:ca:3c:4f:c9:88:72:f7:50:d8:e8:e0:06:43:ee: c5:5c:38:9b:e7:24:46:a6:ee:8d:b0:70:4e:75:96:00:db:d6: 59:f9:58:74:67:9f:ca:9c:12:fc:77:a7:0e:5a:38:22:5b:de: c9:33:35:bd:d0:4c:9f:6a:0f:71:7b:db:cb:fd:da:bc:39:4f: 23:1e:74:5b:ff:8d:73:72:16:a9:9f:57:54:96:3e:2c:f0:65: af:df -----BEGIN CERTIFICATE----- MIICfDCCAeWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEL MAkGA1UECBMCQ0ExFDASBgNVBAoTC00yQ3J5cHRvIENBMRIwEAYDVQQDEwlsb2Nh bGhvc3QwHhcNMDYwNDIyMDQzNTU2WhcNMDkwNDIxMDQzNTU2WjBEMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFDASBgNVBAoTC00yQ3J5cHRvIENBMRIwEAYDVQQD Ewlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANiAAo+1fZ+b eXZnpWZkwDAMcWXxxngBoCnUOizl7lhN21PFdG5O97alju+r6Hz1XS0YupW4FUNu WnjCkQUIsn7PxNO7rMdDJ/uPQw170NEyUYYRbj6qaBmIuc/VcvCkc9FpxGUUDhJk fh/fGAkLakvNv65ZghUckA/D5cuz7YZNAgMBAAGjfjB8MAwGA1UdEwQFMAMBAf8w LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G A1UdDgQWBBRc+cWbsAI3PGZzTQ7LWj27OkYi3TAfBgNVHSMEGDAWgBRc+cWbsAI3 PGZzTQ7LWj27OkYi3TANBgkqhkiG9w0BAQUFAAOBgQBrnnFKrdIct1gabouJko1O YmEGLugR+Jyg4hF8tuK+77mxNSDRgWLFyjxPyYhy91DY6OAGQ+7FXDib5yRGpu6N sHBOdZYA29ZZ+Vh0Z5/KnBL8d6cOWjgiW97JMzW90Eyfag9xe9vL/dq8OU8jHnRb /41zchapn1dUlj4s8GWv3w== -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/https.howto/dh1024.pem0000664000175000017500000000036512605232411020747 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/https.howto/get_https.py0000775000175000017500000000154612607370517021736 0ustar matejmatej00000000000000#!/usr/bin/env python """Demonstrations of M2Crypto.httpslib. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2006 OSAF. All Rights Reserved. """ from M2Crypto import Rand, SSL, httpslib def get_https(): ctx = SSL.Context() if ctx.load_verify_locations('ca.pem') != 1: raise Exception('CA certificates not loaded') ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) h = httpslib.HTTPSConnection('localhost', 9443, ssl_context=ctx) h.set_debuglevel(1) h.putrequest('GET', '/') h.endheaders() resp = h.getresponse() while 1: data = resp.read() if not data: break print data h.close() Rand.load_file('../randpool.dat', -1) get_https() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/https.howto/https_cli.py0000664000175000017500000000242212607370517021715 0ustar matejmatej00000000000000#!/usr/bin/env python """Demonstrations of M2Crypto.httpslib. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2006 OSAF. All Rights Reserved. """ import sys from M2Crypto import Rand, SSL, httpslib, threading def test_httpslib(): ctx = SSL.Context() if ctx.load_verify_locations('ca.pem') != 1: raise Exception('CA certificates not loaded') ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.set_info_callback() h = httpslib.HTTPSConnection('localhost', 9443, ssl_context=ctx) h.set_debuglevel(1) h.putrequest('GET', '/') h.putheader('Accept', 'text/html') h.putheader('Accept', 'text/plain') h.putheader('Connection', 'close') h.endheaders() resp = h.getresponse() f = resp.fp c = 0 while 1: # Either of following two works. #data = f.readline() data = resp.read() if not data: break c = c + len(data) sys.stdout.write(data) sys.stdout.flush() f.close() h.close() if __name__=='__main__': Rand.load_file('../randpool.dat', -1) #threading.init() test_httpslib() #threading.cleanup() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/https.howto/orig_https_srv.py0000664000175000017500000001073512607370517023006 0ustar matejmatej00000000000000"""This server extends BaseHTTPServer and SimpleHTTPServer thusly: 1. One thread per connection. 2. Generates directory listings. In addition, it has the following properties: 1. Works over HTTPS only. 2. Displays SSL handshaking and SSL session info. 3. Performs SSL renegotiation when a magic url is requested. TODO: 1. Cache stat() of directory entries. 2. Fancy directory indexing. 3. Interface ZPublisher. Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2006 OSAF. All Rights Reserved. """ import os, sys from SimpleHTTPServer import SimpleHTTPRequestHandler from M2Crypto import Rand, SSL, threading from M2Crypto.SSL.SSLServer import ThreadingSSLServer try: from cStringIO import StringIO except ImportError: from StringIO import StringIO def mkdirlist(path, url): dirlist = os.listdir(path) dirlist.sort() f = StringIO() f.write('Index listing for %s\r\n' % (url,)) f.write('

    Index listing for %s

    \r\n' % (url,)) f.write('
    \r\n')
        for d in dirlist:
            if os.path.isdir(os.path.join(path, d)):
                d2 = d + '/'
            else:
                d2 = d
            if url == '/':
                f.write('%s
    \r\n' % (d, d2)) else: f.write('%s
    \r\n' % (url, d, d2)) f.write('
    \r\n\r\n') f.reset() return f class HTTP_Handler(SimpleHTTPRequestHandler): server_version = "https_srv/0.1" reneg = 0 # Cribbed from SimpleHTTPRequestHander to add the ".der" entry, # which facilitates installing your own certificates into browsers. extensions_map = { '': 'text/plain', # Default, *must* be present '.html': 'text/html', '.htm': 'text/html', '.gif': 'image/gif', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.der': 'application/x-x509-ca-cert' } def send_head(self): if self.path[1:8] == '_reneg_': self.reneg = 1 self.path = self.path[8:] path = self.translate_path(self.path) if os.path.isdir(path): f = mkdirlist(path, self.path) filetype = 'text/html' else: try: f = open(path, 'rb') filetype = self.guess_type(path) except IOError: self.send_error(404, "File not found") return None self.send_response(200) self.send_header("Content-type", filetype) self.end_headers() return f def do_GET(self): #sess = self.request.get_session() #self.log_message('\n%s', sess.as_text()) f = self.send_head() if self.reneg: self.reneg = 0 self.request.renegotiate() sess = self.request.get_session() self.log_message('\n%s', sess.as_text()) if f: self.copyfile(f, self.wfile) f.close() def do_HEAD(self): #sess = self.request.get_session() #self.log_message('\n%s', sess.as_text()) f = self.send_head() if f: f.close() class HTTPS_Server(ThreadingSSLServer): def __init__(self, server_addr, handler, ssl_ctx): ThreadingSSLServer.__init__(self, server_addr, handler, ssl_ctx) self.server_name = server_addr[0] self.server_port = server_addr[1] def finish(self): self.request.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN) self.request.close() def init_context(protocol, certfile, cafile, verify, verify_depth=10): ctx=SSL.Context(protocol) ctx.load_cert(certfile) ctx.load_client_ca(cafile) if ctx.load_verify_locations(cafile) != 1: raise Exception('CA certificates not loaded') ctx.set_verify(verify, verify_depth) ctx.set_allow_unknown_ca(1) ctx.set_session_id_ctx('https_srv') ctx.set_info_callback() return ctx if __name__ == '__main__': if len(sys.argv) < 2: wdir = '.' else: wdir = sys.argv[1] Rand.load_file('../randpool.dat', -1) threading.init() ctx = init_context('sslv23', 'server.pem', 'ca.pem', \ SSL.verify_none) #SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) ctx.set_tmp_dh('dh1024.pem') os.chdir(wdir) httpsd = HTTPS_Server(('', 9443), HTTP_Handler, ctx) httpsd.serve_forever() threading.cleanup() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/https.howto/server.pem0000664000175000017500000000743312605232411021356 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=CA, O=M2Crypto CA, CN=localhost Validity Not Before: Apr 22 04:36:56 2006 GMT Not After : Apr 22 04:36:56 2007 GMT Subject: C=US, ST=CA, O=M2Crypto Server, CN=localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:a5:cc:39:ad:ba:81:3d:bd:05:f4:61:50:9f:9c: f6:ad:ec:29:d9:78:1e:24:61:f7:1b:36:bf:69:d8: b3:45:ae:6f:3a:4c:4f:d6:13:6d:60:8d:f2:bb:2a: c4:1b:79:fd:e2:f8:d6:3c:56:53:3b:27:f7:3f:70: a4:64:99:63:46:2e:3f:ef:52:da:a9:04:5b:6e:d4: 40:57:c5:59:61:d3:3f:7d:b8:03:c1:9b:65:46:2a: c5:9d:70:b7:ca:79:6e:dd:e4:3f:c2:f4:2f:2e:81: 32:c8:e9:a6:b6:a8:c8:1f:48:be:7a:66:56:98:fc: 3c:25:fc:d9:3d:73:07:30:71 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: F0:48:3A:32:88:8C:80:D7:22:AB:56:F8:86:B3:04:47:10:76:37:BE X509v3 Authority Key Identifier: keyid:5C:F9:C5:9B:B0:02:37:3C:66:73:4D:0E:CB:5A:3D:BB:3A:46:22:DD Signature Algorithm: sha1WithRSAEncryption 39:47:95:5c:ea:7e:db:b8:e0:80:f6:e5:d4:9f:83:bc:41:89: 31:97:c8:a4:95:0d:5d:6d:cc:64:8d:19:71:17:75:4b:7f:fb: 35:88:bf:68:e2:a2:be:c5:71:71:56:2a:92:31:25:2a:4b:98: 4e:77:42:45:78:45:21:a5:76:99:92:39:32:7d:a2:4c:38:b0: f1:db:7f:d1:4d:23:99:35:1e:0e:a1:59:a3:ff:9c:51:ef:4c: 11:c9:32:61:38:11:7d:57:2a:81:9a:96:1f:b3:88:f7:ab:5b: 58:f7:79:9b:a8:e3:b7:09:90:8e:c9:7d:44:4f:af:85:dc:c8: 29:4d -----BEGIN CERTIFICATE----- MIICfTCCAeagAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEL MAkGA1UECBMCQ0ExFDASBgNVBAoTC00yQ3J5cHRvIENBMRIwEAYDVQQDEwlsb2Nh bGhvc3QwHhcNMDYwNDIyMDQzNjU2WhcNMDcwNDIyMDQzNjU2WjBIMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExGDAWBgNVBAoTD00yQ3J5cHRvIFNlcnZlcjESMBAG A1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClzDmt uoE9vQX0YVCfnPat7CnZeB4kYfcbNr9p2LNFrm86TE/WE21gjfK7KsQbef3i+NY8 VlM7J/c/cKRkmWNGLj/vUtqpBFtu1EBXxVlh0z99uAPBm2VGKsWdcLfKeW7d5D/C 9C8ugTLI6aa2qMgfSL56ZlaY/Dwl/Nk9cwcwcQIDAQABo3sweTAJBgNVHRMEAjAA MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd BgNVHQ4EFgQU8Eg6MoiMgNciq1b4hrMERxB2N74wHwYDVR0jBBgwFoAUXPnFm7AC Nzxmc00Oy1o9uzpGIt0wDQYJKoZIhvcNAQEFBQADgYEAOUeVXOp+27jggPbl1J+D vEGJMZfIpJUNXW3MZI0ZcRd1S3/7NYi/aOKivsVxcVYqkjElKkuYTndCRXhFIaV2 mZI5Mn2iTDiw8dt/0U0jmTUeDqFZo/+cUe9MEckyYTgRfVcqgZqWH7OI96tbWPd5 m6jjtwmQjsl9RE+vhdzIKU0= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQClzDmtuoE9vQX0YVCfnPat7CnZeB4kYfcbNr9p2LNFrm86TE/W E21gjfK7KsQbef3i+NY8VlM7J/c/cKRkmWNGLj/vUtqpBFtu1EBXxVlh0z99uAPB m2VGKsWdcLfKeW7d5D/C9C8ugTLI6aa2qMgfSL56ZlaY/Dwl/Nk9cwcwcQIDAQAB AoGBAIwzbZbePsnxXOaxoBbJCcQ7D4yJSZvkh6womKauC7Lh9carn1tc5EIg5uCl Il5Fw466c5dkPE+q1SZ9X1Z+avYh4ypHjpcr1Lfvwo0wfOBx5MBj6ppMdwgrMXuo jRChK3gBZXmKaIH19h/sGp/lZRW2HiX63aN11KDmtfwo6Bq9AkEA2OftYJUqceK3 /E8q6OE1oQLm+oK6CPZ29A5TRNOadRu1opDR/y59GcUQ5ebJNH8DXyF82lSi3DKt SNoSOF32cwJBAMOuKGUAwnq1yH3q+MAF7CZjGou7Ar6VRseyLnD5nttynT85QRW8 N/WCosKLhV7wi9kKJmHGUJfRAqdo14D8IIsCQQCVjrU6FyABDpZVvjCUClT0BBBH QsQLUgWLGiWIG28wuD5xLPHexas0jZCtNIgfTkSA35I66Iiy065vwQ03GHLJAkAG eGC/jjngAtjBSR62grufPVGoYyOhF6CCg+LDO43EJdMLPyJmzJVxGcO1+RUM4ZlO MOa5/uu1SWT0EiRmEHAnAkBusVcHcd6d4uaoiCybIhF4hL4GsbKoImIciakNlteA c1RZZHc2jzO/Ihoz50H1njXwY86YbjncOXw8shtayd8j -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/medusa/0000775000175000017500000000000012613362233016320 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/medusa/00_README0000664000175000017500000000147112605232411017475 0ustar matejmatej00000000000000 19 Sep 2001 ------------- M2Crypto HTTPS and FTP/TLS servers All the files in this directory are from the Apr 2001 release of Medusa, except for the following: - 00_README (this file) - server.pem, the server's certificate - ca.pem, my CA certificate - https_server.py - ftps_server.py - START.py - START_xmlrpc.py - index.html, a sample HTML file - poison_handler.py, a webpoison clone By default, http_server listens on port 9080 and https_server port 9443. Document root is current directory, and serves up index.html. The xmlrpc server is accessible below '/RPC2'. It requires Fredrik Lundh's xmlrpc_handler on PYTHONPATH. The FTP/TLS server listens on port 9021 by default. I've only tested it with the 'anonymous' authentication handler. Medusa files are copyright Sam Rushing. My files are copyright me. M2Crypto-0.22.6rc4/demo/medusa/START.py0000664000175000017500000000346012607370517017601 0ustar matejmatej00000000000000#!/usr/bin/env python # Standard Python library import os import os.path import sys # Medusa import asyncore import default_handler import filesys import ftp_server import http_server import status_handler # M2Crypto import https_server import poison_handler import ftps_server from M2Crypto import Rand, SSL, threading HTTP_PORT=9080 HTTPS_PORT=9443 FTP_PORT = 9021 hs=http_server.http_server('', HTTP_PORT) Rand.load_file('../randpool.dat', -1) ssl_ctx=SSL.Context('sslv23') ssl_ctx.load_cert('server.pem') ssl_ctx.load_verify_location('ca.pem') ssl_ctx.load_client_CA('ca.pem') #ssl_ctx.set_verify(SSL.verify_peer, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_client_once, 10) ssl_ctx.set_verify(SSL.verify_none, 10) ssl_ctx.set_session_id_ctx('127.0.0.1:9443') ssl_ctx.set_tmp_dh('dh1024.pem') ssl_ctx.set_info_callback() hss=https_server.https_server('', HTTPS_PORT, ssl_ctx) #fs=filesys.os_filesystem(os.path.abspath(os.curdir)) fs=filesys.os_filesystem('/usr/local/pkg/apache/htdocs') #fs=filesys.os_filesystem('c:/pkg/jdk130/docs') dh=default_handler.default_handler(fs) hs.install_handler(dh) hss.install_handler(dh) #class rpc_demo (xmlrpc_handler.xmlrpc_handler): # def call (self, method, params): # print 'method="%s" params=%s' % (method, params) # return "Sure, that works" #rpch = rpc_demo() #hs.install_handler(rpch) #hss.install_handler(rpch) ph=poison_handler.poison_handler(10) hs.install_handler(ph) hss.install_handler(ph) fauthz = ftp_server.anon_authorizer('/usr/local/pkg/apache/htdocs') ftps = ftps_server.ftp_tls_server(fauthz, ssl_ctx, port=FTP_PORT) sh=status_handler.status_extension([hs, hss, ftps]) hs.install_handler(sh) hss.install_handler(sh) asyncore.loop() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/medusa/START_xmlrpc.py0000664000175000017500000000332512607370517021166 0ustar matejmatej00000000000000#!/usr/bin/env python # Standard Python library import os import os.path import sys # Medusa import asyncore import default_handler import filesys import http_server import status_handler # M2Crypto import https_server import poison_handler from M2Crypto import Rand, SSL # XMLrpc import xmlrpc_handler HTTP_PORT=9080 HTTPS_PORT=9443 hs=http_server.http_server('', HTTP_PORT) Rand.load_file('../randpool.dat', -1) ssl_ctx=SSL.Context('sslv23') ssl_ctx.load_cert('server.pem') #ssl_ctx.load_verify_location('ca.pem') #ssl_ctx.load_client_CA('ca.pem') #ssl_ctx.set_verify(SSL.verify_peer, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_client_once, 10) ssl_ctx.set_verify(SSL.verify_none, 10) ssl_ctx.set_session_id_ctx('127.0.0.1:9443') ssl_ctx.set_tmp_dh('dh1024.pem') #ssl_ctx.set_info_callback() hss=https_server.https_server('', HTTPS_PORT, ssl_ctx) #fs=filesys.os_filesystem(os.path.abspath(os.curdir)) fs=filesys.os_filesystem('/usr/local/pkg/apache/htdocs') #fs=filesys.os_filesystem('c:/pkg/jdk118/docs') dh=default_handler.default_handler(fs) hs.install_handler(dh) hss.install_handler(dh) # Cribbed from xmlrpc_handler.py. # This is where you implement your RPC functionality. class rpc_demo (xmlrpc_handler.xmlrpc_handler): def call (self, method, params): print 'method="%s" params=%s' % (method, params) return "Sure, that works" rpch = rpc_demo() hs.install_handler(rpch) hss.install_handler(rpch) ph=poison_handler.poison_handler(10) hs.install_handler(ph) hss.install_handler(ph) sh=status_handler.status_extension([hss]) hs.install_handler(sh) hss.install_handler(sh) asyncore.loop() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/medusa/asynchat.py0000664000175000017500000002121412607370517020513 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # $Id$ # Author: Sam Rushing # ====================================================================== # Copyright 1996 by Sam Rushing # # All Rights Reserved # # 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, and that the name of Sam # Rushing not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL SAM RUSHING 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. # ====================================================================== """A class supporting chat-style (command/response) protocols. This class adds support for 'chat' style protocols - where one side sends a 'command', and the other sends a response (examples would be the common internet protocols - smtp, nntp, ftp, etc..). The handle_read() method looks at the input stream for the current 'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n' for multi-line output), calling self.found_terminator() on its receipt. for example: Say you build an async nntp client using this class. At the start of the connection, you'll have self.terminator set to '\r\n', in order to process the single-line greeting. Just before issuing a 'LIST' command you'll set it to '\r\n.\r\n'. The output of the LIST command will be accumulated (using your own 'collect_incoming_data' method) up to the terminator, and then control will be returned to you - by calling your self.found_terminator() method. """ import socket import asyncore import string class async_chat (asyncore.dispatcher): """This is an abstract class. You must derive from this class, and add the two methods collect_incoming_data() and found_terminator()""" # these are overridable defaults ac_in_buffer_size = 4096 ac_out_buffer_size = 4096 def __init__ (self, conn=None): self.ac_in_buffer = '' self.ac_out_buffer = '' self.producer_fifo = fifo() asyncore.dispatcher.__init__ (self, conn) def set_terminator (self, term): "Set the input delimiter. Can be a fixed string of any length, an integer, or None" self.terminator = term def get_terminator (self): return self.terminator # grab some more data from the socket, # throw it to the collector method, # check for the terminator, # if found, transition to the next state. def handle_read (self): try: data = self.recv (self.ac_in_buffer_size) except socket.error, why: self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(1024). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if terminator is None: # no terminator, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' elif type(terminator) == type(0): # numeric terminator n = terminator if lb < n: self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: self.collect_incoming_data (self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = string.find (self.ac_in_buffer, terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end (self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' def handle_write (self): self.initiate_send () def handle_close (self): self.close() def push (self, data): self.producer_fifo.push (simple_producer (data)) self.initiate_send() def push_with_producer (self, producer): self.producer_fifo.push (producer) self.initiate_send() def readable (self): "predicate for inclusion in the readable for select()" return (len(self.ac_in_buffer) <= self.ac_in_buffer_size) def writable (self): "predicate for inclusion in the writable for select()" # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected) # this is about twice as fast, though not as clear. return not ( (self.ac_out_buffer is '') and self.producer_fifo.is_empty() and self.connected ) def close_when_done (self): "automatically close this channel once the outgoing queue is empty" self.producer_fifo.push (None) # refill the outgoing buffer by calling the more() method # of the first producer in the queue def refill_buffer (self): _string_type = type('') while 1: if len(self.producer_fifo): p = self.producer_fifo.first() # a 'None' in the producer fifo is a sentinel, # telling us to close the channel. if p is None: if not self.ac_out_buffer: self.producer_fifo.pop() self.close() return elif type(p) is _string_type: self.producer_fifo.pop() self.ac_out_buffer = self.ac_out_buffer + p return data = p.more() if data: self.ac_out_buffer = self.ac_out_buffer + data return else: self.producer_fifo.pop() else: return def initiate_send (self): obs = self.ac_out_buffer_size # try to refill the buffer if (len (self.ac_out_buffer) < obs): self.refill_buffer() if self.ac_out_buffer and self.connected: # try to send the buffer try: num_sent = self.send (self.ac_out_buffer[:obs]) if num_sent: self.ac_out_buffer = self.ac_out_buffer[num_sent:] except socket.error, why: self.handle_error() return def discard_buffers (self): # Emergencies only! self.ac_in_buffer = '' self.ac_out_buffer = '' while self.producer_fifo: self.producer_fifo.pop() class simple_producer: def __init__ (self, data, buffer_size=512): self.data = data self.buffer_size = buffer_size def more (self): if len (self.data) > self.buffer_size: result = self.data[:self.buffer_size] self.data = self.data[self.buffer_size:] return result else: result = self.data self.data = '' return result class fifo: def __init__ (self, list=None): if not list: self.list = [] else: self.list = list def __len__ (self): return len(self.list) def is_empty (self): return self.list == [] def first (self): return self.list[0] def push (self, data): self.list.append (data) def pop (self): if self.list: result = self.list[0] del self.list[0] return (1, result) else: return (0, None) # Given 'haystack', see if any prefix of 'needle' is at its end. This # assumes an exact match has already been checked. Return the number of # characters matched. # for example: # f_p_a_e ("qwerty\r", "\r\n") => 1 # f_p_a_e ("qwertydkjf", "\r\n") => 0 # f_p_a_e ("qwerty\r\n", "\r\n") => # this could maybe be made faster with a computed regex? # [answer: no; circa Python-2.0, Jan 2001] # new python: 28961/s # old python: 18307/s # re: 12820/s # regex: 14035/s def find_prefix_at_end (haystack, needle): l = len(needle) - 1 while l and not haystack.endswith(needle[:l]): l -= 1 return l M2Crypto-0.22.6rc4/demo/medusa/asyncore.py0000664000175000017500000003360612607370517020534 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # $Id$ # Author: Sam Rushing # ====================================================================== # Copyright 1996 by Sam Rushing # # All Rights Reserved # # 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, and that the name of Sam # Rushing not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL SAM RUSHING 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. # ====================================================================== """Basic infrastructure for asynchronous socket service clients and servers. There are only two ways to have a program on a single processor do "more than one thing at a time". Multi-threaded programming is the simplest and most popular way to do it, but there is another very different technique, that lets you have nearly all the advantages of multi-threading, without actually using multiple threads. it's really only practical if your program is largely I/O bound. If your program is CPU bound, then pre-emptive scheduled threads are probably what you really need. Network servers are rarely CPU-bound, however. If your operating system supports the select() system call in its I/O library (and nearly all do), then you can use it to juggle multiple communication channels at once; doing other work while your I/O is taking place in the "background." Although this strategy can seem strange and complex, especially at first, it is in many ways easier to understand and control than multi-threaded programming. The module documented here solves many of the difficult problems for you, making the task of building sophisticated high-performance network servers and clients a snap. """ import exceptions import select import socket import string import sys import os if os.name == 'nt': EWOULDBLOCK = 10035 EINPROGRESS = 10036 EALREADY = 10037 ECONNRESET = 10054 ENOTCONN = 10057 ESHUTDOWN = 10058 else: from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN try: socket_map except NameError: socket_map = {} class ExitNow (exceptions.Exception): pass DEBUG = 0 def poll (timeout=0.0, map=None): global DEBUG if map is None: map = socket_map if map: r = []; w = []; e = [] for fd, obj in map.items(): if obj.readable(): r.append (fd) if obj.writable(): w.append (fd) r,w,e = select.select (r,w,e, timeout) if DEBUG: print r,w,e for fd in r: try: obj = map[fd] try: obj.handle_read_event() except ExitNow: raise ExitNow except: obj.handle_error() except KeyError: pass for fd in w: try: obj = map[fd] try: obj.handle_write_event() except ExitNow: raise ExitNow except: obj.handle_error() except KeyError: pass def poll2 (timeout=0.0, map=None): import poll if map is None: map=socket_map # timeout is in milliseconds timeout = int(timeout*1000) if map: l = [] for fd, obj in map.items(): flags = 0 if obj.readable(): flags = poll.POLLIN if obj.writable(): flags = flags | poll.POLLOUT if flags: l.append ((fd, flags)) r = poll.poll (l, timeout) for fd, flags in r: try: obj = map[fd] try: if (flags & poll.POLLIN): obj.handle_read_event() if (flags & poll.POLLOUT): obj.handle_write_event() except ExitNow: raise ExitNow except: obj.handle_error() except KeyError: pass def poll3 (timeout=0.0, map=None): # Use the poll() support added to the select module in Python 2.0 if map is None: map=socket_map # timeout is in milliseconds timeout = int(timeout*1000) pollster = select.poll() if map: l = [] for fd, obj in map.items(): flags = 0 if obj.readable(): flags = select.POLLIN if obj.writable(): flags = flags | select.POLLOUT if flags: pollster.register(fd, flags) r = pollster.poll (timeout) for fd, flags in r: try: obj = map[fd] try: if (flags & select.POLLIN): obj.handle_read_event() if (flags & select.POLLOUT): obj.handle_write_event() except ExitNow: raise ExitNow except: obj.handle_error() except KeyError: pass def loop (timeout=30.0, use_poll=0, map=None): if use_poll: if hasattr (select, 'poll'): poll_fun = poll3 else: poll_fun = poll2 else: poll_fun = poll if map is None: map=socket_map while map: poll_fun (timeout, map) class dispatcher: debug = 0 connected = 0 accepting = 0 closing = 0 addr = None def __init__ (self, sock=None, map=None): if sock: self.set_socket (sock, map) # I think it should inherit this anyway self.socket.setblocking (0) self.connected = 1 def __repr__ (self): try: status = [] if self.accepting and self.addr: status.append ('listening') elif self.connected: status.append ('connected') if self.addr: status.append ('%s:%d' % self.addr) return '<%s %s at %x>' % ( self.__class__.__name__, string.join (status, ' '), id(self) ) except: try: ar = repr(self.addr) except: ar = 'no self.addr!' return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar) def add_channel (self, map=None): #self.log_info ('adding channel %s' % self) if map is None: map=socket_map map [self._fileno] = self def del_channel (self, map=None): fd = self._fileno if map is None: map=socket_map if map.has_key (fd): #self.log_info ('closing channel %d:%s' % (fd, self)) del map [fd] def create_socket (self, family, type): self.family_and_type = family, type self.socket = socket.socket (family, type) self.socket.setblocking(0) self._fileno = self.socket.fileno() self.add_channel() def set_socket (self, sock, map=None): self.__dict__['socket'] = sock self._fileno = sock.fileno() self.add_channel (map) def set_reuse_addr (self): # try to re-use a server port if possible try: self.socket.setsockopt ( socket.SOL_SOCKET, socket.SO_REUSEADDR, self.socket.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1 ) except: pass # ================================================== # predicates for select() # these are used as filters for the lists of sockets # to pass to select(). # ================================================== def readable (self): return 1 if os.name == 'mac': # The macintosh will select a listening socket for # write if you let it. What might this mean? def writable (self): return not self.accepting else: def writable (self): return 1 # ================================================== # socket object methods. # ================================================== def listen (self, num): self.accepting = 1 if os.name == 'nt' and num > 5: num = 1 return self.socket.listen (num) def bind (self, addr): self.addr = addr return self.socket.bind (addr) def connect (self, address): self.connected = 0 try: self.socket.connect (address) except socket.error, why: if why[0] in (EINPROGRESS, EALREADY, EWOULDBLOCK): return else: raise socket.error, why self.connected = 1 self.handle_connect() def accept (self): try: conn, addr = self.socket.accept() return conn, addr except socket.error, why: if why[0] == EWOULDBLOCK: pass else: raise socket.error, why def send (self, data): try: result = self.socket.send (data) return result except socket.error, why: if why[0] == EWOULDBLOCK: return 0 else: raise socket.error, why return 0 def recv (self, buffer_size): try: data = self.socket.recv (buffer_size) if not data: # a closed connection is indicated by signaling # a read condition, and having recv() return 0. self.handle_close() return '' else: return data except socket.error, why: # winsock sometimes throws ENOTCONN if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]: self.handle_close() return '' else: raise socket.error, why def close (self): self.del_channel() self.socket.close() # cheap inheritance, used to pass all other attribute # references to the underlying socket object. def __getattr__ (self, attr): return getattr (self.socket, attr) # log and log_info maybe overriden to provide more sophisitcated # logging and warning methods. In general, log is for 'hit' logging # and 'log_info' is for informational, warning and error logging. def log (self, message): sys.stderr.write ('log: %s\n' % str(message)) def log_info (self, message, type='info'): if __debug__ or type != 'info': print '%s: %s' % (type, message) def handle_read_event (self): if self.accepting: # for an accepting socket, getting a read implies # that we are connected if not self.connected: self.connected = 1 self.handle_accept() elif not self.connected: self.handle_connect() self.connected = 1 self.handle_read() else: self.handle_read() def handle_write_event (self): # getting a write implies that we are connected if not self.connected: self.handle_connect() self.connected = 1 self.handle_write() def handle_expt_event (self): self.handle_expt() def handle_error (self): (file,fun,line), t, v, tbinfo = compact_traceback() # sometimes a user repr method will crash. try: self_repr = repr (self) except: self_repr = '<__repr__ (self) failed for object at %0x>' % id(self) self.log_info ( 'uncaptured python exception, closing channel %s (%s:%s %s)' % ( self_repr, t, v, tbinfo ), 'error' ) self.close() def handle_expt (self): self.log_info ('unhandled exception', 'warning') def handle_read (self): self.log_info ('unhandled read event', 'warning') def handle_write (self): self.log_info ('unhandled write event', 'warning') def handle_connect (self): self.log_info ('unhandled connect event', 'warning') def handle_accept (self): self.log_info ('unhandled accept event', 'warning') def handle_close (self): self.log_info ('unhandled close event', 'warning') self.close() # --------------------------------------------------------------------------- # adds simple buffered output capability, useful for simple clients. # [for more sophisticated usage use asynchat.async_chat] # --------------------------------------------------------------------------- class dispatcher_with_send (dispatcher): def __init__ (self, sock=None): dispatcher.__init__ (self, sock) self.out_buffer = '' def initiate_send (self): num_sent = 0 num_sent = dispatcher.send (self, self.out_buffer[:512]) self.out_buffer = self.out_buffer[num_sent:] def handle_write (self): self.initiate_send() def writable (self): return (not self.connected) or len(self.out_buffer) def send (self, data): if self.debug: self.log_info ('sending %s' % repr(data)) self.out_buffer = self.out_buffer + data self.initiate_send() # --------------------------------------------------------------------------- # used for debugging. # --------------------------------------------------------------------------- def compact_traceback (): t,v,tb = sys.exc_info() tbinfo = [] while 1: tbinfo.append (( tb.tb_frame.f_code.co_filename, tb.tb_frame.f_code.co_name, str(tb.tb_lineno) )) tb = tb.tb_next if not tb: break # just to be safe del tb file, function, line = tbinfo[-1] info = '[' + string.join ( map ( lambda x: string.join (x, '|'), tbinfo ), '] [' ) + ']' return (file, function, line), t, v, info def close_all (map=None): if map is None: map=socket_map for x in map.values(): x.socket.close() map.clear() # Asynchronous File I/O: # # After a little research (reading man pages on various unixen, and # digging through the linux kernel), I've determined that select() # isn't meant for doing doing asynchronous file i/o. # Heartening, though - reading linux/mm/filemap.c shows that linux # supports asynchronous read-ahead. So _MOST_ of the time, the data # will be sitting in memory for us already when we go to read it. # # What other OS's (besides NT) support async file i/o? [VMS?] # # Regardless, this is useful for pipes, and stdin/stdout... import os if os.name == 'posix': import fcntl import FCNTL class file_wrapper: # here we override just enough to make a file # look like a socket for the purposes of asyncore. def __init__ (self, fd): self.fd = fd def recv (self, *args): return apply (os.read, (self.fd,)+args) def send (self, *args): return apply (os.write, (self.fd,)+args) read = recv write = send def close (self): return os.close (self.fd) def fileno (self): return self.fd class file_dispatcher (dispatcher): def __init__ (self, fd): dispatcher.__init__ (self) self.connected = 1 # set it to non-blocking mode flags = fcntl.fcntl (fd, FCNTL.F_GETFL, 0) flags = flags | FCNTL.O_NONBLOCK fcntl.fcntl (fd, FCNTL.F_SETFL, flags) self.set_file (fd) def set_file (self, fd): self._fileno = fd self.socket = file_wrapper (fd) self.add_channel() M2Crypto-0.22.6rc4/demo/medusa/auth_handler.py0000664000175000017500000001067112613276364021346 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # # support for 'basic' authenticaion. import base64 import hashlib import re import string import time import counter import default_handler get_header = default_handler.get_header import http_server import producers # This is a 'handler' that wraps an authorization method # around access to the resources normally served up by # another handler. # does anyone support digest authentication? (rfc2069) class auth_handler: def __init__(self, dict, handler, realm='default'): self.authorizer = dictionary_authorizer(dict) self.handler = handler self.realm = realm self.pass_count = counter.counter() self.fail_count = counter.counter() def match(self, request): # by default, use the given handler's matcher return self.handler.match(request) def handle_request(self, request): # authorize a request before handling it... scheme = get_header(AUTHORIZATION, request.header) if scheme: scheme = string.lower(scheme) if scheme == 'basic': cookie = AUTHORIZATION.group(2) try: decoded = base64.decodestring(cookie) except: print 'malformed authorization info <%s>' % cookie request.error(400) return auth_info = string.split(decoded, ':') if self.authorizer.authorize(auth_info): self.pass_count.increment() request.auth_info = auth_info self.handler.handle_request(request) else: self.handle_unauthorized(request) #elif scheme == 'digest': # print 'digest: ',AUTHORIZATION.group(2) else: print 'unknown/unsupported auth method: %s' % scheme self.handle_unauthorized() else: # list both? prefer one or the other? # you could also use a 'nonce' here. [see below] #auth = 'Basic realm="%s" Digest realm="%s"' % # (self.realm, self.realm) #nonce = self.make_nonce (request) #auth = 'Digest realm="%s" nonce="%s"' % (self.realm, nonce) #request['WWW-Authenticate'] = auth #print 'sending header: %s' % request['WWW-Authenticate'] self.handle_unauthorized(request) def handle_unauthorized(self, request): # We are now going to receive data that we want to ignore. # to ignore the file data we're not interested in. self.fail_count.increment() request.channel.set_terminator(None) request['Connection'] = 'close' request['WWW-Authenticate'] = 'Basic realm="%s"' % self.realm request.error(401) def make_nonce(self, request): "A digest-authentication , constructed as suggested in RFC 2069" ip = request.channel.server.ip now = str(long(time.time()))[:-1] private_key = str(id(self)) nonce = string.join([ip, now, private_key], ':') return self.apply_hash(nonce) def apply_hash(self, s): "Apply MD5 to a string , then wrap it in base64 encoding." m = hashlib.new() m.update(s) d = m.digest() # base64.encodestring tacks on an extra linefeed. return base64.encodestring(d)[:-1] def status(self): # Thanks to mwm@contessa.phone.net (Mike Meyer) r = [ producers.simple_producer( '
  • Authorization Extension : ' 'Unauthorized requests: %s
      ' % self.fail_count ) ] if hasattr(self.handler, 'status'): r.append(self.handler.status()) r.append( producers.simple_producer('
    ') ) return producers.composite_producer( http_server.fifo(r) ) class dictionary_authorizer: def __init__(self, dict): self.dict = dict def authorize(self, auth_info): [username, password] = auth_info if (username in self.dict) and (self.dict[username] == password): return 1 else: return 0 AUTHORIZATION = re.compile( # scheme challenge 'Authorization: ([^ ]+) (.*)', re.IGNORECASE ) M2Crypto-0.22.6rc4/demo/medusa/ca.pem0000664000175000017500000000230412605232411017400 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/medusa/counter.py0000664000175000017500000000241212607370517020357 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # It is tempting to add an __int__ method to this class, but it's not # a good idea. This class tries to gracefully handle integer # overflow, and to hide this detail from both the programmer and the # user. Note that the __str__ method can be relied on for printing out # the value of a counter: # # >>> print 'Total Client: %s' % self.total_clients # # If you need to do arithmetic with the value, then use the 'as_long' # method, the use of long arithmetic is a reminder that the counter # will overflow. class counter: "general-purpose counter" def __init__ (self, initial_value=0): self.value = initial_value def increment (self, delta=1): result = self.value try: self.value = self.value + delta except OverflowError: self.value = long(self.value) + delta return result def decrement (self, delta=1): result = self.value try: self.value = self.value - delta except OverflowError: self.value = long(self.value) - delta return result def as_long (self): return long(self.value) def __nonzero__ (self): return self.value != 0 def __repr__ (self): return '' % (self.value, id(self)) def __str__ (self): return str(long(self.value)) #return str(long(self.value))[:-1] M2Crypto-0.22.6rc4/demo/medusa/default_handler.py0000664000175000017500000001202412607370517022021 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # # Author: Sam Rushing # Copyright 1997 by Sam Rushing # All Rights Reserved. # # standard python modules import os import re import posixpath import stat import string import time # medusa modules import http_date import http_server import mime_type_table import status_handler import producers unquote = http_server.unquote # This is the 'default' handler. it implements the base set of # features expected of a simple file-delivering HTTP server. file # services are provided through a 'filesystem' object, the very same # one used by the FTP server. # # You can replace or modify this handler if you want a non-standard # HTTP server. You can also derive your own handler classes from # it. # # support for handling POST requests is available in the derived # class , defined below. # from counter import counter class default_handler: valid_commands = ['get', 'head'] IDENT = 'Default HTTP Request Handler' # Pathnames that are tried when a URI resolves to a directory name directory_defaults = [ 'index.html', 'default.html' ] default_file_producer = producers.file_producer def __init__ (self, filesystem): self.filesystem = filesystem # count total hits self.hit_counter = counter() # count file deliveries self.file_counter = counter() # count cache hits self.cache_counter = counter() hit_counter = 0 def __repr__ (self): return '<%s (%s hits) at %x>' % ( self.IDENT, self.hit_counter, id (self) ) # always match, since this is a default def match (self, request): return 1 # handle a file request, with caching. def handle_request (self, request): if request.command not in self.valid_commands: request.error (400) # bad request return self.hit_counter.increment() path, params, query, fragment = request.split_uri() if '%' in path: path = unquote (path) # strip off all leading slashes while path and path[0] == '/': path = path[1:] if self.filesystem.isdir (path): if path and path[-1] != '/': request['Location'] = 'http://%s/%s/' % ( request.channel.server.server_name, path ) request.error (301) return # we could also generate a directory listing here, # may want to move this into another method for that # purpose found = 0 if path and path[-1] != '/': path = path + '/' for default in self.directory_defaults: p = path + default if self.filesystem.isfile (p): path = p found = 1 break if not found: request.error (404) # Not Found return elif not self.filesystem.isfile (path): request.error (404) # Not Found return file_length = self.filesystem.stat (path)[stat.ST_SIZE] ims = get_header_match (IF_MODIFIED_SINCE, request.header) length_match = 1 if ims: length = ims.group (4) if length: try: length = string.atoi (length) if length != file_length: length_match = 0 except: pass ims_date = 0 if ims: ims_date = http_date.parse_http_date (ims.group (1)) try: mtime = self.filesystem.stat (path)[stat.ST_MTIME] except: request.error (404) return if length_match and ims_date: if mtime <= ims_date: request.reply_code = 304 request.done() self.cache_counter.increment() return try: file = self.filesystem.open (path, 'rb') except IOError: request.error (404) return request['Last-Modified'] = http_date.build_http_date (mtime) request['Content-Length'] = file_length self.set_content_type (path, request) if request.command == 'get': request.push (self.default_file_producer (file)) self.file_counter.increment() request.done() def set_content_type (self, path, request): ext = string.lower (get_extension (path)) if mime_type_table.content_type_map.has_key (ext): request['Content-Type'] = mime_type_table.content_type_map[ext] else: # TODO: test a chunk off the front of the file for 8-bit # characters, and use application/octet-stream instead. request['Content-Type'] = 'text/plain' def status (self): return producers.simple_producer ( '
  • %s' % status_handler.html_repr (self) + '
      ' + '
    • Total Hits: %s' % self.hit_counter + '
    • Files Delivered: %s' % self.file_counter + '
    • Cache Hits: %s' % self.cache_counter + '
    ' ) # HTTP/1.0 doesn't say anything about the "; length=nnnn" addition # to this header. I suppose it's purpose is to avoid the overhead # of parsing dates... IF_MODIFIED_SINCE = re.compile ( 'If-Modified-Since: ([^;]+)((; length=([0-9]+)$)|$)', re.IGNORECASE ) USER_AGENT = re.compile ('User-Agent: (.*)', re.IGNORECASE) CONTENT_TYPE = re.compile ( r'Content-Type: ([^;]+)((; boundary=([A-Za-z0-9\'\(\)+_,./:=?-]+)$)|$)', re.IGNORECASE ) get_header = http_server.get_header get_header_match = http_server.get_header_match def get_extension (path): dirsep = string.rfind (path, '/') dotsep = string.rfind (path, '.') if dotsep > dirsep: return path[dotsep+1:] else: return '' M2Crypto-0.22.6rc4/demo/medusa/dh1024.pem0000664000175000017500000000036512605232411017724 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/medusa/filesys.py0000664000175000017500000002542612607370517020370 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # $Id$ # Author: Sam Rushing # # Generic filesystem interface. # # We want to provide a complete wrapper around any and all # filesystem operations. # this class is really just for documentation, # identifying the API for a filesystem object. # opening files for reading, and listing directories, should # return a producer. class abstract_filesystem: def __init__ (self): pass def current_directory (self): "Return a string representing the current directory." pass def listdir (self, path, long=0): """Return a listing of the directory at 'path' The empty string indicates the current directory. If 'long' is set, instead return a list of (name, stat_info) tuples """ pass def open (self, path, mode): "Return an open file object" pass def stat (self, path): "Return the equivalent of os.stat() on the given path." pass def isdir (self, path): "Does the path represent a directory?" pass def isfile (self, path): "Does the path represent a plain file?" pass def cwd (self, path): "Change the working directory." pass def cdup (self): "Change to the parent of the current directory." pass def longify (self, path): """Return a 'long' representation of the filename [for the output of the LIST command]""" pass # standard wrapper around a unix-like filesystem, with a 'false root' # capability. # security considerations: can symbolic links be used to 'escape' the # root? should we allow it? if not, then we could scan the # filesystem on startup, but that would not help if they were added # later. We will probably need to check for symlinks in the cwd method. # what to do if wd is an invalid directory? import os import stat import string def safe_stat (path): try: return (path, os.stat (path)) except: return None import regsub import glob class os_filesystem: path_module = os.path # set this to zero if you want to disable pathname globbing. # [we currently don't glob, anyway] do_globbing = 1 def __init__ (self, root, wd='/'): self.root = root self.wd = wd def current_directory (self): return self.wd def isfile (self, path): p = self.normalize (self.path_module.join (self.wd, path)) return self.path_module.isfile (self.translate(p)) def isdir (self, path): p = self.normalize (self.path_module.join (self.wd, path)) return self.path_module.isdir (self.translate(p)) def cwd (self, path): p = self.normalize (self.path_module.join (self.wd, path)) translated_path = self.translate(p) if not self.path_module.isdir (translated_path): return 0 else: old_dir = os.getcwd() # temporarily change to that directory, in order # to see if we have permission to do so. try: can = 0 try: os.chdir (translated_path) can = 1 self.wd = p except: pass finally: if can: os.chdir (old_dir) return can def cdup (self): return self.cwd ('..') def listdir (self, path, long=0): p = self.translate (path) # I think we should glob, but limit it to the current # directory only. ld = os.listdir (p) if not long: return list_producer (ld, 0, None) else: old_dir = os.getcwd() try: os.chdir (p) # if os.stat fails we ignore that file. result = filter (None, map (safe_stat, ld)) finally: os.chdir (old_dir) return list_producer (result, 1, self.longify) # TODO: implement a cache w/timeout for stat() def stat (self, path): p = self.translate (path) return os.stat (p) def open (self, path, mode): p = self.translate (path) return open (p, mode) def unlink (self, path): p = self.translate (path) return os.unlink (p) def mkdir (self, path): p = self.translate (path) return os.mkdir (p) def rmdir (self, path): p = self.translate (path) return os.rmdir (p) # utility methods def normalize (self, path): # watch for the ever-sneaky '/+' path element path = regsub.gsub ('/+', '/', path) p = self.path_module.normpath (path) # remove 'dangling' cdup's. if len(p) > 2 and p[:3] == '/..': p = '/' return p def translate (self, path): # we need to join together three separate # path components, and do it safely. # // # use the operating system's path separator. path = string.join (string.split (path, '/'), os.sep) p = self.normalize (self.path_module.join (self.wd, path)) p = self.normalize (self.path_module.join (self.root, p[1:])) return p def longify (self, (path, stat_info)): return unix_longify (path, stat_info) def __repr__ (self): return '' % ( self.root, self.wd ) if os.name == 'posix': class unix_filesystem (os_filesystem): pass class schizophrenic_unix_filesystem (os_filesystem): PROCESS_UID = os.getuid() PROCESS_EUID = os.geteuid() PROCESS_GID = os.getgid() PROCESS_EGID = os.getegid() def __init__ (self, root, wd='/', persona=(None, None)): os_filesystem.__init__ (self, root, wd) self.persona = persona def become_persona (self): if self.persona is not (None, None): uid, gid = self.persona # the order of these is important! os.setegid (gid) os.seteuid (uid) def become_nobody (self): if self.persona is not (None, None): os.seteuid (self.PROCESS_UID) os.setegid (self.PROCESS_GID) # cwd, cdup, open, listdir def cwd (self, path): try: self.become_persona() return os_filesystem.cwd (self, path) finally: self.become_nobody() def cdup (self, path): try: self.become_persona() return os_filesystem.cdup (self) finally: self.become_nobody() def open (self, filename, mode): try: self.become_persona() return os_filesystem.open (self, filename, mode) finally: self.become_nobody() def listdir (self, path, long=0): try: self.become_persona() return os_filesystem.listdir (self, path, long) finally: self.become_nobody() # This hasn't been very reliable across different platforms. # maybe think about a separate 'directory server'. # # import posixpath # import fcntl # import FCNTL # import select # import asyncore # # # pipes /bin/ls for directory listings. # class unix_filesystem (os_filesystem): # pass # path_module = posixpath # # def listdir (self, path, long=0): # p = self.translate (path) # if not long: # return list_producer (os.listdir (p), 0, None) # else: # command = '/bin/ls -l %s' % p # print 'opening pipe to "%s"' % command # fd = os.popen (command, 'rt') # return pipe_channel (fd) # # # this is both a dispatcher, _and_ a producer # class pipe_channel (asyncore.file_dispatcher): # buffer_size = 4096 # # def __init__ (self, fd): # asyncore.file_dispatcher.__init__ (self, fd) # self.fd = fd # self.done = 0 # self.data = '' # # def handle_read (self): # if len (self.data) < self.buffer_size: # self.data = self.data + self.fd.read (self.buffer_size) # #print '%s.handle_read() => len(self.data) == %d' % (self, len(self.data)) # # def handle_expt (self): # #print '%s.handle_expt()' % self # self.done = 1 # # def ready (self): # #print '%s.ready() => %d' % (self, len(self.data)) # return ((len (self.data) > 0) or self.done) # # def more (self): # if self.data: # r = self.data # self.data = '' # elif self.done: # self.close() # self.downstream.finished() # r = '' # else: # r = None # #print '%s.more() => %s' % (self, (r and len(r))) # return r # For the 'real' root, we could obtain a list of drives, and then # use that. Doesn't win32 provide such a 'real' filesystem? # [yes, I think something like this "\\.\c\windows"] class msdos_filesystem (os_filesystem): def longify (self, (path, stat_info)): return msdos_longify (path, stat_info) # A merged filesystem will let you plug other filesystems together. # We really need the equivalent of a 'mount' capability - this seems # to be the most general idea. So you'd use a 'mount' method to place # another filesystem somewhere in the hierarchy. # Note: this is most likely how I will handle ~user directories # with the http server. class merged_filesystem: def __init__ (self, *fsys): pass # this matches the output of NT's ftp server (when in # MSDOS mode) exactly. def msdos_longify (file, stat_info): if stat.S_ISDIR (stat_info[stat.ST_MODE]): dir = '' else: dir = ' ' date = msdos_date (stat_info[stat.ST_MTIME]) return '%s %s %8d %s' % ( date, dir, stat_info[stat.ST_SIZE], file ) def msdos_date (t): try: info = time.gmtime (t) except: info = time.gmtime (0) # year, month, day, hour, minute, second, ... if info[3] > 11: merid = 'PM' info[3] = info[3] - 12 else: merid = 'AM' return '%02d-%02d-%02d %02d:%02d%s' % ( info[1], info[2], info[0]%100, info[3], info[4], merid ) months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] mode_table = { '0':'---', '1':'--x', '2':'-w-', '3':'-wx', '4':'r--', '5':'r-x', '6':'rw-', '7':'rwx' } import time def unix_longify (file, stat_info): # for now, only pay attention to the lower bits mode = ('%o' % stat_info[stat.ST_MODE])[-3:] mode = string.join (map (lambda x: mode_table[x], mode), '') if stat.S_ISDIR (stat_info[stat.ST_MODE]): dirchar = 'd' else: dirchar = '-' date = ls_date (long(time.time()), stat_info[stat.ST_MTIME]) return '%s%s %3d %-8d %-8d %8d %s %s' % ( dirchar, mode, stat_info[stat.ST_NLINK], stat_info[stat.ST_UID], stat_info[stat.ST_GID], stat_info[stat.ST_SIZE], date, file ) # Emulate the unix 'ls' command's date field. # it has two formats - if the date is more than 180 # days in the past, then it's like this: # Oct 19 1995 # otherwise, it looks like this: # Oct 19 17:33 def ls_date (now, t): try: info = time.gmtime (t) except: info = time.gmtime (0) # 15,600,000 == 86,400 * 180 if (now - t) > 15600000: return '%s %2d %d' % ( months[info[1]-1], info[2], info[0] ) else: return '%s %2d %02d:%02d' % ( months[info[1]-1], info[2], info[3], info[4] ) # =========================================================================== # Producers # =========================================================================== class list_producer: def __init__ (self, file_list, long, longify): self.file_list = file_list self.long = long self.longify = longify self.done = 0 def ready (self): if len(self.file_list): return 1 else: if not self.done: self.done = 1 return 0 return (len(self.file_list) > 0) # this should do a pushd/popd def more (self): if not self.file_list: return '' else: # do a few at a time bunch = self.file_list[:50] if self.long: bunch = map (self.longify, bunch) self.file_list = self.file_list[50:] return string.joinfields (bunch, '\r\n') + '\r\n' M2Crypto-0.22.6rc4/demo/medusa/ftp_server.py0000664000175000017500000007642212607370517021073 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # # An extensible, configurable, asynchronous FTP server. # # All socket I/O is non-blocking, however file I/O is currently # blocking. Eventually file I/O may be made non-blocking, too, if it # seems necessary. Currently the only CPU-intensive operation is # getting and formatting a directory listing. [this could be moved # into another process/directory server, or another thread?] # # Only a subset of RFC 959 is implemented, but much of that RFC is # vestigial anyway. I've attempted to include the most commonly-used # commands, using the feature set of wu-ftpd as a guide. import asyncore import asynchat import os import regsub import socket import stat import string import sys import time # TODO: implement a directory listing cache. On very-high-load # servers this could save a lot of disk abuse, and possibly the # work of computing emulated unix ls output. # Potential security problem with the FTP protocol? I don't think # there's any verification of the origin of a data connection. Not # really a problem for the server (since it doesn't send the port # command, except when in PASV mode) But I think a data connection # could be spoofed by a program with access to a sniffer - it could # watch for a PORT command to go over a command channel, and then # connect to that port before the server does. # Unix user id's: # In order to support assuming the id of a particular user, # it seems there are two options: # 1) fork, and seteuid in the child # 2) carefully control the effective uid around filesystem accessing # methods, using try/finally. [this seems to work] VERSION = '1.1' from counter import counter import producers import status_handler import logger import string class ftp_channel (asynchat.async_chat): # defaults for a reliable __repr__ addr = ('unknown','0') # unset this in a derived class in order # to enable the commands in 'self.write_commands' read_only = 1 write_commands = ['appe','dele','mkd','rmd','rnfr','rnto','stor','stou'] restart_position = 0 # comply with (possibly troublesome) RFC959 requirements # This is necessary to correctly run an active data connection # through a firewall that triggers on the source port (expected # to be 'L-1', or 20 in the normal case). bind_local_minus_one = 0 def __init__ (self, server, conn, addr): self.server = server self.current_mode = 'a' self.addr = addr asynchat.async_chat.__init__ (self, conn) self.set_terminator ('\r\n') # client data port. Defaults to 'the same as the control connection'. self.client_addr = (addr[0], 21) self.client_dc = None self.in_buffer = '' self.closing = 0 self.passive_acceptor = None self.passive_connection = None self.filesystem = None self.authorized = 0 # send the greeting self.respond ( '220 %s FTP server (Medusa Async V%s [experimental]) ready.' % ( self.server.hostname, VERSION ) ) # def __del__ (self): # print 'ftp_channel.__del__()' # -------------------------------------------------- # async-library methods # -------------------------------------------------- def handle_expt (self): # this is handled below. not sure what I could # do here to make that code less kludgish. pass def collect_incoming_data (self, data): self.in_buffer = self.in_buffer + data if len(self.in_buffer) > 4096: # silently truncate really long lines # (possible denial-of-service attack) self.in_buffer = '' def found_terminator (self): line = self.in_buffer if not len(line): return sp = string.find (line, ' ') if sp != -1: line = [line[:sp], line[sp+1:]] else: line = [line] command = string.lower (line[0]) # watch especially for 'urgent' abort commands. if string.find (command, 'abor') != -1: # strip off telnet sync chars and the like... while command and command[0] not in string.letters: command = command[1:] fun_name = 'cmd_%s' % command if command != 'pass': self.log ('<== %s' % repr(self.in_buffer)[1:-1]) else: self.log ('<== %s' % line[0]+' ') self.in_buffer = '' if not hasattr (self, fun_name): self.command_not_understood (line[0]) return fun = getattr (self, fun_name) if (not self.authorized) and (command not in ('user', 'pass', 'help', 'quit')): self.respond ('530 Please log in with USER and PASS') elif (not self.check_command_authorization (command)): self.command_not_authorized (command) else: try: result = apply (fun, (line,)) except: self.server.total_exceptions.increment() (file, fun, line), t,v, tbinfo = asyncore.compact_traceback() if self.client_dc: try: self.client_dc.close() except: pass self.respond ( '451 Server Error: %s, %s: file: %s line: %s' % ( t,v,file,line, ) ) closed = 0 def close (self): if not self.closed: self.closed = 1 if self.passive_acceptor: self.passive_acceptor.close() if self.client_dc: self.client_dc.close() self.server.closed_sessions.increment() asynchat.async_chat.close (self) # -------------------------------------------------- # filesystem interface functions. # override these to provide access control or perform # other functions. # -------------------------------------------------- def cwd (self, line): return self.filesystem.cwd (line[1]) def cdup (self, line): return self.filesystem.cdup() def open (self, path, mode): return self.filesystem.open (path, mode) # returns a producer def listdir (self, path, long=0): return self.filesystem.listdir (path, long) def get_dir_list (self, line, long=0): # we need to scan the command line for arguments to '/bin/ls'... args = line[1:] path_args = [] for arg in args: if arg[0] != '-': path_args.append (arg) else: # ignore arguments pass if len(path_args) < 1: dir = '.' else: dir = path_args[0] return self.listdir (dir, long) # -------------------------------------------------- # authorization methods # -------------------------------------------------- def check_command_authorization (self, command): if command in self.write_commands and self.read_only: return 0 else: return 1 # -------------------------------------------------- # utility methods # -------------------------------------------------- def log (self, message): self.server.logger.log ( self.addr[0], '%d %s' % ( self.addr[1], message ) ) def respond (self, resp): self.log ('==> %s' % resp) self.push (resp + '\r\n') def command_not_understood (self, command): self.respond ("500 '%s': command not understood." % command) def command_not_authorized (self, command): self.respond ( "530 You are not authorized to perform the '%s' command" % ( command ) ) def make_xmit_channel (self): # In PASV mode, the connection may or may _not_ have been made # yet. [although in most cases it is... FTP Explorer being # the only exception I've yet seen]. This gets somewhat confusing # because things may happen in any order... pa = self.passive_acceptor if pa: if pa.ready: # a connection has already been made. conn, addr = self.passive_acceptor.ready cdc = xmit_channel (self, addr) cdc.set_socket (conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: # we're still waiting for a connect to the PASV port. cdc = xmit_channel (self) else: # not in PASV mode. ip, port = self.client_addr cdc = xmit_channel (self, self.client_addr) cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) if self.bind_local_minus_one: cdc.bind (('', self.server.port - 1)) try: cdc.connect ((ip, port)) except socket.error, why: self.respond ("425 Can't build data connection") self.client_dc = cdc # pretty much the same as xmit, but only right on the verge of # being worth a merge. def make_recv_channel (self, fd): pa = self.passive_acceptor if pa: if pa.ready: # a connection has already been made. conn, addr = pa.ready cdc = recv_channel (self, addr, fd) cdc.set_socket (conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: # we're still waiting for a connect to the PASV port. cdc = recv_channel (self, None, fd) else: # not in PASV mode. ip, port = self.client_addr cdc = recv_channel (self, self.client_addr, fd) cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) try: cdc.connect ((ip, port)) except socket.error, why: self.respond ("425 Can't build data connection") self.client_dc = cdc type_map = { 'a':'ASCII', 'i':'Binary', 'e':'EBCDIC', 'l':'Binary' } type_mode_map = { 'a':'t', 'i':'b', 'e':'b', 'l':'b' } # -------------------------------------------------- # command methods # -------------------------------------------------- def cmd_type (self, line): 'specify data transfer type' # ascii, ebcdic, image, local t = string.lower (line[1]) # no support for EBCDIC # if t not in ['a','e','i','l']: if t not in ['a','i','l']: self.command_not_understood (string.join (line)) elif t == 'l' and (len(line) > 2 and line[2] != '8'): self.respond ('504 Byte size must be 8') else: self.current_mode = t self.respond ('200 Type set to %s.' % self.type_map[t]) def cmd_quit (self, line): 'terminate session' self.respond ('221 Goodbye.') self.close_when_done() def cmd_port (self, line): 'specify data connection port' info = string.split (line[1], ',') ip = string.join (info[:4], '.') port = string.atoi(info[4])*256 + string.atoi(info[5]) # how many data connections at a time? # I'm assuming one for now... # TODO: we should (optionally) verify that the # ip number belongs to the client. [wu-ftpd does this?] self.client_addr = (ip, port) self.respond ('200 PORT command successful.') def new_passive_acceptor (self): # ensure that only one of these exists at a time. if self.passive_acceptor is not None: self.passive_acceptor.close() self.passive_acceptor = None self.passive_acceptor = passive_acceptor (self) return self.passive_acceptor def cmd_pasv (self, line): 'prepare for server-to-server transfer' pc = self.new_passive_acceptor() port = pc.addr[1] ip_addr = pc.control_channel.getsockname()[0] self.respond ( '227 Entering Passive Mode (%s,%d,%d)' % ( string.join (string.split (ip_addr, '.'), ','), port/256, port%256 ) ) self.client_dc = None def cmd_nlst (self, line): 'give name list of files in directory' # ncftp adds the -FC argument for the user-visible 'nlist' # command. We could try to emulate ls flags, but not just yet. if '-FC' in line: line.remove ('-FC') try: dir_list_producer = self.get_dir_list (line, 0) except os.error, why: self.respond ('550 Could not list directory: %s' % repr(why)) return self.respond ( '150 Opening %s mode data connection for file list' % ( self.type_map[self.current_mode] ) ) self.make_xmit_channel() self.client_dc.push_with_producer (dir_list_producer) self.client_dc.close_when_done() def cmd_list (self, line): 'give list files in a directory' try: dir_list_producer = self.get_dir_list (line, 1) except os.error, why: self.respond ('550 Could not list directory: %s' % repr(why)) return self.respond ( '150 Opening %s mode data connection for file list' % ( self.type_map[self.current_mode] ) ) self.make_xmit_channel() self.client_dc.push_with_producer (dir_list_producer) self.client_dc.close_when_done() def cmd_cwd (self, line): 'change working directory' if self.cwd (line): self.respond ('250 CWD command successful.') else: self.respond ('550 No such directory.') def cmd_cdup (self, line): 'change to parent of current working directory' if self.cdup(line): self.respond ('250 CDUP command successful.') else: self.respond ('550 No such directory.') def cmd_pwd (self, line): 'print the current working directory' self.respond ( '257 "%s" is the current directory.' % ( self.filesystem.current_directory() ) ) # modification time # example output: # 213 19960301204320 def cmd_mdtm (self, line): 'show last modification time of file' filename = line[1] if not self.filesystem.isfile (filename): self.respond ('550 "%s" is not a file' % filename) else: mtime = time.gmtime(self.filesystem.stat(filename)[stat.ST_MTIME]) self.respond ( '213 %4d%02d%02d%02d%02d%02d' % ( mtime[0], mtime[1], mtime[2], mtime[3], mtime[4], mtime[5] ) ) def cmd_noop (self, line): 'do nothing' self.respond ('200 NOOP command successful.') def cmd_size (self, line): 'return size of file' filename = line[1] if not self.filesystem.isfile (filename): self.respond ('550 "%s" is not a file' % filename) else: self.respond ( '213 %d' % (self.filesystem.stat(filename)[stat.ST_SIZE]) ) def cmd_retr (self, line): 'retrieve a file' if len(line) < 2: self.command_not_understood (string.join (line)) else: file = line[1] if not self.filesystem.isfile (file): self.log_info ('checking %s' % file) self.respond ('550 No such file') else: try: # FIXME: for some reason, 'rt' isn't working on win95 mode = 'r'+self.type_mode_map[self.current_mode] fd = self.open (file, mode) except IOError, why: self.respond ('553 could not open file for reading: %s' % (repr(why))) return self.respond ( "150 Opening %s mode data connection for file '%s'" % ( self.type_map[self.current_mode], file ) ) self.make_xmit_channel() if self.restart_position: # try to position the file as requested, but # give up silently on failure (the 'file object' # may not support seek()) try: fd.seek (self.restart_position) except: pass self.restart_position = 0 self.client_dc.push_with_producer ( file_producer (self, self.client_dc, fd) ) self.client_dc.close_when_done() def cmd_stor (self, line, mode='wb'): 'store a file' if len (line) < 2: self.command_not_understood (string.join (line)) else: if self.restart_position: restart_position = 0 self.respond ('553 restart on STOR not yet supported') return file = line[1] # todo: handle that type flag try: fd = self.open (file, mode) except IOError, why: self.respond ('553 could not open file for writing: %s' % (repr(why))) return self.respond ( '150 Opening %s connection for %s' % ( self.type_map[self.current_mode], file ) ) self.make_recv_channel (fd) def cmd_abor (self, line): 'abort operation' if self.client_dc: self.client_dc.close() self.respond ('226 ABOR command successful.') def cmd_appe (self, line): 'append to a file' return self.cmd_stor (line, 'ab') def cmd_dele (self, line): if len (line) != 2: self.command_not_understood (string.join (line)) else: file = line[1] if self.filesystem.isfile (file): try: self.filesystem.unlink (file) self.respond ('250 DELE command successful.') except: self.respond ('550 error deleting file.') else: self.respond ('550 %s: No such file.' % file) def cmd_mkd (self, line): if len (line) != 2: self.command.not_understood (string.join (line)) else: path = line[1] try: self.filesystem.mkdir (path) self.respond ('257 MKD command successful.') except: self.respond ('550 error creating directory.') def cmd_rmd (self, line): if len (line) != 2: self.command.not_understood (string.join (line)) else: path = line[1] try: self.filesystem.rmdir (path) self.respond ('250 RMD command successful.') except: self.respond ('550 error removing directory.') def cmd_user (self, line): 'specify user name' if len(line) > 1: self.user = line[1] self.respond ('331 Password required.') else: self.command_not_understood (string.join (line)) def cmd_pass (self, line): 'specify password' if len(line) < 2: pw = '' else: pw = line[1] result, message, fs = self.server.authorizer.authorize (self, self.user, pw) if result: self.respond ('230 %s' % message) self.filesystem = fs self.authorized = 1 self.log_info('Successful login: Filesystem=%s' % repr(fs)) else: self.respond ('530 %s' % message) def cmd_rest (self, line): 'restart incomplete transfer' try: pos = string.atoi (line[1]) except ValueError: self.command_not_understood (string.join (line)) self.restart_position = pos self.respond ( '350 Restarting at %d. Send STORE or RETRIEVE to initiate transfer.' % pos ) def cmd_stru (self, line): 'obsolete - set file transfer structure' if line[1] in 'fF': # f == 'file' self.respond ('200 STRU F Ok') else: self.respond ('504 Unimplemented STRU type') def cmd_mode (self, line): 'obsolete - set file transfer mode' if line[1] in 'sS': # f == 'file' self.respond ('200 MODE S Ok') else: self.respond ('502 Unimplemented MODE type') # The stat command has two personalities. Normally it returns status # information about the current connection. But if given an argument, # it is equivalent to the LIST command, with the data sent over the # control connection. Strange. But wuftpd, ftpd, and nt's ftp server # all support it. # ## def cmd_stat (self, line): ## 'return status of server' ## pass def cmd_syst (self, line): 'show operating system type of server system' # Replying to this command is of questionable utility, because # this server does not behave in a predictable way w.r.t. the # output of the LIST command. We emulate Unix ls output, but # on win32 the pathname can contain drive information at the front # Currently, the combination of ensuring that os.sep == '/' # and removing the leading slash when necessary seems to work. # [cd'ing to another drive also works] # # This is how wuftpd responds, and is probably # the most expected. The main purpose of this reply is so that # the client knows to expect Unix ls-style LIST output. self.respond ('215 UNIX Type: L8') # one disadvantage to this is that some client programs # assume they can pass args to /bin/ls. # a few typical responses: # 215 UNIX Type: L8 (wuftpd) # 215 Windows_NT version 3.51 # 215 VMS MultiNet V3.3 # 500 'SYST': command not understood. (SVR4) def cmd_help (self, line): 'give help information' # find all the methods that match 'cmd_xxxx', # use their docstrings for the help response. attrs = dir(self.__class__) help_lines = [] for attr in attrs: if attr[:4] == 'cmd_': x = getattr (self, attr) if type(x) == type(self.cmd_help): if x.__doc__: help_lines.append ('\t%s\t%s' % (attr[4:], x.__doc__)) if help_lines: self.push ('214-The following commands are recognized\r\n') self.push_with_producer (producers.lines_producer (help_lines)) self.push ('214\r\n') else: self.push ('214-\r\n\tHelp Unavailable\r\n214\r\n') class ftp_server (asyncore.dispatcher): # override this to spawn a different FTP channel class. ftp_channel_class = ftp_channel SERVER_IDENT = 'FTP Server (V%s)' % VERSION def __init__ ( self, authorizer, hostname =None, ip ='', port =21, resolver =None, logger_object=logger.file_logger (sys.stdout) ): self.ip = ip self.port = port self.authorizer = authorizer if hostname is None: self.hostname = socket.gethostname() else: self.hostname = hostname # statistics self.total_sessions = counter() self.closed_sessions = counter() self.total_files_out = counter() self.total_files_in = counter() self.total_bytes_out = counter() self.total_bytes_in = counter() self.total_exceptions = counter() # asyncore.dispatcher.__init__ (self) self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind ((self.ip, self.port)) self.listen (5) if not logger_object: logger_object = sys.stdout if resolver: self.logger = logger.resolving_logger (resolver, logger_object) else: self.logger = logger.unresolving_logger (logger_object) self.log_info('FTP server started at %s\n\tAuthorizer:%s\n\tHostname: %s\n\tPort: %d' % ( time.ctime(time.time()), repr (self.authorizer), self.hostname, self.port) ) def writable (self): return 0 def handle_read (self): pass def handle_connect (self): pass def handle_accept (self): conn, addr = self.accept() self.total_sessions.increment() self.log_info('Incoming connection from %s:%d' % (addr[0], addr[1])) self.ftp_channel_class (self, conn, addr) # return a producer describing the state of the server def status (self): def nice_bytes (n): return string.join (status_handler.english_bytes (n)) return producers.lines_producer ( ['

    %s

    ' % self.SERVER_IDENT, '
    Listening on Host: %s' % self.hostname, 'Port: %d' % self.port, '
    Sessions', 'Total: %s' % self.total_sessions, 'Current: %d' % (self.total_sessions.as_long() - self.closed_sessions.as_long()), '
    Files', 'Sent: %s' % self.total_files_out, 'Received: %s' % self.total_files_in, '
    Bytes', 'Sent: %s' % nice_bytes (self.total_bytes_out.as_long()), 'Received: %s' % nice_bytes (self.total_bytes_in.as_long()), '
    Exceptions: %s' % self.total_exceptions, ] ) # ====================================================================== # Data Channel Classes # ====================================================================== # This socket accepts a data connection, used when the server has been # placed in passive mode. Although the RFC implies that we ought to # be able to use the same acceptor over and over again, this presents # a problem: how do we shut it off, so that we are accepting # connections only when we expect them? [we can't] # # wuftpd, and probably all the other servers, solve this by allowing # only one connection to hit this acceptor. They then close it. Any # subsequent data-connection command will then try for the default # port on the client side [which is of course never there]. So the # 'always-send-PORT/PASV' behavior seems required. # # Another note: wuftpd will also be listening on the channel as soon # as the PASV command is sent. It does not wait for a data command # first. # --- we need to queue up a particular behavior: # 1) xmit : queue up producer[s] # 2) recv : the file object # # It would be nice if we could make both channels the same. Hmmm.. # class passive_acceptor (asyncore.dispatcher): ready = None def __init__ (self, control_channel): # connect_fun (conn, addr) asyncore.dispatcher.__init__ (self) self.control_channel = control_channel self.create_socket (socket.AF_INET, socket.SOCK_STREAM) # bind to an address on the interface that the # control connection is coming from. self.bind (( self.control_channel.getsockname()[0], 0 )) self.addr = self.getsockname() self.listen (1) # def __del__ (self): # print 'passive_acceptor.__del__()' def log (self, *ignore): pass def handle_accept (self): conn, addr = self.accept() dc = self.control_channel.client_dc if dc is not None: dc.set_socket (conn) dc.addr = addr dc.connected = 1 self.control_channel.passive_acceptor = None else: self.ready = conn, addr self.close() class xmit_channel (asynchat.async_chat): # for an ethernet, you want this to be fairly large, in fact, it # _must_ be large for performance comparable to an ftpd. [64k] we # ought to investigate automatically-sized buffers... ac_out_buffer_size = 16384 bytes_out = 0 def __init__ (self, channel, client_addr=None): self.channel = channel self.client_addr = client_addr asynchat.async_chat.__init__ (self) # def __del__ (self): # print 'xmit_channel.__del__()' def log (*args): pass def readable (self): return not self.connected def writable (self): return 1 def send (self, data): result = asynchat.async_chat.send (self, data) self.bytes_out = self.bytes_out + result return result def handle_error (self): # usually this is to catch an unexpected disconnect. self.log_info ('unexpected disconnect on data xmit channel', 'error') try: self.close() except: pass # TODO: there's a better way to do this. we need to be able to # put 'events' in the producer fifo. to do this cleanly we need # to reposition the 'producer' fifo as an 'event' fifo. def close (self): c = self.channel s = c.server c.client_dc = None s.total_files_out.increment() s.total_bytes_out.increment (self.bytes_out) if not len(self.producer_fifo): c.respond ('226 Transfer complete') elif not c.closed: c.respond ('426 Connection closed; transfer aborted') del c del s del self.channel asynchat.async_chat.close (self) class recv_channel (asyncore.dispatcher): def __init__ (self, channel, client_addr, fd): self.channel = channel self.client_addr = client_addr self.fd = fd asyncore.dispatcher.__init__ (self) self.bytes_in = counter() def log (self, *ignore): pass def handle_connect (self): pass def writable (self): return 0 def recv (*args): result = apply (asyncore.dispatcher.recv, args) self = args[0] self.bytes_in.increment(len(result)) return result buffer_size = 8192 def handle_read (self): block = self.recv (self.buffer_size) if block: try: self.fd.write (block) except IOError: self.log_info ('got exception writing block...', 'error') def handle_close (self): s = self.channel.server s.total_files_in.increment() s.total_bytes_in.increment(self.bytes_in.as_long()) self.fd.close() self.channel.respond ('226 Transfer complete.') self.close() import filesys # not much of a doorman! 8^) class dummy_authorizer: def __init__ (self, root='/'): self.root = root def authorize (self, channel, username, password): channel.persona = -1, -1 channel.read_only = 1 return 1, 'Ok.', filesys.os_filesystem (self.root) class anon_authorizer: def __init__ (self, root='/'): self.root = root def authorize (self, channel, username, password): if username in ('ftp', 'anonymous'): channel.persona = -1, -1 channel.read_only = 1 return 1, 'Ok.', filesys.os_filesystem (self.root) else: return 0, 'Password invalid.', None # =========================================================================== # Unix-specific improvements # =========================================================================== if os.name == 'posix': class unix_authorizer: # return a trio of (success, reply_string, filesystem) def authorize (self, channel, username, password): import crypt import pwd try: info = pwd.getpwnam (username) except KeyError: return 0, 'No such user.', None mangled = info[1] if crypt.crypt (password, mangled[:2]) == mangled: channel.read_only = 0 fs = filesys.schizophrenic_unix_filesystem ( '/', info[5], persona = (info[2], info[3]) ) return 1, 'Login successful.', fs else: return 0, 'Password invalid.', None def __repr__ (self): return '' # simple anonymous ftp support class unix_authorizer_with_anonymous (unix_authorizer): def __init__ (self, root=None, real_users=0): self.root = root self.real_users = real_users def authorize (self, channel, username, password): if string.lower(username) in ['anonymous', 'ftp']: import pwd try: # ok, here we run into lots of confusion. # on some os', anon runs under user 'nobody', # on others as 'ftp'. ownership is also critical. # need to investigate. # linux: new linuxen seem to have nobody's UID=-1, # which is an illegal value. Use ftp. ftp_user_info = pwd.getpwnam ('ftp') if string.lower(os.uname()[0]) == 'linux': nobody_user_info = pwd.getpwnam ('ftp') else: nobody_user_info = pwd.getpwnam ('nobody') channel.read_only = 1 if self.root is None: self.root = ftp_user_info[5] fs = filesys.unix_filesystem (self.root, '/') return 1, 'Anonymous Login Successful', fs except KeyError: return 0, 'Anonymous account not set up', None elif self.real_users: return unix_authorizer.authorize ( self, channel, username, password ) else: return 0, 'User logins not allowed', None class file_producer: block_size = 16384 def __init__ (self, server, dc, fd): self.fd = fd self.done = 0 def more (self): if self.done: return '' else: block = self.fd.read (self.block_size) if not block: self.fd.close() self.done = 1 return block # usage: ftp_server /PATH/TO/FTP/ROOT PORT # for example: # $ ftp_server /home/users/ftp 8021 if os.name == 'posix': def test (port='8021'): import sys fs = ftp_server ( unix_authorizer(), port=string.atoi (port) ) try: asyncore.loop() except KeyboardInterrupt: self.log_info('FTP server shutting down. (received SIGINT)', 'warning') # close everything down on SIGINT. # of course this should be a cleaner shutdown. asyncore.close_all() if __name__ == '__main__': test (sys.argv[1]) # not unix else: def test (): fs = ftp_server (dummy_authorizer()) if __name__ == '__main__': test () # this is the command list from the wuftpd man page # '*' means we've implemented it. # '!' requires write access # command_documentation = { 'abor': 'abort previous command', #* 'acct': 'specify account (ignored)', 'allo': 'allocate storage (vacuously)', 'appe': 'append to a file', #*! 'cdup': 'change to parent of current working directory', #* 'cwd': 'change working directory', #* 'dele': 'delete a file', #! 'help': 'give help information', #* 'list': 'give list files in a directory', #* 'mkd': 'make a directory', #! 'mdtm': 'show last modification time of file', #* 'mode': 'specify data transfer mode', 'nlst': 'give name list of files in directory', #* 'noop': 'do nothing', #* 'pass': 'specify password', #* 'pasv': 'prepare for server-to-server transfer', #* 'port': 'specify data connection port', #* 'pwd': 'print the current working directory', #* 'quit': 'terminate session', #* 'rest': 'restart incomplete transfer', #* 'retr': 'retrieve a file', #* 'rmd': 'remove a directory', #! 'rnfr': 'specify rename-from file name', #! 'rnto': 'specify rename-to file name', #! 'site': 'non-standard commands (see next section)', 'size': 'return size of file', #* 'stat': 'return status of server', #* 'stor': 'store a file', #*! 'stou': 'store a file with a unique name', #! 'stru': 'specify data transfer structure', 'syst': 'show operating system type of server system', #* 'type': 'specify data transfer type', #* 'user': 'specify user name', #* 'xcup': 'change to parent of current working directory (deprecated)', 'xcwd': 'change working directory (deprecated)', 'xmkd': 'make a directory (deprecated)', #! 'xpwd': 'print the current working directory (deprecated)', 'xrmd': 'remove a directory (deprecated)', #! } # debugging aid (linux) def get_vm_size (): return string.atoi (string.split(open ('/proc/self/stat').readline())[22]) def print_vm(): print 'vm: %8dk' % (get_vm_size()/1024) M2Crypto-0.22.6rc4/demo/medusa/ftps_server.py0000664000175000017500000003576612607370517021264 0ustar matejmatej00000000000000"""An FTP/TLS server built on Medusa's ftp_server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # Python import socket, string, sys, time # Medusa from counter import counter import asynchat, asyncore, ftp_server, logger # M2Crypto from M2Crypto import SSL VERSION_STRING='0.09' class ftp_tls_channel(ftp_server.ftp_channel): """FTP/TLS server channel for Medusa.""" def __init__(self, server, ssl_ctx, conn, addr): """Initialise the channel.""" self.ssl_ctx = ssl_ctx self.server = server self.current_mode = 'a' self.addr = addr asynchat.async_chat.__init__(self, conn) self.set_terminator('\r\n') self.client_addr = (addr[0], 21) self.client_dc = None self.in_buffer = '' self.closing = 0 self.passive_acceptor = None self.passive_connection = None self.filesystem = None self.authorized = 0 self._ssl_accepting = 0 self._ssl_accepted = 0 self._pbsz = None self._prot = None resp = '220 %s M2Crypto (Medusa) FTP/TLS server v%s ready.' self.respond(resp % (self.server.hostname, VERSION_STRING)) def writable(self): return self._ssl_accepting or self._ssl_accepted def handle_read(self): """Handle a read event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_read(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def handle_write(self): """Handle a write event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_write(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' def found_terminator(self): """Dispatch the FTP command.""" line = self.in_buffer if not len(line): return sp = string.find(line, ' ') if sp != -1: line = [line[:sp], line[sp+1:]] else: line = [line] command = string.lower(line[0]) if string.find(command, 'stor') != -1: while command and command[0] not in string.letters: command = command[1:] func_name = 'cmd_%s' % command if command != 'pass': self.log('<== %s' % repr(self.in_buffer)[1:-1]) else: self.log('<== %s' % line[0]+' ') self.in_buffer = '' if not hasattr(self, func_name): self.command_not_understood(line[0]) return func = getattr(self, func_name) if not self.check_command_authorization(command): self.command_not_authorized(command) else: try: result = apply(func, (line,)) except: self.server.total_exceptions.increment() (file, func, line), t, v, tbinfo = asyncore.compact_traceback() if self.client_dc: try: self.client_dc_close() except: pass resp = '451 Server error: %s, %s: file %s line: %s' self.respond(resp % (t, v, file, line)) def make_xmit_channel(self): """Create a connection for sending data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_xmit_channel(self, conn, self.ssl_ctx, addr) else: cdc = ftp_server.xmit_channel(self, addr) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, None) else: cdc = ftp_server.xmit_channel(self) else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, self.client_addr) else: cdc = ftp_server.xmit_channel(self, self.client_addr) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) if self.bind_local_minus_one: cdc.bind(('', self.server.port - 1)) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def make_recv_channel(self, fd): """Create a connection for receiving data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_recv_channel(self, conn, self.ssl_ctx, addr, fd) else: cdc = ftp_server.recv_channel(self, addr, fd) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, None, fd) else: cdc = ftp_server.recv_channel(self, None, fd) else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, self._prot, self.client_addr, fd) else: cdc = ftp_server.recv_channel(self, self.client_addr, fd) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def cmd_auth(self, line): """Prepare for TLS operation.""" # XXX Handle variations. if line[1] != 'TLS': self.command_not_understood (string.join(line)) else: self.respond('234 AUTH TLS successful') self._ssl_accepting = 1 self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.addr) self.socket.setup_ssl() self.socket.set_accept_state() self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 def cmd_pbsz(self, line): """Negotiate size of buffer for secure data transfer. For FTP/TLS the only valid value for the parameter is '0'; any other value is accepted but ignored.""" if not (self._ssl_accepting or self._ssl_accepted): return self.respond('503 AUTH TLS must be issued prior to PBSZ') self._pbsz = 1 self.respond('200 PBSZ=0 successful.') def cmd_prot(self, line): """Negotiate the security level of the data connection.""" if self._pbsz is None: return self.respond('503 PBSZ must be issued prior to PROT') if line[1] == 'C': self.respond('200 Protection set to Clear') self._pbsz = None self._prot = None elif line[1] == 'P': self.respond('200 Protection set to Private') self._prot = 1 elif line[1] in ('S', 'E'): self.respond('536 PROT %s unsupported' % line[1]) else: self.respond('504 PROT %s unsupported' % line[1]) class ftp_tls_server(ftp_server.ftp_server): """FTP/TLS server for Medusa.""" SERVER_IDENT = 'M2Crypto FTP/TLS Server (v%s)' % VERSION_STRING ftp_channel_class = ftp_tls_channel def __init__(self, authz, ssl_ctx, host=None, ip='', port=21, resolver=None, log_obj=None): """Initialise the server.""" self.ssl_ctx = ssl_ctx self.ip = ip self.port = port self.authorizer = authz if host is None: self.hostname = socket.gethostname() else: self.hostname = host self.total_sessions = counter() self.closed_sessions = counter() self.total_files_out = counter() self.total_files_in = counter() self.total_bytes_out = counter() self.total_bytes_in = counter() self.total_exceptions = counter() asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((self.ip, self.port)) self.listen(5) if log_obj is None: log_obj = sys.stdout if resolver: self.logger = logger.resolving_logger(resolver, log_obj) else: self.logger = logger.unresolving_logger(logger.file_logger(sys.stdout)) l = 'M2Crypto (Medusa) FTP/TLS server started at %s\n\tAuthz: %s\n\tHostname: %s\n\tPort: %d' self.log_info(l % (time.ctime(time.time()), repr(self.authorizer), self.hostname, self.port)) def handle_accept(self): """Accept a socket and dispatch a channel to handle it.""" conn, addr = self.accept() self.total_sessions.increment() self.log_info('Connection from %s:%d' % addr) self.ftp_channel_class(self, self.ssl_ctx, conn, addr) class nbio_ftp_tls_actor: """TLS protocol negotiation mixin for FTP/TLS.""" def tls_init(self, sock, ssl_ctx, client_addr): """Perform TLS protocol negotiation.""" self.ssl_ctx = ssl_ctx self.client_addr = client_addr self._ssl_handshaking = 1 self._ssl_handshake_ok = 0 if sock: self.socket = SSL.Connection(self.ssl_ctx, sock) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() # else the client hasn't connected yet; when that happens, # handle_connect() will be triggered. def tls_neg_ok(self): """Return status of TLS protocol negotiation.""" if self._ssl_handshaking: self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 return self._ssl_handshake_ok def handle_connect(self): """Handle a data connection that occurs after this instance came into being. When this handler is triggered, self.socket has been created and refers to the underlying connected socket.""" self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' class tls_xmit_channel(nbio_ftp_tls_actor, ftp_server.xmit_channel): """TLS driver for a send-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr=None): """Initialise the driver.""" ftp_server.xmit_channel.__init__(self, channel, client_addr) self.tls_init(conn, ssl_ctx, client_addr) def readable(self): """This channel is readable iff TLS negotiation is in progress. (Which implies a connected channel, of course.)""" if not self.connected: return 0 else: return self._ssl_handshaking def writable(self): """This channel is writable iff TLS negotiation is in progress or the application has data to send.""" if self._ssl_handshaking: return 1 else: return ftp_server.xmit_channel.writable(self) def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_write(self) class tls_recv_channel(nbio_ftp_tls_actor, ftp_server.recv_channel): """TLS driver for a receive-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr, fd): """Initialise the driver.""" ftp_server.recv_channel.__init__(self, channel, client_addr, fd) self.tls_init(conn, ssl_ctx, client_addr) def writable(self): """This channel is writable iff TLS negotiation is in progress.""" return self._ssl_handshaking def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_write(self) M2Crypto-0.22.6rc4/demo/medusa/http_date.py0000664000175000017500000000514412607370517020661 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- import re import string import time def concat (*args): return ''.join (args) def join (seq, field=' '): return field.join (seq) def group (s): return '(' + s + ')' short_days = ['sun','mon','tue','wed','thu','fri','sat'] long_days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'] short_day_reg = group (join (short_days, '|')) long_day_reg = group (join (long_days, '|')) daymap = {} for i in range(7): daymap[short_days[i]] = i daymap[long_days[i]] = i hms_reg = join (3 * [group('[0-9][0-9]')], ':') months = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'] monmap = {} for i in range(12): monmap[months[i]] = i+1 months_reg = group (join (months, '|')) # From draft-ietf-http-v11-spec-07.txt/3.3.1 # Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 # Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 # Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format # rfc822 format rfc822_date = join ( [concat (short_day_reg,','), # day group('[0-9][0-9]?'), # date months_reg, # month group('[0-9]+'), # year hms_reg, # hour minute second 'gmt' ], ' ' ) rfc822_reg = re.compile (rfc822_date) def unpack_rfc822 (m): g = m.group a = string.atoi return ( a(g(4)), # year monmap[g(3)], # month a(g(2)), # day a(g(5)), # hour a(g(6)), # minute a(g(7)), # second 0, 0, 0 ) # rfc850 format rfc850_date = join ( [concat (long_day_reg,','), join ( [group ('[0-9][0-9]?'), months_reg, group ('[0-9]+') ], '-' ), hms_reg, 'gmt' ], ' ' ) rfc850_reg = re.compile (rfc850_date) # they actually unpack the same way def unpack_rfc850 (m): g = m.group a = string.atoi return ( a(g(4)), # year monmap[g(3)], # month a(g(2)), # day a(g(5)), # hour a(g(6)), # minute a(g(7)), # second 0, 0, 0 ) # parsdate.parsedate - ~700/sec. # parse_http_date - ~1333/sec. def build_http_date (when): return time.strftime ('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(when)) def parse_http_date (d): d = string.lower (d) tz = time.timezone m = rfc850_reg.match (d) if m and m.end() == len(d): retval = int (time.mktime (unpack_rfc850(m)) - tz) else: m = rfc822_reg.match (d) if m and m.end() == len(d): retval = int (time.mktime (unpack_rfc822(m)) - tz) else: return 0 # Thanks to Craig Silverstein for pointing # out the DST discrepancy if time.daylight and time.localtime(retval)[-1] == 1: # DST correction retval = retval + (tz - time.altzone) return retval M2Crypto-0.22.6rc4/demo/medusa/http_server.py0000664000175000017500000004747612607370517021270 0ustar matejmatej00000000000000#! /usr/local/bin/python # -*- Mode: Python; tab-width: 4 -*- # # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # # python modules import os import re import socket import stat import string import sys import time # async modules import asyncore import asynchat # medusa modules import http_date import producers import status_handler import logger VERSION_STRING = '1.1' from counter import counter from urllib import unquote # =========================================================================== # Request Object # =========================================================================== class http_request: # default reply code reply_code = 200 request_counter = counter() # Whether to automatically use chunked encoding when # # HTTP version is 1.1 # Content-Length is not set # Chunked encoding is not already in effect # # If your clients are having trouble, you might want to disable this. use_chunked = 1 # by default, this request object ignores user data. collector = None def __init__ (self, *args): # unpack information about the request (self.channel, self.request, self.command, self.uri, self.version, self.header) = args self.outgoing = fifo() self.reply_headers = { 'Server' : 'Medusa/%s' % VERSION_STRING, 'Date' : http_date.build_http_date (time.time()) } self.request_number = http_request.request_counter.increment() self._split_uri = None self._header_cache = {} # -------------------------------------------------- # reply header management # -------------------------------------------------- def __setitem__ (self, key, value): self.reply_headers[key] = value def __getitem__ (self, key): return self.reply_headers[key] def has_key (self, key): return self.reply_headers.has_key (key) def build_reply_header (self): return string.join ( [self.response(self.reply_code)] + map ( lambda x: '%s: %s' % x, self.reply_headers.items() ), '\r\n' ) + '\r\n\r\n' # -------------------------------------------------- # split a uri # -------------------------------------------------- # ;?# path_regex = re.compile ( # path params query fragment r'([^;?#]*)(;[^?#]*)?(\?[^#]*)?(#.*)?' ) def split_uri (self): if self._split_uri is None: m = self.path_regex.match (self.uri) if m.end() != len(self.uri): raise ValueError, "Broken URI" else: self._split_uri = m.groups() return self._split_uri def get_header_with_regex (self, head_reg, group): for line in self.header: m = head_reg.match (line) if m.end() == len(line): return head_reg.group (group) return '' def get_header (self, header): header = string.lower (header) hc = self._header_cache if not hc.has_key (header): h = header + ': ' hl = len(h) for line in self.header: if string.lower (line[:hl]) == h: r = line[hl:] hc[header] = r return r hc[header] = None return None else: return hc[header] # -------------------------------------------------- # user data # -------------------------------------------------- def collect_incoming_data (self, data): if self.collector: self.collector.collect_incoming_data (data) else: self.log_info( 'Dropping %d bytes of incoming request data' % len(data), 'warning' ) def found_terminator (self): if self.collector: self.collector.found_terminator() else: self.log_info ( 'Unexpected end-of-record for incoming request', 'warning' ) def push (self, thing): if type(thing) == type(''): self.outgoing.push (producers.simple_producer (thing)) else: self.outgoing.push (thing) def response (self, code=200): message = self.responses[code] self.reply_code = code return 'HTTP/%s %d %s' % (self.version, code, message) def error (self, code): self.reply_code = code message = self.responses[code] s = self.DEFAULT_ERROR_MESSAGE % { 'code': code, 'message': message, } self['Content-Length'] = len(s) self['Content-Type'] = 'text/html' # make an error reply self.push (s) self.done() # can also be used for empty replies reply_now = error def done (self): "finalize this transaction - send output to the http channel" # ---------------------------------------- # persistent connection management # ---------------------------------------- # --- BUCKLE UP! ---- connection = string.lower (get_header (CONNECTION, self.header)) close_it = 0 wrap_in_chunking = 0 if self.version == '1.0': if connection == 'keep-alive': if not self.has_key ('Content-Length'): close_it = 1 else: self['Connection'] = 'Keep-Alive' else: close_it = 1 elif self.version == '1.1': if connection == 'close': close_it = 1 elif not self.has_key ('Content-Length'): if self.has_key ('Transfer-Encoding'): if not self['Transfer-Encoding'] == 'chunked': close_it = 1 elif self.use_chunked: self['Transfer-Encoding'] = 'chunked' wrap_in_chunking = 1 else: close_it = 1 elif self.version is None: # Although we don't *really* support http/0.9 (because we'd have to # use \r\n as a terminator, and it would just yuck up a lot of stuff) # it's very common for developers to not want to type a version number # when using telnet to debug a server. close_it = 1 outgoing_header = producers.simple_producer (self.build_reply_header()) if close_it: self['Connection'] = 'close' if wrap_in_chunking: outgoing_producer = producers.chunked_producer ( producers.composite_producer (self.outgoing) ) # prepend the header outgoing_producer = producers.composite_producer ( fifo([outgoing_header, outgoing_producer]) ) else: # prepend the header self.outgoing.push_front (outgoing_header) outgoing_producer = producers.composite_producer (self.outgoing) # apply a few final transformations to the output self.channel.push_with_producer ( # globbing gives us large packets producers.globbing_producer ( # hooking lets us log the number of bytes sent producers.hooked_producer ( outgoing_producer, self.log ) ) ) self.channel.current_request = None if close_it: self.channel.close_when_done() def log_date_string (self, when): return time.strftime ( '%d/%b/%Y:%H:%M:%S ', time.gmtime(when) ) + tz_for_log def log (self, bytes): self.channel.server.logger.log ( self.channel.addr[0], '%d - - [%s] "%s" %d %d\n' % ( self.channel.addr[1], self.log_date_string (time.time()), self.request, self.reply_code, bytes ) ) responses = { 100: "Continue", 101: "Switching Protocols", 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 300: "Multiple Choices", 301: "Moved Permanently", 302: "Moved Temporarily", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Time-out", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Request Entity Too Large", 414: "Request-URI Too Large", 415: "Unsupported Media Type", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Time-out", 505: "HTTP Version not supported" } # Default error message DEFAULT_ERROR_MESSAGE = string.join ( ['', 'Error response', '', '', '

    Error response

    ', '

    Error code %(code)d.', '

    Message: %(message)s.', '', '' ], '\r\n' ) # =========================================================================== # HTTP Channel Object # =========================================================================== class http_channel (asynchat.async_chat): # use a larger default output buffer ac_out_buffer_size = 1<<16 current_request = None channel_counter = counter() def __init__ (self, server, conn, addr): self.channel_number = http_channel.channel_counter.increment() self.request_counter = counter() asynchat.async_chat.__init__ (self, conn) self.server = server self.addr = addr self.set_terminator ('\r\n\r\n') self.in_buffer = '' self.creation_time = int (time.time()) self.check_maintenance() def __repr__ (self): ar = asynchat.async_chat.__repr__(self)[1:-1] return '<%s channel#: %s requests:%s>' % ( ar, self.channel_number, self.request_counter ) # Channel Counter, Maintenance Interval... maintenance_interval = 500 def check_maintenance (self): if not self.channel_number % self.maintenance_interval: self.maintenance() def maintenance (self): self.kill_zombies() # 30-minute zombie timeout. status_handler also knows how to kill zombies. zombie_timeout = 30 * 60 def kill_zombies (self): now = int (time.time()) for channel in asyncore.socket_map.values(): if channel.__class__ == self.__class__: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() # -------------------------------------------------- # send/recv overrides, good place for instrumentation. # -------------------------------------------------- # this information needs to get into the request object, # so that it may log correctly. def send (self, data): result = asynchat.async_chat.send (self, data) self.server.bytes_out.increment (len(data)) return result def recv (self, buffer_size): try: result = asynchat.async_chat.recv (self, buffer_size) self.server.bytes_in.increment (len(result)) return result except MemoryError: # --- Save a Trip to Your Service Provider --- # It's possible for a process to eat up all the memory of # the machine, and put it in an extremely wedged state, # where medusa keeps running and can't be shut down. This # is where MemoryError tends to get thrown, though of # course it could get thrown elsewhere. sys.exit ("Out of Memory!") def handle_error (self): t, v = sys.exc_info()[:2] if t is SystemExit: raise t, v else: asynchat.async_chat.handle_error (self) def log (self, *args): pass # -------------------------------------------------- # async_chat methods # -------------------------------------------------- def collect_incoming_data (self, data): if self.current_request: # we are receiving data (probably POST data) for a request self.current_request.collect_incoming_data (data) else: # we are receiving header (request) data self.in_buffer = self.in_buffer + data def found_terminator (self): if self.current_request: self.current_request.found_terminator() else: header = self.in_buffer self.in_buffer = '' lines = string.split (header, '\r\n') # -------------------------------------------------- # crack the request header # -------------------------------------------------- while lines and not lines[0]: # as per the suggestion of http-1.1 section 4.1, (and # Eric Parker ), ignore a leading # blank lines (buggy browsers tack it onto the end of # POST requests) lines = lines[1:] if not lines: self.close_when_done() return request = lines[0] # unquote path if necessary (thanks to Skip Montaro for pointing # out that we must unquote in piecemeal fashion). if '%' in request: request = unquote (request) command, uri, version = crack_request (request) header = join_headers (lines[1:]) r = http_request (self, request, command, uri, version, header) self.request_counter.increment() self.server.total_requests.increment() if command is None: self.log_info ('Bad HTTP request: %s' % repr(request), 'error') r.error (400) return # -------------------------------------------------- # handler selection and dispatch # -------------------------------------------------- for h in self.server.handlers: if h.match (r): try: self.current_request = r # This isn't used anywhere. # r.handler = h # CYCLE h.handle_request (r) except: self.server.exceptions.increment() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback() self.log_info( 'Server Error: %s, %s: file: %s line: %s' % (t,v,file,line), 'error') try: r.error (500) except: pass return # no handlers, so complain r.error (404) def writable (self): # this is just the normal async_chat 'writable', here for comparison return self.ac_out_buffer or len(self.producer_fifo) def writable_for_proxy (self): # this version of writable supports the idea of a 'stalled' producer # [i.e., it's not ready to produce any output yet] This is needed by # the proxy, which will be waiting for the magic combination of # 1) hostname resolved # 2) connection made # 3) data available. if self.ac_out_buffer: return 1 elif len(self.producer_fifo): p = self.producer_fifo.first() if hasattr (p, 'stalled'): return not p.stalled() else: return 1 # =========================================================================== # HTTP Server Object # =========================================================================== class http_server (asyncore.dispatcher): SERVER_IDENT = 'HTTP Server (V%s)' % VERSION_STRING channel_class = http_channel def __init__ (self, ip, port, resolver=None, logger_object=None): self.ip = ip self.port = port asyncore.dispatcher.__init__ (self) self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.handlers = [] if not logger_object: logger_object = logger.file_logger (sys.stdout) self.set_reuse_addr() self.bind ((ip, port)) # lower this to 5 if your OS complains self.listen (1024) host, port = self.socket.getsockname() if not ip: self.log_info('Computing default hostname', 'warning') ip = socket.gethostbyname (socket.gethostname()) try: self.server_name = socket.gethostbyaddr (ip)[0] except socket.error: self.log_info('Cannot do reverse lookup', 'warning') self.server_name = ip # use the IP address as the "hostname" self.server_port = port self.total_clients = counter() self.total_requests = counter() self.exceptions = counter() self.bytes_out = counter() self.bytes_in = counter() if not logger_object: logger_object = logger.file_logger (sys.stdout) if resolver: self.logger = logger.resolving_logger (resolver, logger_object) else: self.logger = logger.unresolving_logger (logger_object) self.log_info ( 'Medusa (V%s) started at %s' '\n\tHostname: %s' '\n\tPort:%d' '\n' % ( VERSION_STRING, time.ctime(time.time()), self.server_name, port, ) ) def writable (self): return 0 def handle_read (self): pass def readable (self): return self.accepting def handle_connect (self): pass def handle_accept (self): self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. self.log_info ('warning: server accept() threw an exception', 'warning') return except TypeError: # unpack non-sequence. this can happen when a read event # fires on a listening socket, but when we call accept() # we get EWOULDBLOCK, so dispatcher.accept() returns None. # Seen on FreeBSD3. self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning') return self.channel_class (self, conn, addr) def install_handler (self, handler, back=0): if back: self.handlers.append (handler) else: self.handlers.insert (0, handler) def remove_handler (self, handler): self.handlers.remove (handler) def status (self): def nice_bytes (n): return string.join (status_handler.english_bytes (n)) handler_stats = filter (None, map (maybe_status, self.handlers)) if self.total_clients: ratio = self.total_requests.as_long() / float(self.total_clients.as_long()) else: ratio = 0.0 return producers.composite_producer ( fifo ([producers.lines_producer ( ['

    %s

    ' % self.SERVER_IDENT, '
    Listening on: Host: %s' % self.server_name, 'Port: %d' % self.port, '

      ' '
    • Total Clients: %s' % self.total_clients, 'Requests: %s' % self.total_requests, 'Requests/Client: %.1f' % (ratio), '
    • Total Bytes In: %s' % (nice_bytes (self.bytes_in.as_long())), 'Bytes Out: %s' % (nice_bytes (self.bytes_out.as_long())), '
    • Total Exceptions: %s' % self.exceptions, '

    ' 'Extension List

      ', ])] + handler_stats + [producers.simple_producer('
    ')] ) ) def maybe_status (thing): if hasattr (thing, 'status'): return thing.status() else: return None CONNECTION = re.compile ('Connection: (.*)', re.IGNORECASE) # merge multi-line headers # [486dx2: ~500/sec] def join_headers (headers): r = [] for i in range(len(headers)): if headers[i][0] in ' \t': r[-1] = r[-1] + headers[i][1:] else: r.append (headers[i]) return r def get_header (head_reg, lines, group=1): for line in lines: m = head_reg.match (line) if m and m.end() == len(line): return m.group (group) return '' def get_header_match (head_reg, lines): for line in lines: m = head_reg.match (line) if m and m.end() == len(line): return m return '' REQUEST = re.compile ('([^ ]+) ([^ ]+)(( HTTP/([0-9.]+))$|$)') def crack_request (r): m = REQUEST.match (r) if m.end() == len(r): if m.group(3): version = m.group(5) else: version = None return string.lower (m.group(1)), m.group(2), version else: return None, None, None class fifo: def __init__ (self, list=None): if not list: self.list = [] else: self.list = list def __len__ (self): return len(self.list) def first (self): return self.list[0] def push_front (self, object): self.list.insert (0, object) def push (self, data): self.list.append (data) def pop (self): if self.list: result = self.list[0] del self.list[0] return (1, result) else: return (0, None) def compute_timezone_for_log (): if time.daylight: tz = time.altzone else: tz = time.timezone if tz > 0: neg = 1 else: neg = 0 tz = -tz h, rem = divmod (tz, 3600) m, rem = divmod (rem, 60) if neg: return '-%02d%02d' % (h, m) else: return '+%02d%02d' % (h, m) # if you run this program over a TZ change boundary, this will be invalid. tz_for_log = compute_timezone_for_log() if __name__ == '__main__': import sys if len(sys.argv) < 2: print 'usage: %s ' % (sys.argv[0]) else: import monitor import filesys import default_handler import status_handler import ftp_server import chat_server import resolver import logger rs = resolver.caching_resolver ('127.0.0.1') lg = logger.file_logger (sys.stdout) ms = monitor.secure_monitor_server ('fnord', '127.0.0.1', 9999) fs = filesys.os_filesystem (sys.argv[1]) dh = default_handler.default_handler (fs) hs = http_server ('', string.atoi (sys.argv[2]), rs, lg) hs.install_handler (dh) ftp = ftp_server.ftp_server ( ftp_server.dummy_authorizer(sys.argv[1]), port=8021, resolver=rs, logger_object=lg ) cs = chat_server.chat_server ('', 7777) sh = status_handler.status_extension([hs,ms,ftp,cs,rs]) hs.install_handler (sh) if ('-p' in sys.argv): def profile_loop (): try: asyncore.loop() except KeyboardInterrupt: pass import profile profile.run ('profile_loop()', 'profile.out') else: asyncore.loop() M2Crypto-0.22.6rc4/demo/medusa/https_server.py0000664000175000017500000000510212607370517021427 0ustar matejmatej00000000000000#!/usr/bin/env python """A https server built on Medusa's http_server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import asynchat, asyncore, http_server, socket, sys from M2Crypto import SSL VERSION_STRING='0.09' class https_channel(http_server.http_channel): def __init__(self, server, conn, addr): http_server.http_channel.__init__(self, server, conn, addr) def send(self, data): try: result = self.socket._write_nbio(data) if result <= 0: return 0 else: self.server.bytes_out.increment(result) return result except SSL.SSLError, why: self.close() self.log_info('send: closing channel %s %s' % (repr(self), why)) return 0 def recv(self, buffer_size): try: result = self.socket._read_nbio(buffer_size) if result is None: return '' elif result == '': self.close() return '' else: self.server.bytes_in.increment(len(result)) return result except SSL.SSLError, why: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), why)) return '' class https_server(http_server.http_server): SERVER_IDENT='M2Crypto HTTPS Server (v%s)' % VERSION_STRING channel_class=https_channel def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): http_server.http_server.__init__(self, ip, port, resolver, logger_object) sys.stdout.write(self.SERVER_IDENT + '\n\n') sys.stdout.flush() self.ssl_ctx=ssl_ctx def handle_accept(self): # Cribbed from http_server. self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. sys.stderr.write ('warning: server accept() threw an exception\n') return # Turn the vanilla socket into an SSL connection. try: ssl_conn=SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr) except SSL.SSLError: pass def writeable(self): return 0 M2Crypto-0.22.6rc4/demo/medusa/index.html0000664000175000017500000000015612605232411020312 0ustar matejmatej00000000000000 M2Crypto HTTPS Server

    M2Crypto HTTPS Server - It works!

    M2Crypto-0.22.6rc4/demo/medusa/logger.py0000664000175000017500000001543012607370517020163 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- import asynchat import socket import string import time # these three are for the rotating logger import os # | import stat # v # # three types of log: # 1) file # with optional flushing. Also, one that rotates the log. # 2) socket # dump output directly to a socket connection. [how do we # keep it open?] # 3) syslog # log to syslog via tcp. this is a per-line protocol. # # # The 'standard' interface to a logging object is simply # log_object.log (message) # # a file-like object that captures output, and # makes sure to flush it always... this could # be connected to: # o stdio file # o low-level file # o socket channel # o syslog output... class file_logger: # pass this either a path or a file object. def __init__ (self, file, flush=1, mode='a'): if type(file) == type(''): if (file == '-'): import sys self.file = sys.stdout else: self.file = open (file, mode) else: self.file = file self.do_flush = flush def __repr__ (self): return '' % self.file def write (self, data): self.file.write (data) self.maybe_flush() def writeline (self, line): self.file.writeline (line) self.maybe_flush() def writelines (self, lines): self.file.writelines (lines) self.maybe_flush() def maybe_flush (self): if self.do_flush: self.file.flush() def flush (self): self.file.flush() def softspace (self, *args): pass def log (self, message): if message[-1] not in ('\r', '\n'): self.write (message + '\n') else: self.write (message) # like a file_logger, but it must be attached to a filename. # When the log gets too full, or a certain time has passed, # it backs up the log and starts a new one. Note that backing # up the log is done via "mv" because anything else (cp, gzip) # would take time, during which medusa would do nothing else. class rotating_file_logger (file_logger): # If freq is non-None we back up "daily", "weekly", or "monthly". # Else if maxsize is non-None we back up whenever the log gets # to big. If both are None we never back up. def __init__ (self, file, freq=None, maxsize=None, flush=1, mode='a'): self.filename = file self.mode = mode self.file = open (file, mode) self.freq = freq self.maxsize = maxsize self.rotate_when = self.next_backup(self.freq) self.do_flush = flush def __repr__ (self): return '' % self.file # We back up at midnight every 1) day, 2) monday, or 3) 1st of month def next_backup (self, freq): (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) if freq == 'daily': return time.mktime(yr,mo,day+1, 0,0,0, 0,0,-1) elif freq == 'weekly': return time.mktime(yr,mo,day-wd+7, 0,0,0, 0,0,-1) # wd(monday)==0 elif freq == 'monthly': return time.mktime(yr,mo+1,1, 0,0,0, 0,0,-1) else: return None # not a date-based backup def maybe_flush (self): # rotate first if necessary self.maybe_rotate() if self.do_flush: # from file_logger() self.file.flush() def maybe_rotate (self): if self.freq and time.time() > self.rotate_when: self.rotate() self.rotate_when = self.next_backup(self.freq) elif self.maxsize: # rotate when we get too big try: if os.stat(self.filename)[stat.ST_SIZE] > self.maxsize: self.rotate() except os.error: # file not found, probably self.rotate() # will create a new file def rotate (self): (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) try: self.file.close() newname = '%s.ends%04d%02d%02d' % (self.filename, yr, mo, day) try: open(newname, "r").close() # check if file exists newname = newname + "-%02d%02d%02d" % (hr, min, sec) except: # YEARMODY is unique pass os.rename(self.filename, newname) self.file = open(self.filename, self.mode) except: pass # syslog is a line-oriented log protocol - this class would be # appropriate for FTP or HTTP logs, but not for dumping stderr to. # TODO: a simple safety wrapper that will ensure that the line sent # to syslog is reasonable. # TODO: async version of syslog_client: now, log entries use blocking # send() import m_syslog syslog_logger = m_syslog.syslog_client class syslog_logger (m_syslog.syslog_client): def __init__ (self, address, facility='user'): m_syslog.syslog_client.__init__ (self, address) self.facility = m_syslog.facility_names[facility] self.address=address def __repr__ (self): return '' % (repr(self.address)) def log (self, message): m_syslog.syslog_client.log ( self, message, facility=self.facility, priority=m_syslog.LOG_INFO ) # log to a stream socket, asynchronously class socket_logger (asynchat.async_chat): def __init__ (self, address): if type(address) == type(''): self.create_socket (socket.AF_UNIX, socket.SOCK_STREAM) else: self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.connect (address) self.address = address def __repr__ (self): return '' % (self.address) def log (self, message): if message[-2:] != '\r\n': self.socket.push (message + '\r\n') else: self.socket.push (message) # log to multiple places class multi_logger: def __init__ (self, loggers): self.loggers = loggers def __repr__ (self): return '' % (repr(self.loggers)) def log (self, message): for logger in self.loggers: logger.log (message) class resolving_logger: """Feed (ip, message) combinations into this logger to get a resolved hostname in front of the message. The message will not be logged until the PTR request finishes (or fails).""" def __init__ (self, resolver, logger): self.resolver = resolver self.logger = logger class logger_thunk: def __init__ (self, message, logger): self.message = message self.logger = logger def __call__ (self, host, ttl, answer): if not answer: answer = host self.logger.log ('%s:%s' % (answer, self.message)) def log (self, ip, message): self.resolver.resolve_ptr ( ip, self.logger_thunk ( message, self.logger ) ) class unresolving_logger: "Just in case you don't want to resolve" def __init__ (self, logger): self.logger = logger def log (self, ip, message): self.logger.log ('%s:%s' % (ip, message)) def strip_eol (line): while line and line[-1] in '\r\n': line = line[:-1] return line class tail_logger: "Keep track of the last log messages" def __init__ (self, logger, size=500): self.size = size self.logger = logger self.messages = [] def log (self, message): self.messages.append (strip_eol (message)) if len (self.messages) > self.size: del self.messages[0] self.logger.log (message) M2Crypto-0.22.6rc4/demo/medusa/m_syslog.py0000664000175000017500000001322112607370517020534 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # ====================================================================== # Copyright 1997 by Sam Rushing # # All Rights Reserved # # 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, and that the name of Sam # Rushing not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL SAM RUSHING 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. # ====================================================================== """socket interface to unix syslog. On Unix, there are usually two ways of getting to syslog: via a local unix-domain socket, or via the TCP service. Usually "/dev/log" is the unix domain socket. This may be different for other systems. >>> my_client = syslog_client ('/dev/log') Otherwise, just use the UDP version, port 514. >>> my_client = syslog_client (('my_log_host', 514)) On win32, you will have to use the UDP version. Note that you can use this to log to other hosts (and indeed, multiple hosts). This module is not a drop-in replacement for the python extension module - the interface is different. Usage: >>> c = syslog_client() >>> c = syslog_client ('/strange/non_standard_log_location') >>> c = syslog_client (('other_host.com', 514)) >>> c.log ('testing', facility='local0', priority='debug') """ # TODO: support named-pipe syslog. # [see ftp://sunsite.unc.edu/pub/Linux/system/Daemons/syslog-fifo.tar.z] # from : # =========================================================================== # priorities/facilities are encoded into a single 32-bit quantity, where the # bottom 3 bits are the priority (0-7) and the top 28 bits are the facility # (0-big number). Both the priorities and the facilities map roughly # one-to-one to strings in the syslogd(8) source code. This mapping is # included in this file. # # priorities (these are ordered) LOG_EMERG = 0 # system is unusable LOG_ALERT = 1 # action must be taken immediately LOG_CRIT = 2 # critical conditions LOG_ERR = 3 # error conditions LOG_WARNING = 4 # warning conditions LOG_NOTICE = 5 # normal but significant condition LOG_INFO = 6 # informational LOG_DEBUG = 7 # debug-level messages # facility codes LOG_KERN = 0 # kernel messages LOG_USER = 1 # random user-level messages LOG_MAIL = 2 # mail system LOG_DAEMON = 3 # system daemons LOG_AUTH = 4 # security/authorization messages LOG_SYSLOG = 5 # messages generated internally by syslogd LOG_LPR = 6 # line printer subsystem LOG_NEWS = 7 # network news subsystem LOG_UUCP = 8 # UUCP subsystem LOG_CRON = 9 # clock daemon LOG_AUTHPRIV = 10 # security/authorization messages (private) # other codes through 15 reserved for system use LOG_LOCAL0 = 16 # reserved for local use LOG_LOCAL1 = 17 # reserved for local use LOG_LOCAL2 = 18 # reserved for local use LOG_LOCAL3 = 19 # reserved for local use LOG_LOCAL4 = 20 # reserved for local use LOG_LOCAL5 = 21 # reserved for local use LOG_LOCAL6 = 22 # reserved for local use LOG_LOCAL7 = 23 # reserved for local use priority_names = { "alert": LOG_ALERT, "crit": LOG_CRIT, "debug": LOG_DEBUG, "emerg": LOG_EMERG, "err": LOG_ERR, "error": LOG_ERR, # DEPRECATED "info": LOG_INFO, "notice": LOG_NOTICE, "panic": LOG_EMERG, # DEPRECATED "warn": LOG_WARNING, # DEPRECATED "warning": LOG_WARNING, } facility_names = { "auth": LOG_AUTH, "authpriv": LOG_AUTHPRIV, "cron": LOG_CRON, "daemon": LOG_DAEMON, "kern": LOG_KERN, "lpr": LOG_LPR, "mail": LOG_MAIL, "news": LOG_NEWS, "security": LOG_AUTH, # DEPRECATED "syslog": LOG_SYSLOG, "user": LOG_USER, "uucp": LOG_UUCP, "local0": LOG_LOCAL0, "local1": LOG_LOCAL1, "local2": LOG_LOCAL2, "local3": LOG_LOCAL3, "local4": LOG_LOCAL4, "local5": LOG_LOCAL5, "local6": LOG_LOCAL6, "local7": LOG_LOCAL7, } import socket class syslog_client: def __init__ (self, address='/dev/log'): self.address = address if type (address) == type(''): self.socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM) self.socket.connect (address) self.unix = 1 else: self.socket = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) self.unix = 0 # curious: when talking to the unix-domain '/dev/log' socket, a # zero-terminator seems to be required. this string is placed # into a class variable so that it can be overridden if # necessary. log_format_string = '<%d>%s\000' def log (self, message, facility=LOG_USER, priority=LOG_INFO): message = self.log_format_string % ( self.encode_priority (facility, priority), message ) if self.unix: self.socket.send (message) else: self.socket.sendto (message, self.address) def encode_priority (self, facility, priority): if type(facility) == type(''): facility = facility_names[facility] if type(priority) == type(''): priority = priority_names[priority] return (facility<<3) | priority def close (self): if self.unix: self.socket.close() M2Crypto-0.22.6rc4/demo/medusa/medusa_gif.py0000664000175000017500000000532412605232411020774 0ustar matejmatej00000000000000# -*- Mode: Python -*- # the medusa icon as a python source file. width = 97 height = 61 data = 'GIF89aa\000=\000\204\000\000\000\000\000\255\255\255\245\245\245ssskkkccc111)))\326\326\326!!!\316\316\316\300\300\300\204\204\000\224\224\224\214\214\214\200\200\200RRR\377\377\377JJJ\367\367\367BBB\347\347\347\000\204\000\020\020\020\265\265\265\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\371\004\001\000\000\021\000,\000\000\000\000a\000=\000\000\005\376`$\216di\236h\252\256l\353\276p,\317tm\337x\256\357|m\001@\240E\305\000\364\2164\206R)$\005\201\214\007r\012{X\255\312a\004\260\\>\026\3240\353)\224n\001W+X\334\373\231~\344.\303b\216\024\027x<\273\307\255G,rJiWN\014{S}k"?ti\013EdPQ\207G@_%\000\026yy\\\201\202\227\224<\221Fs$pOjWz\241\272\002\325\307g\012(\007\205\312#j\317(\012A\200\224.\241\003\346GS\247\033\245\344\264\366\015L\'PXQl]\266\263\243\232\260?\245\316\371\362\225\035\332\243J\273\332Q\263\357-D\241T\327\270\265\013W&\330\010u\371b\322IW0\214\261]\003\033Va\365Z#\207\213a\030k\2647\262\014p\354\024[n\321N\363\346\317\003\037P\000\235C\302\000\3228(\244\363YaA\005\022\255_\237@\260\000A\212\326\256qbp\321\332\266\011\334=T\023\010"!B\005\003A\010\224\020\220 H\002\337#\020 O\276E\357h\221\327\003\\\000b@v\004\351A.h\365\354\342B\002\011\257\025\\ \220\340\301\353\006\000\024\214\200pA\300\353\012\364\241k/\340\033C\202\003\000\310fZ\011\003V\240R\005\007\354\376\026A\000\000\360\'\202\177\024\004\210\003\000\305\215\360\000\000\015\220\240\332\203\027@\'\202\004\025VpA\000%\210x\321\206\032J\341\316\010\262\211H"l\333\341\200\200>"]P\002\212\011\010`\002\0066FP\200\001\'\024p]\004\027(8B\221\306]\000\201w>\002iB\001\007\340\260"v7J1\343(\257\020\251\243\011\242i\263\017\215\337\035\220\200\221\365m4d\015\016D\251\341iN\354\346Ng\253\200I\240\031\35609\245\2057\311I\302\2007t\231"&`\314\310\244\011e\226(\236\010w\212\300\234\011\012HX(\214\253\311@\001\233^\222pg{% \340\035\224&H\000\246\201\362\215`@\001"L\340\004\030\234\022\250\'\015(V:\302\235\030\240q\337\205\224\212h@\177\006\000\250\210\004\007\310\207\337\005\257-P\346\257\367]p\353\203\271\256:\203\236\211F\340\247\010\3329g\244\010\307*=A\000\203\260y\012\304s#\014\007D\207,N\007\304\265\027\021C\233\207%B\366[m\353\006\006\034j\360\306+\357\274a\204\000\000;' M2Crypto-0.22.6rc4/demo/medusa/mime_type_table.py0000664000175000017500000000754512605232411022037 0ustar matejmatej00000000000000# -*- Python -*- # Converted by ./convert_mime_type_table.py from: # /usr/src2/apache_1.2b6/conf/mime.types # content_type_map = \ { 'ai': 'application/postscript', 'aif': 'audio/x-aiff', 'aifc': 'audio/x-aiff', 'aiff': 'audio/x-aiff', 'au': 'audio/basic', 'avi': 'video/x-msvideo', 'bcpio': 'application/x-bcpio', 'bin': 'application/octet-stream', 'cdf': 'application/x-netcdf', 'class': 'application/octet-stream', 'cpio': 'application/x-cpio', 'cpt': 'application/mac-compactpro', 'csh': 'application/x-csh', 'dcr': 'application/x-director', 'dir': 'application/x-director', 'dms': 'application/octet-stream', 'doc': 'application/msword', 'dvi': 'application/x-dvi', 'dxr': 'application/x-director', 'eps': 'application/postscript', 'etx': 'text/x-setext', 'exe': 'application/octet-stream', 'gif': 'image/gif', 'gtar': 'application/x-gtar', 'gz': 'application/x-gzip', 'hdf': 'application/x-hdf', 'hqx': 'application/mac-binhex40', 'htm': 'text/html', 'html': 'text/html', 'ice': 'x-conference/x-cooltalk', 'ief': 'image/ief', 'jpe': 'image/jpeg', 'jpeg': 'image/jpeg', 'jpg': 'image/jpeg', 'kar': 'audio/midi', 'latex': 'application/x-latex', 'lha': 'application/octet-stream', 'lzh': 'application/octet-stream', 'man': 'application/x-troff-man', 'me': 'application/x-troff-me', 'mid': 'audio/midi', 'midi': 'audio/midi', 'mif': 'application/x-mif', 'mov': 'video/quicktime', 'movie': 'video/x-sgi-movie', 'mp2': 'audio/mpeg', 'mpe': 'video/mpeg', 'mpeg': 'video/mpeg', 'mpg': 'video/mpeg', 'mpga': 'audio/mpeg', 'mp3': 'audio/mpeg', 'ms': 'application/x-troff-ms', 'nc': 'application/x-netcdf', 'oda': 'application/oda', 'pbm': 'image/x-portable-bitmap', 'pdb': 'chemical/x-pdb', 'pdf': 'application/pdf', 'pgm': 'image/x-portable-graymap', 'png': 'image/png', 'pnm': 'image/x-portable-anymap', 'ppm': 'image/x-portable-pixmap', 'ppt': 'application/powerpoint', 'ps': 'application/postscript', 'qt': 'video/quicktime', 'ra': 'audio/x-realaudio', 'ram': 'audio/x-pn-realaudio', 'ras': 'image/x-cmu-raster', 'rgb': 'image/x-rgb', 'roff': 'application/x-troff', 'rpm': 'audio/x-pn-realaudio-plugin', 'rtf': 'application/rtf', 'rtx': 'text/richtext', 'sgm': 'text/x-sgml', 'sgml': 'text/x-sgml', 'sh': 'application/x-sh', 'shar': 'application/x-shar', 'sit': 'application/x-stuffit', 'skd': 'application/x-koan', 'skm': 'application/x-koan', 'skp': 'application/x-koan', 'skt': 'application/x-koan', 'snd': 'audio/basic', 'src': 'application/x-wais-source', 'sv4cpio': 'application/x-sv4cpio', 'sv4crc': 'application/x-sv4crc', 't': 'application/x-troff', 'tar': 'application/x-tar', 'tcl': 'application/x-tcl', 'tex': 'application/x-tex', 'texi': 'application/x-texinfo', 'texinfo': 'application/x-texinfo', 'tif': 'image/tiff', 'tiff': 'image/tiff', 'tr': 'application/x-troff', 'tsv': 'text/tab-separated-values', 'txt': 'text/plain', 'ustar': 'application/x-ustar', 'vcd': 'application/x-cdlink', 'vrml': 'x-world/x-vrml', 'wav': 'audio/x-wav', 'wrl': 'x-world/x-vrml', 'xbm': 'image/x-xbitmap', 'xpm': 'image/x-xpixmap', 'xwd': 'image/x-xwindowdump', 'xyz': 'chemical/x-pdb', 'zip': 'application/zip', } M2Crypto-0.22.6rc4/demo/medusa/poison_handler.py0000664000175000017500000000340612607370517021710 0ustar matejmatej00000000000000 import string import whrandom RESP_HEAD="""\ """ RESP_MIDDLE="""

    M2Crypto https server demonstration

    This web page is generated by the "poison" http request handler.
    The links just go on and on and on...

    """ RESP_TAIL=""" """ charset='012345678/90ABCDEFGHIJKLM/NOPQRSTUVWXYZabcd/efghijklmnopqrs/tuvwxyz' numchar=len(charset) def makepage(numlinks): title='' for u in range(whrandom.randint(3, 15)): pick=whrandom.randint(0, numchar-1) title=title+charset[pick] title=title+'' url='\r\n' numlinks=whrandom.randint(2, numlinks) for i in range(numlinks): url=url+'' for u in range(whrandom.randint(3, 15)): pick=whrandom.randint(0, numchar-1) url=url+charset[pick] url=url+'
    \r\n' url=RESP_HEAD+title+RESP_MIDDLE+url+RESP_TAIL return url class poison_handler: """This is a clone of webpoison - every URL returns a page of URLs, each of which returns a page of URLs, each of _which_ returns a page of URLs, ad infinitum. The objective is to sucker address-harvesting bots run by spammers.""" def __init__(self, numlinks=10): self.numlinks = numlinks self.poison_level = 0 def match(self, request): return (request.uri[:7] == '/poison') def handle_request(self, request): if request.command == 'get': request.push(makepage(self.numlinks)) request.done() M2Crypto-0.22.6rc4/demo/medusa/producers.py0000664000175000017500000001722012607370517020711 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- import string """ A collection of producers. Each producer implements a particular feature: They can be combined in various ways to get interesting and useful behaviors. For example, you can feed dynamically-produced output into the compressing producer, then wrap this with the 'chunked' transfer-encoding producer. """ class simple_producer: "producer for a string" def __init__ (self, data, buffer_size=1024): self.data = data self.buffer_size = buffer_size def more (self): if len (self.data) > self.buffer_size: result = self.data[:self.buffer_size] self.data = self.data[self.buffer_size:] return result else: result = self.data self.data = '' return result class scanning_producer: "like simple_producer, but more efficient for large strings" def __init__ (self, data, buffer_size=1024): self.data = data self.buffer_size = buffer_size self.pos = 0 def more (self): if self.pos < len(self.data): lp = self.pos rp = min ( len(self.data), self.pos + self.buffer_size ) result = self.data[lp:rp] self.pos = self.pos + len(result) return result else: return '' class lines_producer: "producer for a list of lines" def __init__ (self, lines): self.lines = lines def ready (self): return len(self.lines) def more (self): if self.lines: chunk = self.lines[:50] self.lines = self.lines[50:] return string.join (chunk, '\r\n') + '\r\n' else: return '' class buffer_list_producer: "producer for a list of buffers" # i.e., data == string.join (buffers, '') def __init__ (self, buffers): self.index = 0 self.buffers = buffers def more (self): if self.index >= len(self.buffers): return '' else: data = self.buffers[self.index] self.index = self.index + 1 return data class file_producer: "producer wrapper for file[-like] objects" # match http_channel's outgoing buffer size out_buffer_size = 1<<16 def __init__ (self, file): self.done = 0 self.file = file def more (self): if self.done: return '' else: data = self.file.read (self.out_buffer_size) if not data: self.file.close() del self.file self.done = 1 return '' else: return data # A simple output producer. This one does not [yet] have # the safety feature builtin to the monitor channel: runaway # output will not be caught. # don't try to print from within any of the methods # of this object. class output_producer: "Acts like an output file; suitable for capturing sys.stdout" def __init__ (self): self.data = '' def write (self, data): lines = string.splitfields (data, '\n') data = string.join (lines, '\r\n') self.data = self.data + data def writeline (self, line): self.data = self.data + line + '\r\n' def writelines (self, lines): self.data = self.data + string.joinfields ( lines, '\r\n' ) + '\r\n' def ready (self): return (len (self.data) > 0) def flush (self): pass def softspace (self, *args): pass def more (self): if self.data: result = self.data[:512] self.data = self.data[512:] return result else: return '' class composite_producer: "combine a fifo of producers into one" def __init__ (self, producers): self.producers = producers def more (self): while len(self.producers): p = self.producers.first() d = p.more() if d: return d else: self.producers.pop() else: return '' class globbing_producer: """ 'glob' the output from a producer into a particular buffer size. helps reduce the number of calls to send(). [this appears to gain about 30% performance on requests to a single channel] """ def __init__ (self, producer, buffer_size=1<<16): self.producer = producer self.buffer = '' self.buffer_size = buffer_size def more (self): while len(self.buffer) < self.buffer_size: data = self.producer.more() if data: self.buffer = self.buffer + data else: break r = self.buffer self.buffer = '' return r class hooked_producer: """ A producer that will call when it empties,. with an argument of the number of bytes produced. Useful for logging/instrumentation purposes. """ def __init__ (self, producer, function): self.producer = producer self.function = function self.bytes = 0 def more (self): if self.producer: result = self.producer.more() if not result: self.producer = None self.function (self.bytes) else: self.bytes = self.bytes + len(result) return result else: return '' # HTTP 1.1 emphasizes that an advertised Content-Length header MUST be # correct. In the face of Strange Files, it is conceivable that # reading a 'file' may produce an amount of data not matching that # reported by os.stat() [text/binary mode issues, perhaps the file is # being appended to, etc..] This makes the chunked encoding a True # Blessing, and it really ought to be used even with normal files. # How beautifully it blends with the concept of the producer. class chunked_producer: """A producer that implements the 'chunked' transfer coding for HTTP/1.1. Here is a sample usage: request['Transfer-Encoding'] = 'chunked' request.push ( producers.chunked_producer (your_producer) ) request.done() """ def __init__ (self, producer, footers=None): self.producer = producer self.footers = footers def more (self): if self.producer: data = self.producer.more() if data: return '%x\r\n%s\r\n' % (len(data), data) else: self.producer = None if self.footers: return string.join ( ['0'] + self.footers, '\r\n' ) + '\r\n\r\n' else: return '0\r\n\r\n' else: return '' # Unfortunately this isn't very useful right now (Aug 97), because # apparently the browsers don't do on-the-fly decompression. Which # is sad, because this could _really_ speed things up, especially for # low-bandwidth clients (i.e., most everyone). try: import zlib except ImportError: zlib = None class compressed_producer: """ Compress another producer on-the-fly, using ZLIB [Unfortunately, none of the current browsers seem to support this] """ # Note: It's not very efficient to have the server repeatedly # compressing your outgoing files: compress them ahead of time, or # use a compress-once-and-store scheme. However, if you have low # bandwidth and low traffic, this may make more sense than # maintaining your source files compressed. # # Can also be used for compressing dynamically-produced output. def __init__ (self, producer, level=5): self.producer = producer self.compressor = zlib.compressobj (level) def more (self): if self.producer: cdata = '' # feed until we get some output while not cdata: data = self.producer.more() if not data: self.producer = None return self.compressor.flush() else: cdata = self.compressor.compress (data) return cdata else: return '' class escaping_producer: "A producer that escapes a sequence of characters" " Common usage: escaping the CRLF.CRLF sequence in SMTP, NNTP, etc..." def __init__ (self, producer, esc_from='\r\n.', esc_to='\r\n..'): self.producer = producer self.esc_from = esc_from self.esc_to = esc_to self.buffer = '' from asynchat import find_prefix_at_end self.find_prefix_at_end = find_prefix_at_end def more (self): esc_from = self.esc_from esc_to = self.esc_to buffer = self.buffer + self.producer.more() if buffer: buffer = string.replace (buffer, esc_from, esc_to) i = self.find_prefix_at_end (buffer, esc_from) if i: # we found a prefix self.buffer = buffer[-i:] return buffer[:-i] else: # no prefix, return it all self.buffer = '' return buffer else: return buffer M2Crypto-0.22.6rc4/demo/medusa/put_handler.py0000664000175000017500000000506212607370517021211 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # import re import string import default_handler unquote = default_handler.unquote get_header = default_handler.get_header last_request = None class put_handler: def __init__ (self, filesystem, uri_regex): self.filesystem = filesystem if type (uri_regex) == type(''): self.uri_regex = re.compile (uri_regex) else: self.uri_regex = uri_regex def match (self, request): uri = request.uri if request.command == 'put': m = self.uri_regex.match (uri) if m and m.end() == len(uri): return 1 return 0 def handle_request (self, request): path, params, query, fragment = request.split_uri() # strip off leading slashes while path and path[0] == '/': path = path[1:] if '%' in path: path = unquote (path) # make sure there's a content-length header cl = get_header (CONTENT_LENGTH, request.header) if not cl: request.error (411) return else: cl = string.atoi (cl) # don't let the try to overwrite a directory if self.filesystem.isdir (path): request.error (405) return is_update = self.filesystem.isfile (path) try: output_file = self.filesystem.open (path, 'wb') except: request.error (405) return request.collector = put_collector (output_file, cl, request, is_update) # no terminator while receiving PUT data request.channel.set_terminator (None) # don't respond yet, wait until we've received the data... class put_collector: def __init__ (self, file, length, request, is_update): self.file = file self.length = length self.request = request self.is_update = is_update self.bytes_in = 0 def collect_incoming_data (self, data): ld = len(data) bi = self.bytes_in if (bi + ld) >= self.length: # last bit of data chunk = self.length - bi self.file.write (data[:chunk]) self.file.close() if chunk != ld: print 'orphaned %d bytes: <%s>' % (ld - chunk, repr(data[chunk:])) # do some housekeeping r = self.request ch = r.channel ch.current_request = None # set the terminator back to the default ch.set_terminator ('\r\n\r\n') if self.is_update: r.reply_code = 204 # No content r.done() else: r.reply_now (201) # Created # avoid circular reference del self.request else: self.file.write (data) self.bytes_in = self.bytes_in + ld def found_terminator (self): # shouldn't be called pass CONTENT_LENGTH = re.compile ('Content-Length: ([0-9]+)', re.IGNORECASE) M2Crypto-0.22.6rc4/demo/medusa/redirecting_handler.py0000664000175000017500000000205212607370517022674 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # import re import counter class redirecting_handler: def __init__ (self, pattern, redirect, regex_flag=re.IGNORECASE): self.pattern = pattern self.redirect = redirect self.patreg = re.compile (pattern, regex_flag) self.hits = counter.counter() def match (self, request): m = self.patref.match (request.uri) return (m and (m.end() == len(request.uri))) def handle_request (self, request): self.hits.increment() m = self.patreg.match (request.uri) part = m.group(1) request['Location'] = self.redirect % part request.error (302) # moved temporarily def __repr__ (self): return ' %s]>' % ( id(self), repr(self.pattern), repr(self.redirect) ) def status (self): import producers return producers.simple_producer ( '
  • Redirecting Handler %s => %s Hits: %s' % ( self.pattern, self.redirect, self.hits ) ) M2Crypto-0.22.6rc4/demo/medusa/server.pem0000664000175000017500000000411012605232411020320 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/medusa/status_handler.py0000664000175000017500000001654412607370517021733 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- VERSION_STRING = "$Id$" # # medusa status extension # import string import time import re import asyncore import http_server import medusa_gif import producers from counter import counter START_TIME = long(time.time()) class status_extension: hit_counter = counter() def __init__ (self, objects, statusdir='/status', allow_emergency_debug=0): self.objects = objects self.statusdir = statusdir self.allow_emergency_debug = allow_emergency_debug # We use /status instead of statusdir here because it's too # hard to pass statusdir to the logger, who makes the HREF # to the object dir. We don't need the security-through- # obscurity here in any case, because the id is obscurity enough self.hyper_regex = re.compile('/status/object/([0-9]+)/.*') self.hyper_objects = [] for object in objects: self.register_hyper_object (object) def __repr__ (self): return '' % ( self.hit_counter, id(self) ) def match (self, request): path, params, query, fragment = request.split_uri() # For reasons explained above, we don't use statusdir for /object return (path[:len(self.statusdir)] == self.statusdir or path[:len("/status/object/")] == '/status/object/') # Possible Targets: # /status # /status/channel_list # /status/medusa.gif # can we have 'clickable' objects? # [yes, we can use id(x) and do a linear search] # Dynamic producers: # HTTP/1.0: we must close the channel, because it's dynamic output # HTTP/1.1: we can use the chunked transfer-encoding, and leave # it open. def handle_request (self, request): [path, params, query, fragment] = request.split_uri() self.hit_counter.increment() if path == self.statusdir: # and not a subdirectory up_time = string.join (english_time (long(time.time()) - START_TIME)) request['Content-Type'] = 'text/html' request.push ( '' 'Medusa Status Reports' '' '

    Medusa Status Reports

    ' 'Up: %s' % up_time ) for i in range(len(self.objects)): request.push (self.objects[i].status()) request.push ('
    \r\n') request.push ( '

    Channel List' '


    ' '' '' % ( self.statusdir, self.statusdir, medusa_gif.width, medusa_gif.height ) ) request.done() elif path == self.statusdir + '/channel_list': request['Content-Type'] = 'text/html' request.push ('') request.push(channel_list_producer(self.statusdir)) request.push ( '
    ' '' % ( self.statusdir, medusa_gif.width, medusa_gif.height ) + '' ) request.done() elif path == self.statusdir + '/medusa.gif': request['Content-Type'] = 'image/gif' request['Content-Length'] = len(medusa_gif.data) request.push (medusa_gif.data) request.done() elif path == self.statusdir + '/close_zombies': message = ( '

    Closing all zombie http client connections...

    ' '

    Back to the status page' % self.statusdir ) request['Content-Type'] = 'text/html' request['Content-Length'] = len (message) request.push (message) now = int (time.time()) for channel in asyncore.socket_map.keys(): if channel.__class__ == http_server.http_channel: if channel != request.channel: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() request.done() # Emergency Debug Mode # If a server is running away from you, don't KILL it! # Move all the AF_INET server ports and perform an autopsy... # [disabled by default to protect the innocent] elif self.allow_emergency_debug and path == self.statusdir + '/emergency_debug': request.push ('Moving All Servers...') request.done() for channel in asyncore.socket_map.keys(): if channel.accepting: if type(channel.addr) is type(()): ip, port = channel.addr channel.socket.close() channel.del_channel() channel.addr = (ip, port+10000) fam, typ = channel.family_and_type channel.create_socket (fam, typ) channel.set_reuse_addr() channel.bind (channel.addr) channel.listen(5) else: m = self.hyper_regex.match (path) if m: oid = string.atoi (m.group (1)) for object in self.hyper_objects: if id (object) == oid: if hasattr (object, 'hyper_respond'): object.hyper_respond (self, path, request) else: request.error (404) return def status (self): return producers.simple_producer ( '

  • Status Extension Hits : %s' % self.hit_counter ) def register_hyper_object (self, object): if not object in self.hyper_objects: self.hyper_objects.append (object) import logger class logger_for_status (logger.tail_logger): def status (self): return 'Last %d log entries for: %s' % ( len (self.messages), html_repr (self) ) def hyper_respond (self, sh, path, request): request['Content-Type'] = 'text/plain' messages = self.messages[:] messages.reverse() request.push (lines_producer (messages)) request.done() class lines_producer: def __init__ (self, lines): self.lines = lines def ready (self): return len(self.lines) def more (self): if self.lines: chunk = self.lines[:50] self.lines = self.lines[50:] return string.join (chunk, '\r\n') + '\r\n' else: return '' class channel_list_producer (lines_producer): def __init__ (self, statusdir): channel_reprs = map ( lambda x: '<' + repr(x)[1:-1] + '>', asyncore.socket_map.values() ) channel_reprs.sort() lines_producer.__init__ ( self, ['

    Active Channel List

    ', '
    '
    			 ] + channel_reprs + [
    				 '
    ', '

    Status Report' % statusdir ] ) # this really needs a full-blown quoter... def sanitize (s): if '<' in s: s = string.join (string.split (s, '<'), '<') if '>' in s: s = string.join (string.split (s, '>'), '>') return s def html_repr (object): so = sanitize (repr (object)) if hasattr (object, 'hyper_respond'): return '%s' % (id (object), so) else: return so def html_reprs (list, front='', back=''): reprs = map ( lambda x,f=front,b=back: '%s%s%s' % (f,x,b), map (lambda x: sanitize (html_repr(x)), list) ) reprs.sort() return reprs # for example, tera, giga, mega, kilo # p_d (n, (1024, 1024, 1024, 1024)) # smallest divider goes first - for example # minutes, hours, days # p_d (n, (60, 60, 24)) def progressive_divide (n, parts): result = [] for part in parts: n, rem = divmod (n, part) result.append (rem) result.append (n) return result # b,k,m,g,t def split_by_units (n, units, dividers, format_string): divs = progressive_divide (n, dividers) result = [] for i in range(len(units)): if divs[i]: result.append (format_string % (divs[i], units[i])) result.reverse() if not result: return [format_string % (0, units[0])] else: return result def english_bytes (n): return split_by_units ( n, ('','K','M','G','T'), (1024, 1024, 1024, 1024, 1024), '%d %sB' ) def english_time (n): return split_by_units ( n, ('secs', 'mins', 'hours', 'days', 'weeks', 'years'), ( 60, 60, 24, 7, 52), '%d %s' ) M2Crypto-0.22.6rc4/demo/medusa/virtual_handler.py0000664000175000017500000000302312607370517022062 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- import socket import default_handler import re HOST = re.compile ('Host: ([^:/]+).*', re.IGNORECASE) get_header = default_handler.get_header class virtual_handler: """HTTP request handler for an HTTP/1.0-style virtual host. Each Virtual host must have a different IP""" def __init__ (self, handler, hostname): self.handler = handler self.hostname = hostname try: self.ip = socket.gethostbyname (hostname) except socket.error: raise ValueError, "Virtual Hostname %s does not appear to be registered in the DNS" % hostname def match (self, request): if (request.channel.addr[0] == self.ip): return 1 else: return 0 def handle_request (self, request): return self.handler.handle_request (request) def __repr__ (self): return '' % self.hostname class virtual_handler_with_host: """HTTP request handler for HTTP/1.1-style virtual hosts. This matches by checking the value of the 'Host' header in the request. You actually don't _have_ to support HTTP/1.1 to use this, since many browsers now send the 'Host' header. This is a Good Thing.""" def __init__ (self, handler, hostname): self.handler = handler self.hostname = hostname def match (self, request): host = get_header (HOST, request.header) if host == self.hostname: return 1 else: return 0 def handle_request (self, request): return self.handler.handle_request (request) def __repr__ (self): return '' % self.hostname M2Crypto-0.22.6rc4/demo/medusa/xmlrpc_handler.py0000664000175000017500000000462412607370517021711 0ustar matejmatej00000000000000# -*- Mode: Python; tab-width: 4 -*- # See http://www.xml-rpc.com/ # http://www.pythonware.com/products/xmlrpc/ # Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com) VERSION = "$Id$" import http_server import xmlrpclib import string import sys class xmlrpc_handler: def match (self, request): # Note: /RPC2 is not required by the spec, so you may override this method. if request.uri[:5] == '/RPC2': return 1 else: return 0 def handle_request (self, request): [path, params, query, fragment] = request.split_uri() if request.command in ('post', 'put'): request.collector = collector (self, request) else: request.error (400) def continue_request (self, data, request): params, method = xmlrpclib.loads (data) try: # generate response try: response = self.call (method, params) if type(response) != type(()): response = (response,) except: # report exception back to server response = xmlrpclib.dumps ( xmlrpclib.Fault (1, "%s:%s" % (sys.exc_type, sys.exc_value)) ) else: response = xmlrpclib.dumps (response, methodresponse=1) except: # internal error, report as HTTP server error request.error (500) else: # got a valid XML RPC response request['Content-Type'] = 'text/xml' request.push (response) request.done() def call (self, method, params): # override this method to implement RPC methods raise "NotYetImplemented" class collector: "gathers input for POST and PUT requests" def __init__ (self, handler, request): self.handler = handler self.request = request self.data = '' # make sure there's a content-length header cl = request.get_header ('content-length') if not cl: request.error (411) else: cl = string.atoi (cl) # using a 'numeric' terminator self.request.channel.set_terminator (cl) def collect_incoming_data (self, data): self.data = self.data + data def found_terminator (self): # set the terminator back to the default self.request.channel.set_terminator ('\r\n\r\n') self.handler.continue_request (self.data, self.request) if __name__ == '__main__': class rpc_demo (xmlrpc_handler): def call (self, method, params): print 'method="%s" params=%s' % (method, params) return "Sure, that works" import asyncore import http_server hs = http_server.http_server ('', 8000) rpc = rpc_demo() hs.install_handler (rpc) asyncore.loop() M2Crypto-0.22.6rc4/demo/medusa054/0000775000175000017500000000000012613362233016551 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/medusa054/00_README0000664000175000017500000000143612605232411017727 0ustar matejmatej00000000000000 21 Mar 2004 ------------- M2Crypto HTTPS and FTP/TLS servers All the files in this directory are from Medusa 0.54, except for the following: - 00_README (this file) - server.pem, the server's certificate - ca.pem, my CA certificate - https_server.py - ftps_server.py - START.py - START_xmlrpc.py - index.html, a sample HTML file - poison_handler.py, a webpoison clone By default, http_server listens on port 39080 and https_server port 39443. Document root is current directory, and serves up index.html. The xmlrpc server is accessible below '/RPC2'. The FTP/TLS server listens on port 39021 by default. I've only tested it with the 'anonymous' authentication handler. Medusa files are copyright Sam Rushing. Recent versions are maintained by Andrew Kuchling. My files are copyright me. M2Crypto-0.22.6rc4/demo/medusa054/START.py0000664000175000017500000000347112607370517020034 0ustar matejmatej00000000000000#!/usr/bin/env python # Standard Python library import os import os.path import sys # Medusa import asyncore import default_handler import filesys import ftp_server import http_server import status_handler # M2Crypto import https_server import poison_handler import ftps_server from M2Crypto import Rand, SSL, threading HTTP_PORT=39080 HTTPS_PORT=39443 FTP_PORT = 39021 hs=http_server.http_server('', HTTP_PORT) Rand.load_file('../randpool.dat', -1) ssl_ctx=SSL.Context('sslv23') ssl_ctx.load_cert('server.pem') ssl_ctx.load_verify_locations('ca.pem', '') ssl_ctx.load_client_CA('ca.pem') #ssl_ctx.set_verify(SSL.verify_peer, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_client_once, 10) ssl_ctx.set_verify(SSL.verify_none, 10) ssl_ctx.set_session_id_ctx('127.0.0.1:39443') ssl_ctx.set_tmp_dh('dh1024.pem') ssl_ctx.set_info_callback() hss=https_server.https_server('', HTTPS_PORT, ssl_ctx) fs=filesys.os_filesystem(os.path.abspath(os.curdir)) #fs=filesys.os_filesystem('/usr/local/pkg/apache/htdocs') #fs=filesys.os_filesystem('c:/pkg/jdk130/docs') dh=default_handler.default_handler(fs) hs.install_handler(dh) hss.install_handler(dh) #class rpc_demo (xmlrpc_handler.xmlrpc_handler): # def call (self, method, params): # print 'method="%s" params=%s' % (method, params) # return "Sure, that works" #rpch = rpc_demo() #hs.install_handler(rpch) #hss.install_handler(rpch) ph=poison_handler.poison_handler(10) hs.install_handler(ph) hss.install_handler(ph) fauthz = ftp_server.anon_authorizer('/usr/local/pkg/apache/htdocs') ftps = ftps_server.ftp_tls_server(fauthz, ssl_ctx, port=FTP_PORT) sh=status_handler.status_extension([hs, hss, ftps]) hs.install_handler(sh) hss.install_handler(sh) asyncore.loop() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/medusa054/START_xmlrpc.py0000664000175000017500000000332712607370517021421 0ustar matejmatej00000000000000#!/usr/bin/env python # Standard Python library import os import os.path import sys # Medusa import asyncore import default_handler import filesys import http_server import status_handler # M2Crypto import https_server import poison_handler from M2Crypto import Rand, SSL # XMLrpc import xmlrpc_handler HTTP_PORT=39080 HTTPS_PORT=39443 hs=http_server.http_server('', HTTP_PORT) Rand.load_file('../randpool.dat', -1) ssl_ctx=SSL.Context('sslv23') ssl_ctx.load_cert('server.pem') #ssl_ctx.load_verify_location('ca.pem') #ssl_ctx.load_client_CA('ca.pem') #ssl_ctx.set_verify(SSL.verify_peer, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 10) #ssl_ctx.set_verify(SSL.verify_peer|SSL.verify_client_once, 10) ssl_ctx.set_verify(SSL.verify_none, 10) ssl_ctx.set_session_id_ctx('127.0.0.1:9443') ssl_ctx.set_tmp_dh('dh1024.pem') #ssl_ctx.set_info_callback() hss=https_server.https_server('', HTTPS_PORT, ssl_ctx) fs=filesys.os_filesystem(os.path.abspath(os.curdir)) #fs=filesys.os_filesystem('/usr/local/pkg/apache/htdocs') #fs=filesys.os_filesystem('c:/pkg/jdk118/docs') dh=default_handler.default_handler(fs) hs.install_handler(dh) hss.install_handler(dh) # Cribbed from xmlrpc_handler.py. # This is where you implement your RPC functionality. class rpc_demo (xmlrpc_handler.xmlrpc_handler): def call (self, method, params): print 'method="%s" params=%s' % (method, params) return "Sure, that works" rpch = rpc_demo() hs.install_handler(rpch) hss.install_handler(rpch) ph=poison_handler.poison_handler(10) hs.install_handler(ph) hss.install_handler(ph) sh=status_handler.status_extension([hss]) hs.install_handler(sh) hss.install_handler(sh) asyncore.loop() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/medusa054/ca.pem0000664000175000017500000000230412605232411017631 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/medusa054/counter.py0000664000175000017500000000264012605232411020577 0ustar matejmatej00000000000000# -*- Mode: Python -*- # It is tempting to add an __int__ method to this class, but it's not # a good idea. This class tries to gracefully handle integer # overflow, and to hide this detail from both the programmer and the # user. Note that the __str__ method can be relied on for printing out # the value of a counter: # # >>> print 'Total Client: %s' % self.total_clients # # If you need to do arithmetic with the value, then use the 'as_long' # method, the use of long arithmetic is a reminder that the counter # will overflow. class counter: "general-purpose counter" def __init__ (self, initial_value=0): self.value = initial_value def increment (self, delta=1): result = self.value try: self.value = self.value + delta except OverflowError: self.value = long(self.value) + delta return result def decrement (self, delta=1): result = self.value try: self.value = self.value - delta except OverflowError: self.value = long(self.value) - delta return result def as_long (self): return long(self.value) def __nonzero__ (self): return self.value != 0 def __repr__ (self): return '' % (self.value, id(self)) def __str__ (self): s = str(long(self.value)) if s[-1:] == 'L': s = s[:-1] return s M2Crypto-0.22.6rc4/demo/medusa054/default_handler.py0000664000175000017500000001415412605232411022244 0ustar matejmatej00000000000000# -*- Mode: Python -*- # # Author: Sam Rushing # Copyright 1997 by Sam Rushing # All Rights Reserved. # # standard python modules import mimetypes import re import stat import string # medusa modules import http_date import http_server import status_handler import producers unquote = http_server.unquote # This is the 'default' handler. it implements the base set of # features expected of a simple file-delivering HTTP server. file # services are provided through a 'filesystem' object, the very same # one used by the FTP server. # # You can replace or modify this handler if you want a non-standard # HTTP server. You can also derive your own handler classes from # it. # # support for handling POST requests is available in the derived # class , defined below. # from counter import counter class default_handler: valid_commands = ['GET', 'HEAD'] IDENT = 'Default HTTP Request Handler' # Pathnames that are tried when a URI resolves to a directory name directory_defaults = [ 'index.html', 'default.html' ] default_file_producer = producers.file_producer def __init__ (self, filesystem): self.filesystem = filesystem # count total hits self.hit_counter = counter() # count file deliveries self.file_counter = counter() # count cache hits self.cache_counter = counter() hit_counter = 0 def __repr__ (self): return '<%s (%s hits) at %x>' % ( self.IDENT, self.hit_counter, id (self) ) # always match, since this is a default def match (self, request): return 1 # handle a file request, with caching. def handle_request (self, request): if request.command not in self.valid_commands: request.error (400) # bad request return self.hit_counter.increment() path, params, query, fragment = request.split_uri() if '%' in path: path = unquote (path) # strip off all leading slashes while path and path[0] == '/': path = path[1:] if self.filesystem.isdir (path): if path and path[-1] != '/': request['Location'] = 'http://%s/%s/' % ( request.channel.server.server_name, path ) request.error (301) return # we could also generate a directory listing here, # may want to move this into another method for that # purpose found = 0 if path and path[-1] != '/': path = path + '/' for default in self.directory_defaults: p = path + default if self.filesystem.isfile (p): path = p found = 1 break if not found: request.error (404) # Not Found return elif not self.filesystem.isfile (path): request.error (404) # Not Found return file_length = self.filesystem.stat (path)[stat.ST_SIZE] ims = get_header_match (IF_MODIFIED_SINCE, request.header) length_match = 1 if ims: length = ims.group (4) if length: try: length = string.atoi (length) if length != file_length: length_match = 0 except: pass ims_date = 0 if ims: ims_date = http_date.parse_http_date (ims.group (1)) try: mtime = self.filesystem.stat (path)[stat.ST_MTIME] except: request.error (404) return if length_match and ims_date: if mtime <= ims_date: request.reply_code = 304 request.done() self.cache_counter.increment() return try: file = self.filesystem.open (path, 'rb') except IOError: request.error (404) return request['Last-Modified'] = http_date.build_http_date (mtime) request['Content-Length'] = file_length self.set_content_type (path, request) if request.command == 'GET': request.push (self.default_file_producer (file)) self.file_counter.increment() request.done() def set_content_type (self, path, request): ext = string.lower (get_extension (path)) typ, encoding = mimetypes.guess_type(path) if typ is not None: request['Content-Type'] = typ else: # TODO: test a chunk off the front of the file for 8-bit # characters, and use application/octet-stream instead. request['Content-Type'] = 'text/plain' def status (self): return producers.simple_producer ( '

  • %s' % status_handler.html_repr (self) + '
      ' + '
    • Total Hits: %s' % self.hit_counter + '
    • Files Delivered: %s' % self.file_counter + '
    • Cache Hits: %s' % self.cache_counter + '
    ' ) # HTTP/1.0 doesn't say anything about the "; length=nnnn" addition # to this header. I suppose its purpose is to avoid the overhead # of parsing dates... IF_MODIFIED_SINCE = re.compile ( 'If-Modified-Since: ([^;]+)((; length=([0-9]+)$)|$)', re.IGNORECASE ) USER_AGENT = re.compile ('User-Agent: (.*)', re.IGNORECASE) CONTENT_TYPE = re.compile ( r'Content-Type: ([^;]+)((; boundary=([A-Za-z0-9\'\(\)+_,./:=?-]+)$)|$)', re.IGNORECASE ) get_header = http_server.get_header get_header_match = http_server.get_header_match def get_extension (path): dirsep = string.rfind (path, '/') dotsep = string.rfind (path, '.') if dotsep > dirsep: return path[dotsep+1:] else: return '' M2Crypto-0.22.6rc4/demo/medusa054/dh1024.pem0000664000175000017500000000036512605232411020155 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq /Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx /mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/demo/medusa054/filesys.py0000664000175000017500000002562012605232411020601 0ustar matejmatej00000000000000# -*- Mode: Python -*- # $Id$ # Author: Sam Rushing # # Generic filesystem interface. # # We want to provide a complete wrapper around any and all # filesystem operations. # this class is really just for documentation, # identifying the API for a filesystem object. # opening files for reading, and listing directories, should # return a producer. class abstract_filesystem: def __init__ (self): pass def current_directory (self): "Return a string representing the current directory." pass def listdir (self, path, long=0): """Return a listing of the directory at 'path' The empty string indicates the current directory. If 'long' is set, instead return a list of (name, stat_info) tuples """ pass def open (self, path, mode): "Return an open file object" pass def stat (self, path): "Return the equivalent of os.stat() on the given path." pass def isdir (self, path): "Does the path represent a directory?" pass def isfile (self, path): "Does the path represent a plain file?" pass def cwd (self, path): "Change the working directory." pass def cdup (self): "Change to the parent of the current directory." pass def longify (self, path): """Return a 'long' representation of the filename [for the output of the LIST command]""" pass # standard wrapper around a unix-like filesystem, with a 'false root' # capability. # security considerations: can symbolic links be used to 'escape' the # root? should we allow it? if not, then we could scan the # filesystem on startup, but that would not help if they were added # later. We will probably need to check for symlinks in the cwd method. # what to do if wd is an invalid directory? import os import stat import re import string def safe_stat (path): try: return (path, os.stat (path)) except: return None import glob class os_filesystem: path_module = os.path # set this to zero if you want to disable pathname globbing. # [we currently don't glob, anyway] do_globbing = 1 def __init__ (self, root, wd='/'): self.root = root self.wd = wd def current_directory (self): return self.wd def isfile (self, path): p = self.normalize (self.path_module.join (self.wd, path)) return self.path_module.isfile (self.translate(p)) def isdir (self, path): p = self.normalize (self.path_module.join (self.wd, path)) return self.path_module.isdir (self.translate(p)) def cwd (self, path): p = self.normalize (self.path_module.join (self.wd, path)) translated_path = self.translate(p) if not self.path_module.isdir (translated_path): return 0 else: old_dir = os.getcwd() # temporarily change to that directory, in order # to see if we have permission to do so. try: can = 0 try: os.chdir (translated_path) can = 1 self.wd = p except: pass finally: if can: os.chdir (old_dir) return can def cdup (self): return self.cwd ('..') def listdir (self, path, long=0): p = self.translate (path) # I think we should glob, but limit it to the current # directory only. ld = os.listdir (p) if not long: return list_producer (ld, None) else: old_dir = os.getcwd() try: os.chdir (p) # if os.stat fails we ignore that file. result = filter (None, map (safe_stat, ld)) finally: os.chdir (old_dir) return list_producer (result, self.longify) # TODO: implement a cache w/timeout for stat() def stat (self, path): p = self.translate (path) return os.stat (p) def open (self, path, mode): p = self.translate (path) return open (p, mode) def unlink (self, path): p = self.translate (path) return os.unlink (p) def mkdir (self, path): p = self.translate (path) return os.mkdir (p) def rmdir (self, path): p = self.translate (path) return os.rmdir (p) # utility methods def normalize (self, path): # watch for the ever-sneaky '/+' path element path = re.sub('/+', '/', path) p = self.path_module.normpath (path) # remove 'dangling' cdup's. if len(p) > 2 and p[:3] == '/..': p = '/' return p def translate (self, path): # we need to join together three separate # path components, and do it safely. # // # use the operating system's path separator. path = string.join (string.split (path, '/'), os.sep) p = self.normalize (self.path_module.join (self.wd, path)) p = self.normalize (self.path_module.join (self.root, p[1:])) return p def longify (self, (path, stat_info)): return unix_longify (path, stat_info) def __repr__ (self): return '' % ( self.root, self.wd ) if os.name == 'posix': class unix_filesystem (os_filesystem): pass class schizophrenic_unix_filesystem (os_filesystem): PROCESS_UID = os.getuid() PROCESS_EUID = os.geteuid() PROCESS_GID = os.getgid() PROCESS_EGID = os.getegid() def __init__ (self, root, wd='/', persona=(None, None)): os_filesystem.__init__ (self, root, wd) self.persona = persona def become_persona (self): if self.persona is not (None, None): uid, gid = self.persona # the order of these is important! os.setegid (gid) os.seteuid (uid) def become_nobody (self): if self.persona is not (None, None): os.seteuid (self.PROCESS_UID) os.setegid (self.PROCESS_GID) # cwd, cdup, open, listdir def cwd (self, path): try: self.become_persona() return os_filesystem.cwd (self, path) finally: self.become_nobody() def cdup (self, path): try: self.become_persona() return os_filesystem.cdup (self) finally: self.become_nobody() def open (self, filename, mode): try: self.become_persona() return os_filesystem.open (self, filename, mode) finally: self.become_nobody() def listdir (self, path, long=0): try: self.become_persona() return os_filesystem.listdir (self, path, long) finally: self.become_nobody() # For the 'real' root, we could obtain a list of drives, and then # use that. Doesn't win32 provide such a 'real' filesystem? # [yes, I think something like this "\\.\c\windows"] class msdos_filesystem (os_filesystem): def longify (self, (path, stat_info)): return msdos_longify (path, stat_info) # A merged filesystem will let you plug other filesystems together. # We really need the equivalent of a 'mount' capability - this seems # to be the most general idea. So you'd use a 'mount' method to place # another filesystem somewhere in the hierarchy. # Note: this is most likely how I will handle ~user directories # with the http server. class merged_filesystem: def __init__ (self, *fsys): pass # this matches the output of NT's ftp server (when in # MSDOS mode) exactly. def msdos_longify (file, stat_info): if stat.S_ISDIR (stat_info[stat.ST_MODE]): dir = '' else: dir = ' ' date = msdos_date (stat_info[stat.ST_MTIME]) return '%s %s %8d %s' % ( date, dir, stat_info[stat.ST_SIZE], file ) def msdos_date (t): try: info = time.gmtime (t) except: info = time.gmtime (0) # year, month, day, hour, minute, second, ... if info[3] > 11: merid = 'PM' info[3] = info[3] - 12 else: merid = 'AM' return '%02d-%02d-%02d %02d:%02d%s' % ( info[1], info[2], info[0]%100, info[3], info[4], merid ) months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] mode_table = { '0':'---', '1':'--x', '2':'-w-', '3':'-wx', '4':'r--', '5':'r-x', '6':'rw-', '7':'rwx' } import time def unix_longify (file, stat_info): # for now, only pay attention to the lower bits mode = ('%o' % stat_info[stat.ST_MODE])[-3:] mode = string.join (map (lambda x: mode_table[x], mode), '') if stat.S_ISDIR (stat_info[stat.ST_MODE]): dirchar = 'd' else: dirchar = '-' date = ls_date (long(time.time()), stat_info[stat.ST_MTIME]) return '%s%s %3d %-8d %-8d %8d %s %s' % ( dirchar, mode, stat_info[stat.ST_NLINK], stat_info[stat.ST_UID], stat_info[stat.ST_GID], stat_info[stat.ST_SIZE], date, file ) # Emulate the unix 'ls' command's date field. # it has two formats - if the date is more than 180 # days in the past, then it's like this: # Oct 19 1995 # otherwise, it looks like this: # Oct 19 17:33 def ls_date (now, t): try: info = time.gmtime (t) except: info = time.gmtime (0) # 15,600,000 == 86,400 * 180 if (now - t) > 15600000: return '%s %2d %d' % ( months[info[1]-1], info[2], info[0] ) else: return '%s %2d %02d:%02d' % ( months[info[1]-1], info[2], info[3], info[4] ) # =========================================================================== # Producers # =========================================================================== class list_producer: def __init__ (self, list, func=None): self.list = list self.func = func # this should do a pushd/popd def more (self): if not self.list: return '' else: # do a few at a time bunch = self.list[:50] if self.func is not None: bunch = map (self.func, bunch) self.list = self.list[50:] return string.joinfields (bunch, '\r\n') + '\r\n' M2Crypto-0.22.6rc4/demo/medusa054/ftp_server.py0000664000175000017500000011706012605232411021302 0ustar matejmatej00000000000000# -*- Mode: Python -*- # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # # An extensible, configurable, asynchronous FTP server. # # All socket I/O is non-blocking, however file I/O is currently # blocking. Eventually file I/O may be made non-blocking, too, if it # seems necessary. Currently the only CPU-intensive operation is # getting and formatting a directory listing. [this could be moved # into another process/directory server, or another thread?] # # Only a subset of RFC 959 is implemented, but much of that RFC is # vestigial anyway. I've attempted to include the most commonly-used # commands, using the feature set of wu-ftpd as a guide. import asyncore import asynchat import os import socket import stat import string import sys import time #from medusa.producers import file_producer from producers import file_producer # TODO: implement a directory listing cache. On very-high-load # servers this could save a lot of disk abuse, and possibly the # work of computing emulated unix ls output. # Potential security problem with the FTP protocol? I don't think # there's any verification of the origin of a data connection. Not # really a problem for the server (since it doesn't send the port # command, except when in PASV mode) But I think a data connection # could be spoofed by a program with access to a sniffer - it could # watch for a PORT command to go over a command channel, and then # connect to that port before the server does. # Unix user id's: # In order to support assuming the id of a particular user, # it seems there are two options: # 1) fork, and seteuid in the child # 2) carefully control the effective uid around filesystem accessing # methods, using try/finally. [this seems to work] VERSION = '1.1' from counter import counter import producers import status_handler import logger class ftp_channel (asynchat.async_chat): # defaults for a reliable __repr__ addr = ('unknown','0') # unset this in a derived class in order # to enable the commands in 'self.write_commands' read_only = 1 write_commands = ['appe','dele','mkd','rmd','rnfr','rnto','stor','stou'] restart_position = 0 # comply with (possibly troublesome) RFC959 requirements # This is necessary to correctly run an active data connection # through a firewall that triggers on the source port (expected # to be 'L-1', or 20 in the normal case). bind_local_minus_one = 0 def __init__ (self, server, conn, addr): self.server = server self.current_mode = 'a' self.addr = addr asynchat.async_chat.__init__ (self, conn) self.set_terminator ('\r\n') # client data port. Defaults to 'the same as the control connection'. self.client_addr = (addr[0], 21) self.client_dc = None self.in_buffer = '' self.closing = 0 self.passive_acceptor = None self.passive_connection = None self.filesystem = None self.authorized = 0 # send the greeting self.respond ( '220 %s FTP server (Medusa Async V%s [experimental]) ready.' % ( self.server.hostname, VERSION ) ) # def __del__ (self): # print 'ftp_channel.__del__()' # -------------------------------------------------- # async-library methods # -------------------------------------------------- def handle_expt (self): # this is handled below. not sure what I could # do here to make that code less kludgish. pass def collect_incoming_data (self, data): self.in_buffer = self.in_buffer + data if len(self.in_buffer) > 4096: # silently truncate really long lines # (possible denial-of-service attack) self.in_buffer = '' def found_terminator (self): line = self.in_buffer if not len(line): return sp = string.find (line, ' ') if sp != -1: line = [line[:sp], line[sp+1:]] else: line = [line] command = string.lower (line[0]) # watch especially for 'urgent' abort commands. if string.find (command, 'abor') != -1: # strip off telnet sync chars and the like... while command and command[0] not in string.letters: command = command[1:] fun_name = 'cmd_%s' % command if command != 'pass': self.log ('<== %s' % repr(self.in_buffer)[1:-1]) else: self.log ('<== %s' % line[0]+' ') self.in_buffer = '' if not hasattr (self, fun_name): self.command_not_understood (line[0]) return fun = getattr (self, fun_name) if (not self.authorized) and (command not in ('user', 'pass', 'help', 'quit')): self.respond ('530 Please log in with USER and PASS') elif (not self.check_command_authorization (command)): self.command_not_authorized (command) else: try: result = apply (fun, (line,)) except: self.server.total_exceptions.increment() (file, fun, line), t,v, tbinfo = asyncore.compact_traceback() if self.client_dc: try: self.client_dc.close() except: pass self.respond ( '451 Server Error: %s, %s: file: %s line: %s' % ( t,v,file,line, ) ) closed = 0 def close (self): if not self.closed: self.closed = 1 if self.passive_acceptor: self.passive_acceptor.close() if self.client_dc: self.client_dc.close() self.server.closed_sessions.increment() asynchat.async_chat.close (self) # -------------------------------------------------- # filesystem interface functions. # override these to provide access control or perform # other functions. # -------------------------------------------------- def cwd (self, line): return self.filesystem.cwd (line[1]) def cdup (self, line): return self.filesystem.cdup() def open (self, path, mode): return self.filesystem.open (path, mode) # returns a producer def listdir (self, path, long=0): return self.filesystem.listdir (path, long) def get_dir_list (self, line, long=0): # we need to scan the command line for arguments to '/bin/ls'... args = line[1:] path_args = [] for arg in args: if arg[0] != '-': path_args.append (arg) else: # ignore arguments pass if len(path_args) < 1: dir = '.' else: dir = path_args[0] return self.listdir (dir, long) # -------------------------------------------------- # authorization methods # -------------------------------------------------- def check_command_authorization (self, command): if command in self.write_commands and self.read_only: return 0 else: return 1 # -------------------------------------------------- # utility methods # -------------------------------------------------- def log (self, message): self.server.logger.log ( self.addr[0], '%d %s' % ( self.addr[1], message ) ) def respond (self, resp): self.log ('==> %s' % resp) self.push (resp + '\r\n') def command_not_understood (self, command): self.respond ("500 '%s': command not understood." % command) def command_not_authorized (self, command): self.respond ( "530 You are not authorized to perform the '%s' command" % ( command ) ) def make_xmit_channel (self): # In PASV mode, the connection may or may _not_ have been made # yet. [although in most cases it is... FTP Explorer being # the only exception I've yet seen]. This gets somewhat confusing # because things may happen in any order... pa = self.passive_acceptor if pa: if pa.ready: # a connection has already been made. conn, addr = self.passive_acceptor.ready cdc = xmit_channel (self, addr) cdc.set_socket (conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: # we're still waiting for a connect to the PASV port. cdc = xmit_channel (self) else: # not in PASV mode. ip, port = self.client_addr cdc = xmit_channel (self, self.client_addr) cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) if self.bind_local_minus_one: cdc.bind (('', self.server.port - 1)) try: cdc.connect ((ip, port)) except socket.error, why: self.respond ("425 Can't build data connection") self.client_dc = cdc # pretty much the same as xmit, but only right on the verge of # being worth a merge. def make_recv_channel (self, fd): pa = self.passive_acceptor if pa: if pa.ready: # a connection has already been made. conn, addr = pa.ready cdc = recv_channel (self, addr, fd) cdc.set_socket (conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: # we're still waiting for a connect to the PASV port. cdc = recv_channel (self, None, fd) else: # not in PASV mode. ip, port = self.client_addr cdc = recv_channel (self, self.client_addr, fd) cdc.create_socket (socket.AF_INET, socket.SOCK_STREAM) try: cdc.connect ((ip, port)) except socket.error, why: self.respond ("425 Can't build data connection") self.client_dc = cdc type_map = { 'a':'ASCII', 'i':'Binary', 'e':'EBCDIC', 'l':'Binary' } type_mode_map = { 'a':'t', 'i':'b', 'e':'b', 'l':'b' } # -------------------------------------------------- # command methods # -------------------------------------------------- def cmd_type (self, line): 'specify data transfer type' # ascii, ebcdic, image, local t = string.lower (line[1]) # no support for EBCDIC # if t not in ['a','e','i','l']: if t not in ['a','i','l']: self.command_not_understood (string.join (line)) elif t == 'l' and (len(line) > 2 and line[2] != '8'): self.respond ('504 Byte size must be 8') else: self.current_mode = t self.respond ('200 Type set to %s.' % self.type_map[t]) def cmd_quit (self, line): 'terminate session' self.respond ('221 Goodbye.') self.close_when_done() def cmd_port (self, line): 'specify data connection port' info = string.split (line[1], ',') ip = string.join (info[:4], '.') port = string.atoi(info[4])*256 + string.atoi(info[5]) # how many data connections at a time? # I'm assuming one for now... # TODO: we should (optionally) verify that the # ip number belongs to the client. [wu-ftpd does this?] self.client_addr = (ip, port) self.respond ('200 PORT command successful.') def new_passive_acceptor (self): # ensure that only one of these exists at a time. if self.passive_acceptor is not None: self.passive_acceptor.close() self.passive_acceptor = None self.passive_acceptor = passive_acceptor (self) return self.passive_acceptor def cmd_pasv (self, line): 'prepare for server-to-server transfer' pc = self.new_passive_acceptor() port = pc.addr[1] ip_addr = pc.control_channel.getsockname()[0] self.respond ( '227 Entering Passive Mode (%s,%d,%d)' % ( string.replace(ip_addr, '.', ','), port/256, port%256 ) ) self.client_dc = None def cmd_nlst (self, line): 'give name list of files in directory' # ncftp adds the -FC argument for the user-visible 'nlist' # command. We could try to emulate ls flags, but not just yet. if '-FC' in line: line.remove ('-FC') try: dir_list_producer = self.get_dir_list (line, 0) except os.error, why: self.respond ('550 Could not list directory: %s' % why) return self.respond ( '150 Opening %s mode data connection for file list' % ( self.type_map[self.current_mode] ) ) self.make_xmit_channel() self.client_dc.push_with_producer (dir_list_producer) self.client_dc.close_when_done() def cmd_list (self, line): 'give a list of files in a directory' try: dir_list_producer = self.get_dir_list (line, 1) except os.error, why: self.respond ('550 Could not list directory: %s' % why) return self.respond ( '150 Opening %s mode data connection for file list' % ( self.type_map[self.current_mode] ) ) self.make_xmit_channel() self.client_dc.push_with_producer (dir_list_producer) self.client_dc.close_when_done() def cmd_cwd (self, line): 'change working directory' if self.cwd (line): self.respond ('250 CWD command successful.') else: self.respond ('550 No such directory.') def cmd_cdup (self, line): 'change to parent of current working directory' if self.cdup(line): self.respond ('250 CDUP command successful.') else: self.respond ('550 No such directory.') def cmd_pwd (self, line): 'print the current working directory' self.respond ( '257 "%s" is the current directory.' % ( self.filesystem.current_directory() ) ) # modification time # example output: # 213 19960301204320 def cmd_mdtm (self, line): 'show last modification time of file' filename = line[1] if not self.filesystem.isfile (filename): self.respond ('550 "%s" is not a file' % filename) else: mtime = time.gmtime(self.filesystem.stat(filename)[stat.ST_MTIME]) self.respond ( '213 %4d%02d%02d%02d%02d%02d' % ( mtime[0], mtime[1], mtime[2], mtime[3], mtime[4], mtime[5] ) ) def cmd_noop (self, line): 'do nothing' self.respond ('200 NOOP command successful.') def cmd_size (self, line): 'return size of file' filename = line[1] if not self.filesystem.isfile (filename): self.respond ('550 "%s" is not a file' % filename) else: self.respond ( '213 %d' % (self.filesystem.stat(filename)[stat.ST_SIZE]) ) def cmd_retr (self, line): 'retrieve a file' if len(line) < 2: self.command_not_understood (string.join (line)) else: file = line[1] if not self.filesystem.isfile (file): self.log_info ('checking %s' % file) self.respond ('550 No such file') else: try: # FIXME: for some reason, 'rt' isn't working on win95 mode = 'r'+self.type_mode_map[self.current_mode] fd = self.open (file, mode) except IOError, why: self.respond ('553 could not open file for reading: %s' % (repr(why))) return self.respond ( "150 Opening %s mode data connection for file '%s'" % ( self.type_map[self.current_mode], file ) ) self.make_xmit_channel() if self.restart_position: # try to position the file as requested, but # give up silently on failure (the 'file object' # may not support seek()) try: fd.seek (self.restart_position) except: pass self.restart_position = 0 self.client_dc.push_with_producer ( file_producer (fd) ) self.client_dc.close_when_done() def cmd_stor (self, line, mode='wb'): 'store a file' if len (line) < 2: self.command_not_understood (string.join (line)) else: if self.restart_position: restart_position = 0 self.respond ('553 restart on STOR not yet supported') return file = line[1] # todo: handle that type flag try: fd = self.open (file, mode) except IOError, why: self.respond ('553 could not open file for writing: %s' % (repr(why))) return self.respond ( '150 Opening %s connection for %s' % ( self.type_map[self.current_mode], file ) ) self.make_recv_channel (fd) def cmd_abor (self, line): 'abort operation' if self.client_dc: self.client_dc.close() self.respond ('226 ABOR command successful.') def cmd_appe (self, line): 'append to a file' return self.cmd_stor (line, 'ab') def cmd_dele (self, line): if len (line) != 2: self.command_not_understood (string.join (line)) else: file = line[1] if self.filesystem.isfile (file): try: self.filesystem.unlink (file) self.respond ('250 DELE command successful.') except: self.respond ('550 error deleting file.') else: self.respond ('550 %s: No such file.' % file) def cmd_mkd (self, line): if len (line) != 2: self.command_not_understood (string.join (line)) else: path = line[1] try: self.filesystem.mkdir (path) self.respond ('257 MKD command successful.') except: self.respond ('550 error creating directory.') def cmd_rmd (self, line): if len (line) != 2: self.command_not_understood (string.join (line)) else: path = line[1] try: self.filesystem.rmdir (path) self.respond ('250 RMD command successful.') except: self.respond ('550 error removing directory.') def cmd_user (self, line): 'specify user name' if len(line) > 1: self.user = line[1] self.respond ('331 Password required.') else: self.command_not_understood (string.join (line)) def cmd_pass (self, line): 'specify password' if len(line) < 2: pw = '' else: pw = line[1] result, message, fs = self.server.authorizer.authorize (self, self.user, pw) if result: self.respond ('230 %s' % message) self.filesystem = fs self.authorized = 1 self.log_info('Successful login: Filesystem=%s' % repr(fs)) else: self.respond ('530 %s' % message) def cmd_rest (self, line): 'restart incomplete transfer' try: pos = string.atoi (line[1]) except ValueError: self.command_not_understood (string.join (line)) self.restart_position = pos self.respond ( '350 Restarting at %d. Send STORE or RETRIEVE to initiate transfer.' % pos ) def cmd_stru (self, line): 'obsolete - set file transfer structure' if line[1] in 'fF': # f == 'file' self.respond ('200 STRU F Ok') else: self.respond ('504 Unimplemented STRU type') def cmd_mode (self, line): 'obsolete - set file transfer mode' if line[1] in 'sS': # f == 'file' self.respond ('200 MODE S Ok') else: self.respond ('502 Unimplemented MODE type') # The stat command has two personalities. Normally it returns status # information about the current connection. But if given an argument, # it is equivalent to the LIST command, with the data sent over the # control connection. Strange. But wuftpd, ftpd, and nt's ftp server # all support it. # ## def cmd_stat (self, line): ## 'return status of server' ## pass def cmd_syst (self, line): 'show operating system type of server system' # Replying to this command is of questionable utility, because # this server does not behave in a predictable way w.r.t. the # output of the LIST command. We emulate Unix ls output, but # on win32 the pathname can contain drive information at the front # Currently, the combination of ensuring that os.sep == '/' # and removing the leading slash when necessary seems to work. # [cd'ing to another drive also works] # # This is how wuftpd responds, and is probably # the most expected. The main purpose of this reply is so that # the client knows to expect Unix ls-style LIST output. self.respond ('215 UNIX Type: L8') # one disadvantage to this is that some client programs # assume they can pass args to /bin/ls. # a few typical responses: # 215 UNIX Type: L8 (wuftpd) # 215 Windows_NT version 3.51 # 215 VMS MultiNet V3.3 # 500 'SYST': command not understood. (SVR4) def cmd_help (self, line): 'give help information' # find all the methods that match 'cmd_xxxx', # use their docstrings for the help response. attrs = dir(self.__class__) help_lines = [] for attr in attrs: if attr[:4] == 'cmd_': x = getattr (self, attr) if type(x) == type(self.cmd_help): if x.__doc__: help_lines.append ('\t%s\t%s' % (attr[4:], x.__doc__)) if help_lines: self.push ('214-The following commands are recognized\r\n') self.push_with_producer (producers.lines_producer (help_lines)) self.push ('214\r\n') else: self.push ('214-\r\n\tHelp Unavailable\r\n214\r\n') class ftp_server (asyncore.dispatcher): # override this to spawn a different FTP channel class. ftp_channel_class = ftp_channel SERVER_IDENT = 'FTP Server (V%s)' % VERSION def __init__ ( self, authorizer, hostname =None, ip ='', port =21, resolver =None, logger_object=logger.file_logger (sys.stdout) ): self.ip = ip self.port = port self.authorizer = authorizer if hostname is None: self.hostname = socket.gethostname() else: self.hostname = hostname # statistics self.total_sessions = counter() self.closed_sessions = counter() self.total_files_out = counter() self.total_files_in = counter() self.total_bytes_out = counter() self.total_bytes_in = counter() self.total_exceptions = counter() # asyncore.dispatcher.__init__ (self) self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind ((self.ip, self.port)) self.listen (5) if not logger_object: logger_object = sys.stdout if resolver: self.logger = logger.resolving_logger (resolver, logger_object) else: self.logger = logger.unresolving_logger (logger_object) self.log_info('FTP server started at %s\n\tAuthorizer:%s\n\tHostname: %s\n\tPort: %d' % ( time.ctime(time.time()), repr (self.authorizer), self.hostname, self.port) ) def writable (self): return 0 def handle_read (self): pass def handle_connect (self): pass def handle_accept (self): conn, addr = self.accept() self.total_sessions.increment() self.log_info('Incoming connection from %s:%d' % (addr[0], addr[1])) self.ftp_channel_class (self, conn, addr) # return a producer describing the state of the server def status (self): def nice_bytes (n): return string.join (status_handler.english_bytes (n)) return producers.lines_producer ( ['

    %s

    ' % self.SERVER_IDENT, '
    Listening on Host: %s' % self.hostname, 'Port: %d' % self.port, '
    Sessions', 'Total: %s' % self.total_sessions, 'Current: %d' % (self.total_sessions.as_long() - self.closed_sessions.as_long()), '
    Files', 'Sent: %s' % self.total_files_out, 'Received: %s' % self.total_files_in, '
    Bytes', 'Sent: %s' % nice_bytes (self.total_bytes_out.as_long()), 'Received: %s' % nice_bytes (self.total_bytes_in.as_long()), '
    Exceptions: %s' % self.total_exceptions, ] ) # ====================================================================== # Data Channel Classes # ====================================================================== # This socket accepts a data connection, used when the server has been # placed in passive mode. Although the RFC implies that we ought to # be able to use the same acceptor over and over again, this presents # a problem: how do we shut it off, so that we are accepting # connections only when we expect them? [we can't] # # wuftpd, and probably all the other servers, solve this by allowing # only one connection to hit this acceptor. They then close it. Any # subsequent data-connection command will then try for the default # port on the client side [which is of course never there]. So the # 'always-send-PORT/PASV' behavior seems required. # # Another note: wuftpd will also be listening on the channel as soon # as the PASV command is sent. It does not wait for a data command # first. # --- we need to queue up a particular behavior: # 1) xmit : queue up producer[s] # 2) recv : the file object # # It would be nice if we could make both channels the same. Hmmm.. # class passive_acceptor (asyncore.dispatcher): ready = None def __init__ (self, control_channel): # connect_fun (conn, addr) asyncore.dispatcher.__init__ (self) self.control_channel = control_channel self.create_socket (socket.AF_INET, socket.SOCK_STREAM) # bind to an address on the interface that the # control connection is coming from. self.bind (( self.control_channel.getsockname()[0], 0 )) self.addr = self.getsockname() self.listen (1) # def __del__ (self): # print 'passive_acceptor.__del__()' def log (self, *ignore): pass def handle_accept (self): conn, addr = self.accept() dc = self.control_channel.client_dc if dc is not None: dc.set_socket (conn) dc.addr = addr dc.connected = 1 self.control_channel.passive_acceptor = None else: self.ready = conn, addr self.close() class xmit_channel (asynchat.async_chat): # for an ethernet, you want this to be fairly large, in fact, it # _must_ be large for performance comparable to an ftpd. [64k] we # ought to investigate automatically-sized buffers... ac_out_buffer_size = 16384 bytes_out = 0 def __init__ (self, channel, client_addr=None): self.channel = channel self.client_addr = client_addr asynchat.async_chat.__init__ (self) # def __del__ (self): # print 'xmit_channel.__del__()' def log (self, *args): pass def readable (self): return not self.connected def writable (self): return 1 def send (self, data): result = asynchat.async_chat.send (self, data) self.bytes_out = self.bytes_out + result return result def handle_error (self): # usually this is to catch an unexpected disconnect. self.log_info ('unexpected disconnect on data xmit channel', 'error') try: self.close() except: pass # TODO: there's a better way to do this. we need to be able to # put 'events' in the producer fifo. to do this cleanly we need # to reposition the 'producer' fifo as an 'event' fifo. def close (self): c = self.channel s = c.server c.client_dc = None s.total_files_out.increment() s.total_bytes_out.increment (self.bytes_out) if not len(self.producer_fifo): c.respond ('226 Transfer complete') elif not c.closed: c.respond ('426 Connection closed; transfer aborted') del c del s del self.channel asynchat.async_chat.close (self) class recv_channel (asyncore.dispatcher): def __init__ (self, channel, client_addr, fd): self.channel = channel self.client_addr = client_addr self.fd = fd asyncore.dispatcher.__init__ (self) self.bytes_in = counter() def log (self, *ignore): pass def handle_connect (self): pass def writable (self): return 0 def recv (*args): result = apply (asyncore.dispatcher.recv, args) self = args[0] self.bytes_in.increment(len(result)) return result buffer_size = 8192 def handle_read (self): block = self.recv (self.buffer_size) if block: try: self.fd.write (block) except IOError: self.log_info ('got exception writing block...', 'error') def handle_close (self): s = self.channel.server s.total_files_in.increment() s.total_bytes_in.increment(self.bytes_in.as_long()) self.fd.close() self.channel.respond ('226 Transfer complete.') self.close() import filesys # not much of a doorman! 8^) class dummy_authorizer: def __init__ (self, root='/'): self.root = root def authorize (self, channel, username, password): channel.persona = -1, -1 channel.read_only = 1 return 1, 'Ok.', filesys.os_filesystem (self.root) class anon_authorizer: def __init__ (self, root='/'): self.root = root def authorize (self, channel, username, password): if username in ('ftp', 'anonymous'): channel.persona = -1, -1 channel.read_only = 1 return 1, 'Ok.', filesys.os_filesystem (self.root) else: return 0, 'Password invalid.', None # =========================================================================== # Unix-specific improvements # =========================================================================== if os.name == 'posix': class unix_authorizer: # return a trio of (success, reply_string, filesystem) def authorize (self, channel, username, password): import crypt import pwd try: info = pwd.getpwnam (username) except KeyError: return 0, 'No such user.', None mangled = info[1] if crypt.crypt (password, mangled[:2]) == mangled: channel.read_only = 0 fs = filesys.schizophrenic_unix_filesystem ( '/', info[5], persona = (info[2], info[3]) ) return 1, 'Login successful.', fs else: return 0, 'Password invalid.', None def __repr__ (self): return '' # simple anonymous ftp support class unix_authorizer_with_anonymous (unix_authorizer): def __init__ (self, root=None, real_users=0): self.root = root self.real_users = real_users def authorize (self, channel, username, password): if string.lower(username) in ['anonymous', 'ftp']: import pwd try: # ok, here we run into lots of confusion. # on some os', anon runs under user 'nobody', # on others as 'ftp'. ownership is also critical. # need to investigate. # linux: new linuxen seem to have nobody's UID=-1, # which is an illegal value. Use ftp. ftp_user_info = pwd.getpwnam ('ftp') if string.lower(os.uname()[0]) == 'linux': nobody_user_info = pwd.getpwnam ('ftp') else: nobody_user_info = pwd.getpwnam ('nobody') channel.read_only = 1 if self.root is None: self.root = ftp_user_info[5] fs = filesys.unix_filesystem (self.root, '/') return 1, 'Anonymous Login Successful', fs except KeyError: return 0, 'Anonymous account not set up', None elif self.real_users: return unix_authorizer.authorize ( self, channel, username, password ) else: return 0, 'User logins not allowed', None # usage: ftp_server /PATH/TO/FTP/ROOT PORT # for example: # $ ftp_server /home/users/ftp 8021 if os.name == 'posix': def test (port='8021'): fs = ftp_server ( unix_authorizer(), port=string.atoi (port) ) try: asyncore.loop() except KeyboardInterrupt: fs.log_info('FTP server shutting down. (received SIGINT)', 'warning') # close everything down on SIGINT. # of course this should be a cleaner shutdown. asyncore.close_all() if __name__ == '__main__': test (sys.argv[1]) # not unix else: def test (): fs = ftp_server (dummy_authorizer()) if __name__ == '__main__': test () # this is the command list from the wuftpd man page # '*' means we've implemented it. # '!' requires write access # command_documentation = { 'abor': 'abort previous command', #* 'acct': 'specify account (ignored)', 'allo': 'allocate storage (vacuously)', 'appe': 'append to a file', #*! 'cdup': 'change to parent of current working directory', #* 'cwd': 'change working directory', #* 'dele': 'delete a file', #! 'help': 'give help information', #* 'list': 'give list files in a directory', #* 'mkd': 'make a directory', #! 'mdtm': 'show last modification time of file', #* 'mode': 'specify data transfer mode', 'nlst': 'give name list of files in directory', #* 'noop': 'do nothing', #* 'pass': 'specify password', #* 'pasv': 'prepare for server-to-server transfer', #* 'port': 'specify data connection port', #* 'pwd': 'print the current working directory', #* 'quit': 'terminate session', #* 'rest': 'restart incomplete transfer', #* 'retr': 'retrieve a file', #* 'rmd': 'remove a directory', #! 'rnfr': 'specify rename-from file name', #! 'rnto': 'specify rename-to file name', #! 'site': 'non-standard commands (see next section)', 'size': 'return size of file', #* 'stat': 'return status of server', #* 'stor': 'store a file', #*! 'stou': 'store a file with a unique name', #! 'stru': 'specify data transfer structure', 'syst': 'show operating system type of server system', #* 'type': 'specify data transfer type', #* 'user': 'specify user name', #* 'xcup': 'change to parent of current working directory (deprecated)', 'xcwd': 'change working directory (deprecated)', 'xmkd': 'make a directory (deprecated)', #! 'xpwd': 'print the current working directory (deprecated)', 'xrmd': 'remove a directory (deprecated)', #! } # debugging aid (linux) def get_vm_size (): return string.atoi (string.split(open ('/proc/self/stat').readline())[22]) def print_vm(): print 'vm: %8dk' % (get_vm_size()/1024) M2Crypto-0.22.6rc4/demo/medusa054/ftps_server.py0000664000175000017500000003600012607370517021473 0ustar matejmatej00000000000000"""An FTP/TLS server built on Medusa's ftp_server. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" # Python import socket, string, sys, time # Medusa from counter import counter import asynchat, asyncore, ftp_server, logger # M2Crypto from M2Crypto import SSL, version VERSION_STRING=version class ftp_tls_channel(ftp_server.ftp_channel): """FTP/TLS server channel for Medusa.""" def __init__(self, server, ssl_ctx, conn, addr): """Initialise the channel.""" self.ssl_ctx = ssl_ctx self.server = server self.current_mode = 'a' self.addr = addr asynchat.async_chat.__init__(self, conn) self.set_terminator('\r\n') self.client_addr = (addr[0], 21) self.client_dc = None self.in_buffer = '' self.closing = 0 self.passive_acceptor = None self.passive_connection = None self.filesystem = None self.authorized = 0 self._ssl_accepting = 0 self._ssl_accepted = 0 self._pbsz = None self._prot = None resp = '220 %s M2Crypto (Medusa) FTP/TLS server v%s ready.' self.respond(resp % (self.server.hostname, VERSION_STRING)) def writable(self): return self._ssl_accepting or self._ssl_accepted def handle_read(self): """Handle a read event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_read(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def handle_write(self): """Handle a write event.""" if self._ssl_accepting: self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 else: try: ftp_server.ftp_channel.handle_write(self) except SSL.SSLError, what: if str(what) == 'unexpected eof': self.close() else: raise def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' def found_terminator(self): """Dispatch the FTP command.""" line = self.in_buffer if not len(line): return sp = string.find(line, ' ') if sp != -1: line = [line[:sp], line[sp+1:]] else: line = [line] command = string.lower(line[0]) if string.find(command, 'stor') != -1: while command and command[0] not in string.letters: command = command[1:] func_name = 'cmd_%s' % command if command != 'pass': self.log('<== %s' % repr(self.in_buffer)[1:-1]) else: self.log('<== %s' % line[0]+' ') self.in_buffer = '' if not hasattr(self, func_name): self.command_not_understood(line[0]) return func = getattr(self, func_name) if not self.check_command_authorization(command): self.command_not_authorized(command) else: try: result = apply(func, (line,)) except: self.server.total_exceptions.increment() (file, func, line), t, v, tbinfo = asyncore.compact_traceback() if self.client_dc: try: self.client_dc_close() except: pass resp = '451 Server error: %s, %s: file %s line: %s' self.respond(resp % (t, v, file, line)) def make_xmit_channel(self): """Create a connection for sending data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_xmit_channel(self, conn, self.ssl_ctx, addr) else: cdc = ftp_server.xmit_channel(self, addr) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, None) else: cdc = ftp_server.xmit_channel(self) else: if self._prot: cdc = tls_xmit_channel(self, None, self.ssl_ctx, self.client_addr) else: cdc = ftp_server.xmit_channel(self, self.client_addr) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) if self.bind_local_minus_one: cdc.bind(('', self.server.port - 1)) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def make_recv_channel(self, fd): """Create a connection for receiving data.""" pa = self.passive_acceptor if pa: if pa.ready: conn, addr = pa.ready if self._prot: cdc = tls_recv_channel(self, conn, self.ssl_ctx, addr, fd) else: cdc = ftp_server.recv_channel(self, addr, fd) cdc.set_socket(conn) cdc.connected = 1 self.passive_acceptor.close() self.passive_acceptor = None else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, None, fd) else: cdc = ftp_server.recv_channel(self, None, fd) else: if self._prot: cdc = tls_recv_channel(self, None, self.ssl_ctx, self._prot, self.client_addr, fd) else: cdc = ftp_server.recv_channel(self, self.client_addr, fd) cdc.create_socket(socket.AF_INET, socket.SOCK_STREAM) try: cdc.connect(self.client_addr) except socket.error, what: self.respond('425 Cannot build data connection') self.client_dc = cdc def cmd_auth(self, line): """Prepare for TLS operation.""" # XXX Handle variations. if line[1] != 'TLS': self.command_not_understood (string.join(line)) else: self.respond('234 AUTH TLS successful') self._ssl_accepting = 1 self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.addr) self.socket.setup_ssl() self.socket.set_accept_state() self._ssl_accepted = self.socket.accept_ssl() if self._ssl_accepted: self._ssl_accepting = 0 def cmd_pbsz(self, line): """Negotiate size of buffer for secure data transfer. For FTP/TLS the only valid value for the parameter is '0'; any other value is accepted but ignored.""" if not (self._ssl_accepting or self._ssl_accepted): return self.respond('503 AUTH TLS must be issued prior to PBSZ') self._pbsz = 1 self.respond('200 PBSZ=0 successful.') def cmd_prot(self, line): """Negotiate the security level of the data connection.""" if self._pbsz is None: return self.respond('503 PBSZ must be issued prior to PROT') if line[1] == 'C': self.respond('200 Protection set to Clear') self._pbsz = None self._prot = None elif line[1] == 'P': self.respond('200 Protection set to Private') self._prot = 1 elif line[1] in ('S', 'E'): self.respond('536 PROT %s unsupported' % line[1]) else: self.respond('504 PROT %s unsupported' % line[1]) class ftp_tls_server(ftp_server.ftp_server): """FTP/TLS server for Medusa.""" SERVER_IDENT = 'M2Crypto FTP/TLS Server (v%s)' % VERSION_STRING ftp_channel_class = ftp_tls_channel def __init__(self, authz, ssl_ctx, host=None, ip='', port=21, resolver=None, log_obj=None): """Initialise the server.""" self.ssl_ctx = ssl_ctx self.ip = ip self.port = port self.authorizer = authz if host is None: self.hostname = socket.gethostname() else: self.hostname = host self.total_sessions = counter() self.closed_sessions = counter() self.total_files_out = counter() self.total_files_in = counter() self.total_bytes_out = counter() self.total_bytes_in = counter() self.total_exceptions = counter() asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((self.ip, self.port)) self.listen(5) if log_obj is None: log_obj = sys.stdout if resolver: self.logger = logger.resolving_logger(resolver, log_obj) else: self.logger = logger.unresolving_logger(logger.file_logger(sys.stdout)) l = 'M2Crypto (Medusa) FTP/TLS server started at %s\n\tAuthz: %s\n\tHostname: %s\n\tPort: %d' self.log_info(l % (time.ctime(time.time()), repr(self.authorizer), self.hostname, self.port)) def handle_accept(self): """Accept a socket and dispatch a channel to handle it.""" conn, addr = self.accept() self.total_sessions.increment() self.log_info('Connection from %s:%d' % addr) self.ftp_channel_class(self, self.ssl_ctx, conn, addr) class nbio_ftp_tls_actor: """TLS protocol negotiation mixin for FTP/TLS.""" def tls_init(self, sock, ssl_ctx, client_addr): """Perform TLS protocol negotiation.""" self.ssl_ctx = ssl_ctx self.client_addr = client_addr self._ssl_handshaking = 1 self._ssl_handshake_ok = 0 if sock: self.socket = SSL.Connection(self.ssl_ctx, sock) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() # else the client hasn't connected yet; when that happens, # handle_connect() will be triggered. def tls_neg_ok(self): """Return status of TLS protocol negotiation.""" if self._ssl_handshaking: self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 return self._ssl_handshake_ok def handle_connect(self): """Handle a data connection that occurs after this instance came into being. When this handler is triggered, self.socket has been created and refers to the underlying connected socket.""" self.socket = SSL.Connection(self.ssl_ctx, self.socket) self.socket.setup_addr(self.client_addr) self.socket.setup_ssl() self._ssl_handshake_ok = self.socket.accept_ssl() if self._ssl_handshake_ok: self._ssl_handshaking = 0 self.add_channel() def send(self, data): """Send data over SSL.""" try: result = self.socket.send(data) if result <= 0: return 0 else: return result except SSL.SSLError, what: self.close() self.log_info('send: closing channel %s %s' % (repr(self), what)) return 0 def recv(self, buffer_size): """Receive data over SSL.""" try: result = self.socket.recv(buffer_size) if not result: return '' else: return result except SSL.SSLError, what: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), what)) return '' class tls_xmit_channel(nbio_ftp_tls_actor, ftp_server.xmit_channel): """TLS driver for a send-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr=None): """Initialise the driver.""" ftp_server.xmit_channel.__init__(self, channel, client_addr) self.tls_init(conn, ssl_ctx, client_addr) def readable(self): """This channel is readable iff TLS negotiation is in progress. (Which implies a connected channel, of course.)""" if not self.connected: return 0 else: return self._ssl_handshaking def writable(self): """This channel is writable iff TLS negotiation is in progress or the application has data to send.""" if self._ssl_handshaking: return 1 else: return ftp_server.xmit_channel.writable(self) def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.xmit_channel.handle_write(self) class tls_recv_channel(nbio_ftp_tls_actor, ftp_server.recv_channel): """TLS driver for a receive-only data connection.""" def __init__(self, channel, conn, ssl_ctx, client_addr, fd): """Initialise the driver.""" ftp_server.recv_channel.__init__(self, channel, client_addr, fd) self.tls_init(conn, ssl_ctx, client_addr) def writable(self): """This channel is writable iff TLS negotiation is in progress.""" return self._ssl_handshaking def handle_read(self): """Handle a read event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_read(self) def handle_write(self): """Handle a write event: either continue with TLS negotiation or let the application handle this event.""" if self.tls_neg_ok(): ftp_server.recv_channel.handle_write(self) M2Crypto-0.22.6rc4/demo/medusa054/http_date.py0000664000175000017500000000652712605232411021104 0ustar matejmatej00000000000000# -*- Mode: Python -*- import re import string import time def concat (*args): return ''.join (args) def join (seq, field=' '): return field.join (seq) def group (s): return '(' + s + ')' short_days = ['sun','mon','tue','wed','thu','fri','sat'] long_days = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'] short_day_reg = group (join (short_days, '|')) long_day_reg = group (join (long_days, '|')) daymap = {} for i in range(7): daymap[short_days[i]] = i daymap[long_days[i]] = i hms_reg = join (3 * [group('[0-9][0-9]')], ':') months = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'] monmap = {} for i in range(12): monmap[months[i]] = i+1 months_reg = group (join (months, '|')) # From draft-ietf-http-v11-spec-07.txt/3.3.1 # Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 # Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 # Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format # rfc822 format rfc822_date = join ( [concat (short_day_reg,','), # day group('[0-9][0-9]?'), # date months_reg, # month group('[0-9]+'), # year hms_reg, # hour minute second 'gmt' ], ' ' ) rfc822_reg = re.compile (rfc822_date) def unpack_rfc822 (m): g = m.group a = string.atoi return ( a(g(4)), # year monmap[g(3)], # month a(g(2)), # day a(g(5)), # hour a(g(6)), # minute a(g(7)), # second 0, 0, 0 ) # rfc850 format rfc850_date = join ( [concat (long_day_reg,','), join ( [group ('[0-9][0-9]?'), months_reg, group ('[0-9]+') ], '-' ), hms_reg, 'gmt' ], ' ' ) rfc850_reg = re.compile (rfc850_date) # they actually unpack the same way def unpack_rfc850 (m): g = m.group a = string.atoi return ( a(g(4)), # year monmap[g(3)], # month a(g(2)), # day a(g(5)), # hour a(g(6)), # minute a(g(7)), # second 0, 0, 0 ) # parsdate.parsedate - ~700/sec. # parse_http_date - ~1333/sec. def build_http_date (when): return time.strftime ('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(when)) def parse_http_date (d): d = string.lower (d) tz = time.timezone m = rfc850_reg.match (d) if m and m.end() == len(d): retval = int (time.mktime (unpack_rfc850(m)) - tz) else: m = rfc822_reg.match (d) if m and m.end() == len(d): retval = int (time.mktime (unpack_rfc822(m)) - tz) else: return 0 # Thanks to Craig Silverstein for pointing # out the DST discrepancy if time.daylight and time.localtime(retval)[-1] == 1: # DST correction retval = retval + (tz - time.altzone) return retval M2Crypto-0.22.6rc4/demo/medusa054/http_server.py0000664000175000017500000006107312605232411021472 0ustar matejmatej00000000000000#! /usr/local/bin/python # -*- Mode: Python -*- # # Author: Sam Rushing # Copyright 1996-2000 by Sam Rushing # All Rights Reserved. # # python modules import os import re import socket import string import sys import time # async modules import asyncore import asynchat # medusa modules import http_date import producers import status_handler import logger VERSION_STRING = '1.1' from counter import counter from urllib import unquote, splitquery # =========================================================================== # Request Object # =========================================================================== class http_request: # default reply code reply_code = 200 request_counter = counter() # Whether to automatically use chunked encoding when # # HTTP version is 1.1 # Content-Length is not set # Chunked encoding is not already in effect # # If your clients are having trouble, you might want to disable this. use_chunked = 1 # by default, this request object ignores user data. collector = None def __init__ (self, *args): # unpack information about the request (self.channel, self.request, self.command, self.uri, self.version, self.header) = args self.outgoing = [] self.reply_headers = { 'Server' : 'Medusa/%s' % VERSION_STRING, 'Date' : http_date.build_http_date (time.time()) } self.request_number = http_request.request_counter.increment() self._split_uri = None self._header_cache = {} # -------------------------------------------------- # reply header management # -------------------------------------------------- def __setitem__ (self, key, value): self.reply_headers[key] = value def __getitem__ (self, key): return self.reply_headers[key] def has_key (self, key): return self.reply_headers.has_key (key) def build_reply_header (self): return string.join ( [self.response(self.reply_code)] + map ( lambda x: '%s: %s' % x, self.reply_headers.items() ), '\r\n' ) + '\r\n\r\n' # -------------------------------------------------- # split a uri # -------------------------------------------------- # ;?# path_regex = re.compile ( # path params query fragment r'([^;?#]*)(;[^?#]*)?(\?[^#]*)?(#.*)?' ) def split_uri (self): if self._split_uri is None: m = self.path_regex.match (self.uri) if m.end() != len(self.uri): raise ValueError, "Broken URI" else: self._split_uri = m.groups() return self._split_uri def get_header_with_regex (self, head_reg, group): for line in self.header: m = head_reg.match (line) if m.end() == len(line): return m.group (group) return '' def get_header (self, header): header = string.lower (header) hc = self._header_cache if not hc.has_key (header): h = header + ': ' hl = len(h) for line in self.header: if string.lower (line[:hl]) == h: r = line[hl:] hc[header] = r return r hc[header] = None return None else: return hc[header] # -------------------------------------------------- # user data # -------------------------------------------------- def collect_incoming_data (self, data): if self.collector: self.collector.collect_incoming_data (data) else: self.log_info( 'Dropping %d bytes of incoming request data' % len(data), 'warning' ) def found_terminator (self): if self.collector: self.collector.found_terminator() else: self.log_info ( 'Unexpected end-of-record for incoming request', 'warning' ) def push (self, thing): if type(thing) == type(''): self.outgoing.append(producers.simple_producer (thing)) else: self.outgoing.append(thing) def response (self, code=200): message = self.responses[code] self.reply_code = code return 'HTTP/%s %d %s' % (self.version, code, message) def error (self, code): self.reply_code = code message = self.responses[code] s = self.DEFAULT_ERROR_MESSAGE % { 'code': code, 'message': message, } self['Content-Length'] = len(s) self['Content-Type'] = 'text/html' # make an error reply self.push (s) self.done() # can also be used for empty replies reply_now = error def done (self): "finalize this transaction - send output to the http channel" # ---------------------------------------- # persistent connection management # ---------------------------------------- # --- BUCKLE UP! ---- connection = string.lower (get_header (CONNECTION, self.header)) close_it = 0 wrap_in_chunking = 0 if self.version == '1.0': if connection == 'keep-alive': if not self.has_key ('Content-Length'): close_it = 1 else: self['Connection'] = 'Keep-Alive' else: close_it = 1 elif self.version == '1.1': if connection == 'close': close_it = 1 elif not self.has_key ('Content-Length'): if self.has_key ('Transfer-Encoding'): if not self['Transfer-Encoding'] == 'chunked': close_it = 1 elif self.use_chunked: self['Transfer-Encoding'] = 'chunked' wrap_in_chunking = 1 else: close_it = 1 elif self.version is None: # Although we don't *really* support http/0.9 (because we'd have to # use \r\n as a terminator, and it would just yuck up a lot of stuff) # it's very common for developers to not want to type a version number # when using telnet to debug a server. close_it = 1 outgoing_header = producers.simple_producer (self.build_reply_header()) if close_it: self['Connection'] = 'close' if wrap_in_chunking: outgoing_producer = producers.chunked_producer ( producers.composite_producer (self.outgoing) ) # prepend the header outgoing_producer = producers.composite_producer( [outgoing_header, outgoing_producer] ) else: # prepend the header self.outgoing.insert(0, outgoing_header) outgoing_producer = producers.composite_producer (self.outgoing) # apply a few final transformations to the output self.channel.push_with_producer ( # globbing gives us large packets producers.globbing_producer ( # hooking lets us log the number of bytes sent producers.hooked_producer ( outgoing_producer, self.log ) ) ) self.channel.current_request = None if close_it: self.channel.close_when_done() def log_date_string (self, when): gmt = time.gmtime(when) if time.daylight and gmt[8]: tz = time.altzone else: tz = time.timezone if tz > 0: neg = 1 else: neg = 0 tz = -tz h, rem = divmod (tz, 3600) m, rem = divmod (rem, 60) if neg: offset = '-%02d%02d' % (h, m) else: offset = '+%02d%02d' % (h, m) return time.strftime ( '%d/%b/%Y:%H:%M:%S ', gmt) + offset def log (self, bytes): self.channel.server.logger.log ( self.channel.addr[0], '%d - - [%s] "%s" %d %d\n' % ( self.channel.addr[1], self.log_date_string (time.time()), self.request, self.reply_code, bytes ) ) responses = { 100: "Continue", 101: "Switching Protocols", 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 300: "Multiple Choices", 301: "Moved Permanently", 302: "Moved Temporarily", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Time-out", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Request Entity Too Large", 414: "Request-URI Too Large", 415: "Unsupported Media Type", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Time-out", 505: "HTTP Version not supported" } # Default error message DEFAULT_ERROR_MESSAGE = string.join ( ['', 'Error response', '', '', '

    Error response

    ', '

    Error code %(code)d.', '

    Message: %(message)s.', '', '' ], '\r\n' ) # =========================================================================== # HTTP Channel Object # =========================================================================== class http_channel (asynchat.async_chat): # use a larger default output buffer ac_out_buffer_size = 1<<16 current_request = None channel_counter = counter() def __init__ (self, server, conn, addr): self.channel_number = http_channel.channel_counter.increment() self.request_counter = counter() asynchat.async_chat.__init__ (self, conn) self.server = server self.addr = addr self.set_terminator ('\r\n\r\n') self.in_buffer = '' self.creation_time = int (time.time()) self.check_maintenance() def __repr__ (self): ar = asynchat.async_chat.__repr__(self)[1:-1] return '<%s channel#: %s requests:%s>' % ( ar, self.channel_number, self.request_counter ) # Channel Counter, Maintenance Interval... maintenance_interval = 500 def check_maintenance (self): if not self.channel_number % self.maintenance_interval: self.maintenance() def maintenance (self): self.kill_zombies() # 30-minute zombie timeout. status_handler also knows how to kill zombies. zombie_timeout = 30 * 60 def kill_zombies (self): now = int (time.time()) for channel in asyncore.socket_map.values(): if channel.__class__ == self.__class__: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() # -------------------------------------------------- # send/recv overrides, good place for instrumentation. # -------------------------------------------------- # this information needs to get into the request object, # so that it may log correctly. def send (self, data): result = asynchat.async_chat.send (self, data) self.server.bytes_out.increment (len(data)) return result def recv (self, buffer_size): try: result = asynchat.async_chat.recv (self, buffer_size) self.server.bytes_in.increment (len(result)) return result except MemoryError: # --- Save a Trip to Your Service Provider --- # It's possible for a process to eat up all the memory of # the machine, and put it in an extremely wedged state, # where medusa keeps running and can't be shut down. This # is where MemoryError tends to get thrown, though of # course it could get thrown elsewhere. sys.exit ("Out of Memory!") def handle_error (self): t, v = sys.exc_info()[:2] if t is SystemExit: raise t, v else: asynchat.async_chat.handle_error (self) def log (self, *args): pass # -------------------------------------------------- # async_chat methods # -------------------------------------------------- def collect_incoming_data (self, data): if self.current_request: # we are receiving data (probably POST data) for a request self.current_request.collect_incoming_data (data) else: # we are receiving header (request) data self.in_buffer = self.in_buffer + data def found_terminator (self): if self.current_request: self.current_request.found_terminator() else: header = self.in_buffer self.in_buffer = '' lines = string.split (header, '\r\n') # -------------------------------------------------- # crack the request header # -------------------------------------------------- while lines and not lines[0]: # as per the suggestion of http-1.1 section 4.1, (and # Eric Parker ), ignore a leading # blank lines (buggy browsers tack it onto the end of # POST requests) lines = lines[1:] if not lines: self.close_when_done() return request = lines[0] command, uri, version = crack_request (request) header = join_headers (lines[1:]) # unquote path if necessary (thanks to Skip Montanaro for pointing # out that we must unquote in piecemeal fashion). rpath, rquery = splitquery(uri) if '%' in rpath: if rquery: uri = unquote (rpath) + '?' + rquery else: uri = unquote (rpath) r = http_request (self, request, command, uri, version, header) self.request_counter.increment() self.server.total_requests.increment() if command is None: self.log_info ('Bad HTTP request: %s' % repr(request), 'error') r.error (400) return # -------------------------------------------------- # handler selection and dispatch # -------------------------------------------------- for h in self.server.handlers: if h.match (r): try: self.current_request = r # This isn't used anywhere. # r.handler = h # CYCLE h.handle_request (r) except: self.server.exceptions.increment() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback() self.log_info( 'Server Error: %s, %s: file: %s line: %s' % (t,v,file,line), 'error') try: r.error (500) except: pass return # no handlers, so complain r.error (404) def writable_for_proxy (self): # this version of writable supports the idea of a 'stalled' producer # [i.e., it's not ready to produce any output yet] This is needed by # the proxy, which will be waiting for the magic combination of # 1) hostname resolved # 2) connection made # 3) data available. if self.ac_out_buffer: return 1 elif len(self.producer_fifo): p = self.producer_fifo.first() if hasattr (p, 'stalled'): return not p.stalled() else: return 1 # =========================================================================== # HTTP Server Object # =========================================================================== class http_server (asyncore.dispatcher): SERVER_IDENT = 'HTTP Server (V%s)' % VERSION_STRING channel_class = http_channel def __init__ (self, ip, port, resolver=None, logger_object=None): self.ip = ip self.port = port asyncore.dispatcher.__init__ (self) self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.handlers = [] if not logger_object: logger_object = logger.file_logger (sys.stdout) self.set_reuse_addr() self.bind ((ip, port)) # lower this to 5 if your OS complains self.listen (1024) host, port = self.socket.getsockname() if not ip: self.log_info('Computing default hostname', 'warning') ip = socket.gethostbyname (socket.gethostname()) try: self.server_name = socket.gethostbyaddr (ip)[0] except socket.error: self.log_info('Cannot do reverse lookup', 'warning') self.server_name = ip # use the IP address as the "hostname" self.server_port = port self.total_clients = counter() self.total_requests = counter() self.exceptions = counter() self.bytes_out = counter() self.bytes_in = counter() if not logger_object: logger_object = logger.file_logger (sys.stdout) if resolver: self.logger = logger.resolving_logger (resolver, logger_object) else: self.logger = logger.unresolving_logger (logger_object) self.log_info ( 'Medusa (V%s) started at %s' '\n\tHostname: %s' '\n\tPort:%d' '\n' % ( VERSION_STRING, time.ctime(time.time()), self.server_name, port, ) ) def writable (self): return 0 def handle_read (self): pass def readable (self): return self.accepting def handle_connect (self): pass def handle_accept (self): self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. self.log_info ('warning: server accept() threw an exception', 'warning') return except TypeError: # unpack non-sequence. this can happen when a read event # fires on a listening socket, but when we call accept() # we get EWOULDBLOCK, so dispatcher.accept() returns None. # Seen on FreeBSD3. self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning') return self.channel_class (self, conn, addr) def install_handler (self, handler, back=0): if back: self.handlers.append (handler) else: self.handlers.insert (0, handler) def remove_handler (self, handler): self.handlers.remove (handler) def status (self): def nice_bytes (n): return string.join (status_handler.english_bytes (n)) handler_stats = filter (None, map (maybe_status, self.handlers)) if self.total_clients: ratio = self.total_requests.as_long() / float(self.total_clients.as_long()) else: ratio = 0.0 return producers.composite_producer ( [producers.lines_producer ( ['

    %s

    ' % self.SERVER_IDENT, '
    Listening on: Host: %s' % self.server_name, 'Port: %d' % self.port, '

      ' '
    • Total Clients: %s' % self.total_clients, 'Requests: %s' % self.total_requests, 'Requests/Client: %.1f' % (ratio), '
    • Total Bytes In: %s' % (nice_bytes (self.bytes_in.as_long())), 'Bytes Out: %s' % (nice_bytes (self.bytes_out.as_long())), '
    • Total Exceptions: %s' % self.exceptions, '

    ' 'Extension List

      ', ])] + handler_stats + [producers.simple_producer('
    ')] ) def maybe_status (thing): if hasattr (thing, 'status'): return thing.status() else: return None CONNECTION = re.compile ('Connection: (.*)', re.IGNORECASE) # merge multi-line headers # [486dx2: ~500/sec] def join_headers (headers): r = [] for i in range(len(headers)): if headers[i][0] in ' \t': r[-1] = r[-1] + headers[i][1:] else: r.append (headers[i]) return r def get_header (head_reg, lines, group=1): for line in lines: m = head_reg.match (line) if m and m.end() == len(line): return m.group (group) return '' def get_header_match (head_reg, lines): for line in lines: m = head_reg.match (line) if m and m.end() == len(line): return m return '' REQUEST = re.compile ('([^ ]+) ([^ ]+)(( HTTP/([0-9.]+))$|$)') def crack_request (r): m = REQUEST.match (r) if m and m.end() == len(r): if m.group(3): version = m.group(5) else: version = None return m.group(1), m.group(2), version else: return None, None, None if __name__ == '__main__': import sys if len(sys.argv) < 2: print 'usage: %s ' % (sys.argv[0]) else: import monitor import filesys import default_handler import status_handler import ftp_server import chat_server import resolver import logger rs = resolver.caching_resolver ('127.0.0.1') lg = logger.file_logger (sys.stdout) ms = monitor.secure_monitor_server ('fnord', '127.0.0.1', 9999) fs = filesys.os_filesystem (sys.argv[1]) dh = default_handler.default_handler (fs) hs = http_server ('', string.atoi (sys.argv[2]), rs, lg) hs.install_handler (dh) ftp = ftp_server.ftp_server ( ftp_server.dummy_authorizer(sys.argv[1]), port=8021, resolver=rs, logger_object=lg ) cs = chat_server.chat_server ('', 7777) sh = status_handler.status_extension([hs,ms,ftp,cs,rs]) hs.install_handler (sh) if ('-p' in sys.argv): def profile_loop (): try: asyncore.loop() except KeyboardInterrupt: pass import profile profile.run ('profile_loop()', 'profile.out') else: asyncore.loop() M2Crypto-0.22.6rc4/demo/medusa054/https_server.py0000664000175000017500000000515512607370517021670 0ustar matejmatej00000000000000#!/usr/bin/env python """A https server built on Medusa's http_server. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" import asynchat, asyncore, http_server, socket, sys from M2Crypto import SSL, version VERSION_STRING=version class https_channel(http_server.http_channel): ac_in_buffer_size = 1 << 16 def __init__(self, server, conn, addr): http_server.http_channel.__init__(self, server, conn, addr) def send(self, data): try: result = self.socket._write_nbio(data) if result <= 0: return 0 else: self.server.bytes_out.increment(result) return result except SSL.SSLError, why: self.close() self.log_info('send: closing channel %s %s' % (repr(self), why)) return 0 def recv(self, buffer_size): try: result = self.socket._read_nbio(buffer_size) if result is None: return '' elif result == '': self.close() return '' else: self.server.bytes_in.increment(len(result)) return result except SSL.SSLError, why: self.close() self.log_info('recv: closing channel %s %s' % (repr(self), why)) return '' class https_server(http_server.http_server): SERVER_IDENT='M2Crypto HTTPS Server (v%s)' % VERSION_STRING channel_class=https_channel def __init__(self, ip, port, ssl_ctx, resolver=None, logger_object=None): http_server.http_server.__init__(self, ip, port, resolver, logger_object) sys.stdout.write(self.SERVER_IDENT + '\n\n') sys.stdout.flush() self.ssl_ctx=ssl_ctx def handle_accept(self): # Cribbed from http_server. self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. sys.stderr.write ('warning: server accept() threw an exception\n') return # Turn the vanilla socket into an SSL connection. try: ssl_conn=SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr) except SSL.SSLError: pass def writeable(self): return 0 M2Crypto-0.22.6rc4/demo/medusa054/index.html0000664000175000017500000000015612605232411020543 0ustar matejmatej00000000000000 M2Crypto HTTPS Server

    M2Crypto HTTPS Server - It works!

    M2Crypto-0.22.6rc4/demo/medusa054/logger.py0000664000175000017500000001750012605232411020400 0ustar matejmatej00000000000000# -*- Mode: Python -*- import asynchat import socket import time # these three are for the rotating logger import os # | import stat # v # # three types of log: # 1) file # with optional flushing. Also, one that rotates the log. # 2) socket # dump output directly to a socket connection. [how do we # keep it open?] # 3) syslog # log to syslog via tcp. this is a per-line protocol. # # # The 'standard' interface to a logging object is simply # log_object.log (message) # # a file-like object that captures output, and # makes sure to flush it always... this could # be connected to: # o stdio file # o low-level file # o socket channel # o syslog output... class file_logger: # pass this either a path or a file object. def __init__ (self, file, flush=1, mode='a'): if type(file) == type(''): if (file == '-'): import sys self.file = sys.stdout else: self.file = open (file, mode) else: self.file = file self.do_flush = flush def __repr__ (self): return '' % self.file def write (self, data): self.file.write (data) self.maybe_flush() def writeline (self, line): self.file.writeline (line) self.maybe_flush() def writelines (self, lines): self.file.writelines (lines) self.maybe_flush() def maybe_flush (self): if self.do_flush: self.file.flush() def flush (self): self.file.flush() def softspace (self, *args): pass def log (self, message): if message[-1] not in ('\r', '\n'): self.write (message + '\n') else: self.write (message) # like a file_logger, but it must be attached to a filename. # When the log gets too full, or a certain time has passed, # it backs up the log and starts a new one. Note that backing # up the log is done via "mv" because anything else (cp, gzip) # would take time, during which medusa would do nothing else. class rotating_file_logger (file_logger): # If freq is non-None we back up "daily", "weekly", or "monthly". # Else if maxsize is non-None we back up whenever the log gets # to big. If both are None we never back up. def __init__ (self, file, freq=None, maxsize=None, flush=1, mode='a'): self.filename = file self.mode = mode self.file = open (file, mode) self.freq = freq self.maxsize = maxsize self.rotate_when = self.next_backup(self.freq) self.do_flush = flush def __repr__ (self): return '' % self.file # We back up at midnight every 1) day, 2) monday, or 3) 1st of month def next_backup (self, freq): (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) if freq == 'daily': return time.mktime((yr,mo,day+1, 0,0,0, 0,0,-1)) elif freq == 'weekly': return time.mktime((yr,mo,day-wd+7, 0,0,0, 0,0,-1)) # wd(monday)==0 elif freq == 'monthly': return time.mktime((yr,mo+1,1, 0,0,0, 0,0,-1)) else: return None # not a date-based backup def maybe_flush (self): # rotate first if necessary self.maybe_rotate() if self.do_flush: # from file_logger() self.file.flush() def maybe_rotate (self): if self.freq and time.time() > self.rotate_when: self.rotate() self.rotate_when = self.next_backup(self.freq) elif self.maxsize: # rotate when we get too big try: if os.stat(self.filename)[stat.ST_SIZE] > self.maxsize: self.rotate() except os.error: # file not found, probably self.rotate() # will create a new file def rotate (self): (yr, mo, day, hr, min, sec, wd, jday, dst) = time.localtime(time.time()) try: self.file.close() newname = '%s.ends%04d%02d%02d' % (self.filename, yr, mo, day) try: open(newname, "r").close() # check if file exists newname = newname + "-%02d%02d%02d" % (hr, min, sec) except: # YEARMODY is unique pass os.rename(self.filename, newname) self.file = open(self.filename, self.mode) except: pass # syslog is a line-oriented log protocol - this class would be # appropriate for FTP or HTTP logs, but not for dumping stderr to. # TODO: a simple safety wrapper that will ensure that the line sent # to syslog is reasonable. # TODO: async version of syslog_client: now, log entries use blocking # send() import m_syslog syslog_logger = m_syslog.syslog_client class syslog_logger (m_syslog.syslog_client): def __init__ (self, address, facility='user'): m_syslog.syslog_client.__init__ (self, address) self.facility = m_syslog.facility_names[facility] self.address=address def __repr__ (self): return '' % (repr(self.address)) def log (self, message): m_syslog.syslog_client.log ( self, message, facility=self.facility, priority=m_syslog.LOG_INFO ) # log to a stream socket, asynchronously class socket_logger (asynchat.async_chat): def __init__ (self, address): if type(address) == type(''): self.create_socket (socket.AF_UNIX, socket.SOCK_STREAM) else: self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.connect (address) self.address = address def __repr__ (self): return '' % (self.address) def log (self, message): if message[-2:] != '\r\n': self.socket.push (message + '\r\n') else: self.socket.push (message) # log to multiple places class multi_logger: def __init__ (self, loggers): self.loggers = loggers def __repr__ (self): return '' % (repr(self.loggers)) def log (self, message): for logger in self.loggers: logger.log (message) class resolving_logger: """Feed (ip, message) combinations into this logger to get a resolved hostname in front of the message. The message will not be logged until the PTR request finishes (or fails).""" def __init__ (self, resolver, logger): self.resolver = resolver self.logger = logger class logger_thunk: def __init__ (self, message, logger): self.message = message self.logger = logger def __call__ (self, host, ttl, answer): if not answer: answer = host self.logger.log ('%s:%s' % (answer, self.message)) def log (self, ip, message): self.resolver.resolve_ptr ( ip, self.logger_thunk ( message, self.logger ) ) class unresolving_logger: "Just in case you don't want to resolve" def __init__ (self, logger): self.logger = logger def log (self, ip, message): self.logger.log ('%s:%s' % (ip, message)) def strip_eol (line): while line and line[-1] in '\r\n': line = line[:-1] return line class tail_logger: "Keep track of the last log messages" def __init__ (self, logger, size=500): self.size = size self.logger = logger self.messages = [] def log (self, message): self.messages.append (strip_eol (message)) if len (self.messages) > self.size: del self.messages[0] self.logger.log (message) M2Crypto-0.22.6rc4/demo/medusa054/m_syslog.py0000664000175000017500000001626712605232411020766 0ustar matejmatej00000000000000# -*- Mode: Python -*- # ====================================================================== # Copyright 1997 by Sam Rushing # # All Rights Reserved # # 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, and that the name of Sam # Rushing not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN # NO EVENT SHALL SAM RUSHING 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. # ====================================================================== """socket interface to unix syslog. On Unix, there are usually two ways of getting to syslog: via a local unix-domain socket, or via the TCP service. Usually "/dev/log" is the unix domain socket. This may be different for other systems. >>> my_client = syslog_client ('/dev/log') Otherwise, just use the UDP version, port 514. >>> my_client = syslog_client (('my_log_host', 514)) On win32, you will have to use the UDP version. Note that you can use this to log to other hosts (and indeed, multiple hosts). This module is not a drop-in replacement for the python extension module - the interface is different. Usage: >>> c = syslog_client() >>> c = syslog_client ('/strange/non_standard_log_location') >>> c = syslog_client (('other_host.com', 514)) >>> c.log ('testing', facility='local0', priority='debug') """ # TODO: support named-pipe syslog. # [see ftp://sunsite.unc.edu/pub/Linux/system/Daemons/syslog-fifo.tar.z] # from : # =========================================================================== # priorities/facilities are encoded into a single 32-bit quantity, where the # bottom 3 bits are the priority (0-7) and the top 28 bits are the facility # (0-big number). Both the priorities and the facilities map roughly # one-to-one to strings in the syslogd(8) source code. This mapping is # included in this file. # # priorities (these are ordered) LOG_EMERG = 0 # system is unusable LOG_ALERT = 1 # action must be taken immediately LOG_CRIT = 2 # critical conditions LOG_ERR = 3 # error conditions LOG_WARNING = 4 # warning conditions LOG_NOTICE = 5 # normal but significant condition LOG_INFO = 6 # informational LOG_DEBUG = 7 # debug-level messages # facility codes LOG_KERN = 0 # kernel messages LOG_USER = 1 # random user-level messages LOG_MAIL = 2 # mail system LOG_DAEMON = 3 # system daemons LOG_AUTH = 4 # security/authorization messages LOG_SYSLOG = 5 # messages generated internally by syslogd LOG_LPR = 6 # line printer subsystem LOG_NEWS = 7 # network news subsystem LOG_UUCP = 8 # UUCP subsystem LOG_CRON = 9 # clock daemon LOG_AUTHPRIV = 10 # security/authorization messages (private) # other codes through 15 reserved for system use LOG_LOCAL0 = 16 # reserved for local use LOG_LOCAL1 = 17 # reserved for local use LOG_LOCAL2 = 18 # reserved for local use LOG_LOCAL3 = 19 # reserved for local use LOG_LOCAL4 = 20 # reserved for local use LOG_LOCAL5 = 21 # reserved for local use LOG_LOCAL6 = 22 # reserved for local use LOG_LOCAL7 = 23 # reserved for local use priority_names = { "alert": LOG_ALERT, "crit": LOG_CRIT, "debug": LOG_DEBUG, "emerg": LOG_EMERG, "err": LOG_ERR, "error": LOG_ERR, # DEPRECATED "info": LOG_INFO, "notice": LOG_NOTICE, "panic": LOG_EMERG, # DEPRECATED "warn": LOG_WARNING, # DEPRECATED "warning": LOG_WARNING, } facility_names = { "auth": LOG_AUTH, "authpriv": LOG_AUTHPRIV, "cron": LOG_CRON, "daemon": LOG_DAEMON, "kern": LOG_KERN, "lpr": LOG_LPR, "mail": LOG_MAIL, "news": LOG_NEWS, "security": LOG_AUTH, # DEPRECATED "syslog": LOG_SYSLOG, "user": LOG_USER, "uucp": LOG_UUCP, "local0": LOG_LOCAL0, "local1": LOG_LOCAL1, "local2": LOG_LOCAL2, "local3": LOG_LOCAL3, "local4": LOG_LOCAL4, "local5": LOG_LOCAL5, "local6": LOG_LOCAL6, "local7": LOG_LOCAL7, } import socket class syslog_client: def __init__ (self, address='/dev/log'): self.address = address self.stream = 0 if isinstance(address, type('')): try: self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) self.socket.connect(address) except socket.error: # Some Linux installations have /dev/log # a stream socket instead of a datagram socket. self.socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM) self.stream = 1 else: self.socket = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) # curious: when talking to the unix-domain '/dev/log' socket, a # zero-terminator seems to be required. this string is placed # into a class variable so that it can be overridden if # necessary. log_format_string = '<%d>%s\000' def log (self, message, facility=LOG_USER, priority=LOG_INFO): message = self.log_format_string % ( self.encode_priority (facility, priority), message ) if self.stream: self.socket.send (message) else: self.socket.sendto (message, self.address) def encode_priority (self, facility, priority): if type(facility) == type(''): facility = facility_names[facility] if type(priority) == type(''): priority = priority_names[priority] return (facility<<3) | priority def close (self): if self.stream: self.socket.close() M2Crypto-0.22.6rc4/demo/medusa054/medusa_gif.py0000664000175000017500000000532412605232411021225 0ustar matejmatej00000000000000# -*- Mode: Python -*- # the medusa icon as a python source file. width = 97 height = 61 data = 'GIF89aa\000=\000\204\000\000\000\000\000\255\255\255\245\245\245ssskkkccc111)))\326\326\326!!!\316\316\316\300\300\300\204\204\000\224\224\224\214\214\214\200\200\200RRR\377\377\377JJJ\367\367\367BBB\347\347\347\000\204\000\020\020\020\265\265\265\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\371\004\001\000\000\021\000,\000\000\000\000a\000=\000\000\005\376`$\216di\236h\252\256l\353\276p,\317tm\337x\256\357|m\001@\240E\305\000\364\2164\206R)$\005\201\214\007r\012{X\255\312a\004\260\\>\026\3240\353)\224n\001W+X\334\373\231~\344.\303b\216\024\027x<\273\307\255G,rJiWN\014{S}k"?ti\013EdPQ\207G@_%\000\026yy\\\201\202\227\224<\221Fs$pOjWz\241\272\002\325\307g\012(\007\205\312#j\317(\012A\200\224.\241\003\346GS\247\033\245\344\264\366\015L\'PXQl]\266\263\243\232\260?\245\316\371\362\225\035\332\243J\273\332Q\263\357-D\241T\327\270\265\013W&\330\010u\371b\322IW0\214\261]\003\033Va\365Z#\207\213a\030k\2647\262\014p\354\024[n\321N\363\346\317\003\037P\000\235C\302\000\3228(\244\363YaA\005\022\255_\237@\260\000A\212\326\256qbp\321\332\266\011\334=T\023\010"!B\005\003A\010\224\020\220 H\002\337#\020 O\276E\357h\221\327\003\\\000b@v\004\351A.h\365\354\342B\002\011\257\025\\ \220\340\301\353\006\000\024\214\200pA\300\353\012\364\241k/\340\033C\202\003\000\310fZ\011\003V\240R\005\007\354\376\026A\000\000\360\'\202\177\024\004\210\003\000\305\215\360\000\000\015\220\240\332\203\027@\'\202\004\025VpA\000%\210x\321\206\032J\341\316\010\262\211H"l\333\341\200\200>"]P\002\212\011\010`\002\0066FP\200\001\'\024p]\004\027(8B\221\306]\000\201w>\002iB\001\007\340\260"v7J1\343(\257\020\251\243\011\242i\263\017\215\337\035\220\200\221\365m4d\015\016D\251\341iN\354\346Ng\253\200I\240\031\35609\245\2057\311I\302\2007t\231"&`\314\310\244\011e\226(\236\010w\212\300\234\011\012HX(\214\253\311@\001\233^\222pg{% \340\035\224&H\000\246\201\362\215`@\001"L\340\004\030\234\022\250\'\015(V:\302\235\030\240q\337\205\224\212h@\177\006\000\250\210\004\007\310\207\337\005\257-P\346\257\367]p\353\203\271\256:\203\236\211F\340\247\010\3329g\244\010\307*=A\000\203\260y\012\304s#\014\007D\207,N\007\304\265\027\021C\233\207%B\366[m\353\006\006\034j\360\306+\357\274a\204\000\000;' M2Crypto-0.22.6rc4/demo/medusa054/poison_handler.py0000664000175000017500000000340612607370517022141 0ustar matejmatej00000000000000 import string import whrandom RESP_HEAD="""\ """ RESP_MIDDLE="""

    M2Crypto https server demonstration

    This web page is generated by the "poison" http request handler.
    The links just go on and on and on...

    """ RESP_TAIL=""" """ charset='012345678/90ABCDEFGHIJKLM/NOPQRSTUVWXYZabcd/efghijklmnopqrs/tuvwxyz' numchar=len(charset) def makepage(numlinks): title='' for u in range(whrandom.randint(3, 15)): pick=whrandom.randint(0, numchar-1) title=title+charset[pick] title=title+'' url='\r\n' numlinks=whrandom.randint(2, numlinks) for i in range(numlinks): url=url+'' for u in range(whrandom.randint(3, 15)): pick=whrandom.randint(0, numchar-1) url=url+charset[pick] url=url+'
    \r\n' url=RESP_HEAD+title+RESP_MIDDLE+url+RESP_TAIL return url class poison_handler: """This is a clone of webpoison - every URL returns a page of URLs, each of which returns a page of URLs, each of _which_ returns a page of URLs, ad infinitum. The objective is to sucker address-harvesting bots run by spammers.""" def __init__(self, numlinks=10): self.numlinks = numlinks self.poison_level = 0 def match(self, request): return (request.uri[:7] == '/poison') def handle_request(self, request): if request.command == 'get': request.push(makepage(self.numlinks)) request.done() M2Crypto-0.22.6rc4/demo/medusa054/producers.py0000664000175000017500000002222612605232411021130 0ustar matejmatej00000000000000# -*- Mode: Python -*- """ A collection of producers. Each producer implements a particular feature: They can be combined in various ways to get interesting and useful behaviors. For example, you can feed dynamically-produced output into the compressing producer, then wrap this with the 'chunked' transfer-encoding producer. """ import string from asynchat import find_prefix_at_end class simple_producer: "producer for a string" def __init__ (self, data, buffer_size=1024): self.data = data self.buffer_size = buffer_size def more (self): if len (self.data) > self.buffer_size: result = self.data[:self.buffer_size] self.data = self.data[self.buffer_size:] return result else: result = self.data self.data = '' return result class scanning_producer: "like simple_producer, but more efficient for large strings" def __init__ (self, data, buffer_size=1024): self.data = data self.buffer_size = buffer_size self.pos = 0 def more (self): if self.pos < len(self.data): lp = self.pos rp = min ( len(self.data), self.pos + self.buffer_size ) result = self.data[lp:rp] self.pos = self.pos + len(result) return result else: return '' class lines_producer: "producer for a list of lines" def __init__ (self, lines): self.lines = lines def more (self): if self.lines: chunk = self.lines[:50] self.lines = self.lines[50:] return string.join (chunk, '\r\n') + '\r\n' else: return '' class buffer_list_producer: "producer for a list of strings" # i.e., data == string.join (buffers, '') def __init__ (self, buffers): self.index = 0 self.buffers = buffers def more (self): if self.index >= len(self.buffers): return '' else: data = self.buffers[self.index] self.index = self.index + 1 return data class file_producer: "producer wrapper for file[-like] objects" # match http_channel's outgoing buffer size out_buffer_size = 1<<16 def __init__ (self, file): self.done = 0 self.file = file def more (self): if self.done: return '' else: data = self.file.read (self.out_buffer_size) if not data: self.file.close() del self.file self.done = 1 return '' else: return data # A simple output producer. This one does not [yet] have # the safety feature builtin to the monitor channel: runaway # output will not be caught. # don't try to print from within any of the methods # of this object. class output_producer: "Acts like an output file; suitable for capturing sys.stdout" def __init__ (self): self.data = '' def write (self, data): lines = string.splitfields (data, '\n') data = string.join (lines, '\r\n') self.data = self.data + data def writeline (self, line): self.data = self.data + line + '\r\n' def writelines (self, lines): self.data = self.data + string.joinfields ( lines, '\r\n' ) + '\r\n' def flush (self): pass def softspace (self, *args): pass def more (self): if self.data: result = self.data[:512] self.data = self.data[512:] return result else: return '' class composite_producer: "combine a fifo of producers into one" def __init__ (self, producers): self.producers = producers def more (self): while len(self.producers): p = self.producers[0] d = p.more() if d: return d else: self.producers.pop(0) else: return '' class globbing_producer: """ 'glob' the output from a producer into a particular buffer size. helps reduce the number of calls to send(). [this appears to gain about 30% performance on requests to a single channel] """ def __init__ (self, producer, buffer_size=1<<16): self.producer = producer self.buffer = '' self.buffer_size = buffer_size def more (self): while len(self.buffer) < self.buffer_size: data = self.producer.more() if data: self.buffer = self.buffer + data else: break r = self.buffer self.buffer = '' return r class hooked_producer: """ A producer that will call when it empties,. with an argument of the number of bytes produced. Useful for logging/instrumentation purposes. """ def __init__ (self, producer, function): self.producer = producer self.function = function self.bytes = 0 def more (self): if self.producer: result = self.producer.more() if not result: self.producer = None self.function (self.bytes) else: self.bytes = self.bytes + len(result) return result else: return '' # HTTP 1.1 emphasizes that an advertised Content-Length header MUST be # correct. In the face of Strange Files, it is conceivable that # reading a 'file' may produce an amount of data not matching that # reported by os.stat() [text/binary mode issues, perhaps the file is # being appended to, etc..] This makes the chunked encoding a True # Blessing, and it really ought to be used even with normal files. # How beautifully it blends with the concept of the producer. class chunked_producer: """A producer that implements the 'chunked' transfer coding for HTTP/1.1. Here is a sample usage: request['Transfer-Encoding'] = 'chunked' request.push ( producers.chunked_producer (your_producer) ) request.done() """ def __init__ (self, producer, footers=None): self.producer = producer self.footers = footers def more (self): if self.producer: data = self.producer.more() if data: return '%x\r\n%s\r\n' % (len(data), data) else: self.producer = None if self.footers: return string.join ( ['0'] + self.footers, '\r\n' ) + '\r\n\r\n' else: return '0\r\n\r\n' else: return '' # Unfortunately this isn't very useful right now (Aug 97), because # apparently the browsers don't do on-the-fly decompression. Which # is sad, because this could _really_ speed things up, especially for # low-bandwidth clients (i.e., most everyone). try: import zlib except ImportError: zlib = None class compressed_producer: """ Compress another producer on-the-fly, using ZLIB [Unfortunately, none of the current browsers seem to support this] """ # Note: It's not very efficient to have the server repeatedly # compressing your outgoing files: compress them ahead of time, or # use a compress-once-and-store scheme. However, if you have low # bandwidth and low traffic, this may make more sense than # maintaining your source files compressed. # # Can also be used for compressing dynamically-produced output. def __init__ (self, producer, level=5): self.producer = producer self.compressor = zlib.compressobj (level) def more (self): if self.producer: cdata = '' # feed until we get some output while not cdata: data = self.producer.more() if not data: self.producer = None return self.compressor.flush() else: cdata = self.compressor.compress (data) return cdata else: return '' class escaping_producer: "A producer that escapes a sequence of characters" " Common usage: escaping the CRLF.CRLF sequence in SMTP, NNTP, etc..." def __init__ (self, producer, esc_from='\r\n.', esc_to='\r\n..'): self.producer = producer self.esc_from = esc_from self.esc_to = esc_to self.buffer = '' self.find_prefix_at_end = find_prefix_at_end def more (self): esc_from = self.esc_from esc_to = self.esc_to buffer = self.buffer + self.producer.more() if buffer: buffer = string.replace (buffer, esc_from, esc_to) i = self.find_prefix_at_end (buffer, esc_from) if i: # we found a prefix self.buffer = buffer[-i:] return buffer[:-i] else: # no prefix, return it all self.buffer = '' return buffer else: return buffer M2Crypto-0.22.6rc4/demo/medusa054/server.pem0000664000175000017500000000411012605232411020551 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/medusa054/status_handler.py0000664000175000017500000002211312605232411022135 0ustar matejmatej00000000000000# -*- Mode: Python -*- VERSION_STRING = "$Id$" # # medusa status extension # import string import time import re from cgi import escape import asyncore import http_server import medusa_gif import producers from counter import counter START_TIME = long(time.time()) class status_extension: hit_counter = counter() def __init__ (self, objects, statusdir='/status', allow_emergency_debug=0): self.objects = objects self.statusdir = statusdir self.allow_emergency_debug = allow_emergency_debug # We use /status instead of statusdir here because it's too # hard to pass statusdir to the logger, who makes the HREF # to the object dir. We don't need the security-through- # obscurity here in any case, because the id is obscurity enough self.hyper_regex = re.compile('/status/object/([0-9]+)/.*') self.hyper_objects = [] for object in objects: self.register_hyper_object (object) def __repr__ (self): return '' % ( self.hit_counter, id(self) ) def match (self, request): path, params, query, fragment = request.split_uri() # For reasons explained above, we don't use statusdir for /object return (path[:len(self.statusdir)] == self.statusdir or path[:len("/status/object/")] == '/status/object/') # Possible Targets: # /status # /status/channel_list # /status/medusa.gif # can we have 'clickable' objects? # [yes, we can use id(x) and do a linear search] # Dynamic producers: # HTTP/1.0: we must close the channel, because it's dynamic output # HTTP/1.1: we can use the chunked transfer-encoding, and leave # it open. def handle_request (self, request): [path, params, query, fragment] = request.split_uri() self.hit_counter.increment() if path == self.statusdir: # and not a subdirectory up_time = string.join (english_time (long(time.time()) - START_TIME)) request['Content-Type'] = 'text/html' request.push ( '' 'Medusa Status Reports' '' '

    Medusa Status Reports

    ' 'Up: %s' % up_time ) for i in range(len(self.objects)): request.push (self.objects[i].status()) request.push ('
    \r\n') request.push ( '

    Channel List' '


    ' '' '' % ( self.statusdir, self.statusdir, medusa_gif.width, medusa_gif.height ) ) request.done() elif path == self.statusdir + '/channel_list': request['Content-Type'] = 'text/html' request.push ('') request.push(channel_list_producer(self.statusdir)) request.push ( '
    ' '' % ( self.statusdir, medusa_gif.width, medusa_gif.height ) + '' ) request.done() elif path == self.statusdir + '/medusa.gif': request['Content-Type'] = 'image/gif' request['Content-Length'] = len(medusa_gif.data) request.push (medusa_gif.data) request.done() elif path == self.statusdir + '/close_zombies': message = ( '

    Closing all zombie http client connections...

    ' '

    Back to the status page' % self.statusdir ) request['Content-Type'] = 'text/html' request['Content-Length'] = len (message) request.push (message) now = int (time.time()) for channel in asyncore.socket_map.keys(): if channel.__class__ == http_server.http_channel: if channel != request.channel: if (now - channel.creation_time) > channel.zombie_timeout: channel.close() request.done() # Emergency Debug Mode # If a server is running away from you, don't KILL it! # Move all the AF_INET server ports and perform an autopsy... # [disabled by default to protect the innocent] elif self.allow_emergency_debug and path == self.statusdir + '/emergency_debug': request.push ('Moving All Servers...') request.done() for channel in asyncore.socket_map.keys(): if channel.accepting: if type(channel.addr) is type(()): ip, port = channel.addr channel.socket.close() channel.del_channel() channel.addr = (ip, port+10000) fam, typ = channel.family_and_type channel.create_socket (fam, typ) channel.set_reuse_addr() channel.bind (channel.addr) channel.listen(5) else: m = self.hyper_regex.match (path) if m: oid = string.atoi (m.group (1)) for object in self.hyper_objects: if id (object) == oid: if hasattr (object, 'hyper_respond'): object.hyper_respond (self, path, request) else: request.error (404) return def status (self): return producers.simple_producer ( '

  • Status Extension Hits : %s' % self.hit_counter ) def register_hyper_object (self, object): if not object in self.hyper_objects: self.hyper_objects.append (object) import logger class logger_for_status (logger.tail_logger): def status (self): return 'Last %d log entries for: %s' % ( len (self.messages), html_repr (self) ) def hyper_respond (self, sh, path, request): request['Content-Type'] = 'text/plain' messages = self.messages[:] messages.reverse() request.push (lines_producer (messages)) request.done() class lines_producer: def __init__ (self, lines): self.lines = lines def more (self): if self.lines: chunk = self.lines[:50] self.lines = self.lines[50:] return string.join (chunk, '\r\n') + '\r\n' else: return '' class channel_list_producer (lines_producer): def __init__ (self, statusdir): channel_reprs = map ( lambda x: '<' + repr(x)[1:-1] + '>', asyncore.socket_map.values() ) channel_reprs.sort() lines_producer.__init__ ( self, ['

    Active Channel List

    ', '
    '
                     ] + channel_reprs + [
                             '
    ', '

    Status Report' % statusdir ] ) def html_repr (object): so = escape (repr (object)) if hasattr (object, 'hyper_respond'): return '%s' % (id (object), so) else: return so def html_reprs (list, front='', back=''): reprs = map ( lambda x,f=front,b=back: '%s%s%s' % (f,x,b), map (lambda x: escape (html_repr(x)), list) ) reprs.sort() return reprs # for example, tera, giga, mega, kilo # p_d (n, (1024, 1024, 1024, 1024)) # smallest divider goes first - for example # minutes, hours, days # p_d (n, (60, 60, 24)) def progressive_divide (n, parts): result = [] for part in parts: n, rem = divmod (n, part) result.append (rem) result.append (n) return result # b,k,m,g,t def split_by_units (n, units, dividers, format_string): divs = progressive_divide (n, dividers) result = [] for i in range(len(units)): if divs[i]: result.append (format_string % (divs[i], units[i])) result.reverse() if not result: return [format_string % (0, units[0])] else: return result def english_bytes (n): return split_by_units ( n, ('','K','M','G','T'), (1024, 1024, 1024, 1024, 1024), '%d %sB' ) def english_time (n): return split_by_units ( n, ('secs', 'mins', 'hours', 'days', 'weeks', 'years'), ( 60, 60, 24, 7, 52), '%d %s' ) M2Crypto-0.22.6rc4/demo/medusa054/xmlrpc_handler.py0000664000175000017500000000550312605232411022123 0ustar matejmatej00000000000000# -*- Mode: Python -*- # See http://www.xml-rpc.com/ # http://www.pythonware.com/products/xmlrpc/ # Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com) VERSION = "$Id$" import http_server import xmlrpclib import string import sys class xmlrpc_handler: def match (self, request): # Note: /RPC2 is not required by the spec, so you may override this method. if request.uri[:5] == '/RPC2': return 1 else: return 0 def handle_request (self, request): [path, params, query, fragment] = request.split_uri() if request.command == 'POST': request.collector = collector (self, request) else: request.error (400) def continue_request (self, data, request): params, method = xmlrpclib.loads (data) try: # generate response try: response = self.call (method, params) if type(response) != type(()): response = (response,) except: # report exception back to server response = xmlrpclib.dumps ( xmlrpclib.Fault (1, "%s:%s" % (sys.exc_type, sys.exc_value)) ) else: response = xmlrpclib.dumps (response, methodresponse=1) except: # internal error, report as HTTP server error request.error (500) else: # got a valid XML RPC response request['Content-Type'] = 'text/xml' request.push (response) request.done() def call (self, method, params): # override this method to implement RPC methods raise "NotYetImplemented" class collector: "gathers input for POST and PUT requests" def __init__ (self, handler, request): self.handler = handler self.request = request self.data = '' # make sure there's a content-length header cl = request.get_header ('content-length') if not cl: request.error (411) else: cl = string.atoi (cl) # using a 'numeric' terminator self.request.channel.set_terminator (cl) def collect_incoming_data (self, data): self.data = self.data + data def found_terminator (self): # set the terminator back to the default self.request.channel.set_terminator ('\r\n\r\n') self.handler.continue_request (self.data, self.request) if __name__ == '__main__': class rpc_demo (xmlrpc_handler): def call (self, method, params): print 'method="%s" params=%s' % (method, params) return "Sure, that works" import asyncore hs = http_server.http_server ('', 8000) rpc = rpc_demo() hs.install_handler (rpc) asyncore.loop() M2Crypto-0.22.6rc4/demo/perf/0000775000175000017500000000000012613362233015776 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/perf/memio.py0000664000175000017500000000236612607370517017474 0ustar matejmatej00000000000000#!/usr/bin/env python2.0 """A comparison of Python's cStringIO and M2Crypto's MemoryBuffer, the outcome of which is that MemoryBuffer suffers from doing too much in Python. Two way to optimise MemoryBuffer: 1. Create MemoryBufferIn and MemoryBufferOut a la StringI and StringO. 2. Have MemoryBuffer do all internal work with cStringIO. ;-) """ from cStringIO import StringIO from M2Crypto.BIO import MemoryBuffer from M2Crypto import m2 import profile txt = 'Python, Smalltalk, Haskell, Scheme, Lisp, Self, Erlang, ML, ...' def stringi(iter, txt=txt): buf = StringIO() for i in range(iter): buf.write(txt) out = buf.getvalue() def membufi(iter, txt=txt): buf = MemoryBuffer() for i in range(iter): buf.write(txt) out = buf.getvalue() def membuf2i(iter, txt=txt): buf = MemoryBuffer() buf.write(txt * iter) out = buf.getvalue() def cmembufi(iter, txt=txt): buf = m2.bio_new(m2.bio_s_mem()) for i in range(iter): m2.bio_write(buf, txt) m2.bio_set_mem_eof_return(buf, 0) out = m2.bio_read(buf, m2.bio_ctrl_pending(buf)) if __name__ == '__main__': profile.run('stringi(10000)') profile.run('cmembufi(10000)') profile.run('membufi(10000)') profile.run('membuf2i(10000)') M2Crypto-0.22.6rc4/demo/perf/sha1.py0000664000175000017500000000204512607370517017214 0ustar matejmatej00000000000000#!/usr/bin/env python2.0 """A comparison of Python's sha and M2Crypto.EVP.MessageDigest, the outcome of which is that EVP.MessageDigest suffers from doing too much in Python.""" import profile from sha import sha import M2Crypto from M2Crypto import m2 from M2Crypto.EVP import MessageDigest txt = 'Python, Smalltalk, Haskell, Scheme, Lisp, Self, Erlang, ML, ...' def py_sha(iter, txt=txt): s = sha() for i in range(iter): s.update(txt) out = s.digest() def m2_sha(iter, txt=txt): s = MessageDigest('sha1') for i in range(iter): s.update(txt) out = s.digest() def m2_sha_2(iter, txt=txt): s = MessageDigest('sha1') s.update(txt * iter) out = s.digest() def m2c_sha(iter, txt=txt): ctx = m2.md_ctx_new() m2.digest_init(ctx, m2.sha1()) for i in range(iter): m2.digest_update(ctx, txt) out = m2.digest_final(ctx) if __name__ == '__main__': profile.run('py_sha(10000)') profile.run('m2_sha(10000)') profile.run('m2_sha_2(10000)') profile.run('m2c_sha(10000)') M2Crypto-0.22.6rc4/demo/pgp/0000775000175000017500000000000012613362233015630 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/pgp/pgpstep.py0000664000175000017500000000574712607370517017710 0ustar matejmatej00000000000000#!/usr/bin/env python """pgpstep - steps through a pgp2 packet stream. Copyright (c) 1999 Ng Pheng Siong. All rights reserved.""" from M2Crypto import PGP, util import time def desc_public_key(pkt): print 'packet = public_key' print 'version =', pkt.version() print 'created = ', time.asctime(time.gmtime(pkt.timestamp())) print 'validity code =', pkt.validity() print 'pkc type =', `pkt.pkc()` #e, n = pkt.pubkey() print 'e =', `pkt._e` print 'n =', `pkt._n` print def desc_trust(pkt): print 'packet = trust' print 'trustworthiness = ' print def desc_userid(pkt): print 'packet = user_id' print 'user_id =', pkt.userid() print def desc_signature(pkt): print 'packet = signature' print 'version =', pkt.version() print 'classification =', `pkt._classification` print 'created = ', time.asctime(time.gmtime(pkt.timestamp())) print 'keyid =', `pkt._keyid` print 'pkc type =', `pkt.pkc()` print 'md_algo =', `pkt._md_algo` print 'md_chksum =', `pkt._md_chksum` print 'sig =', `pkt._sig` print def desc_private_key(pkt): print 'packet = private key' print 'version =', pkt.version() print 'created = ', time.asctime(time.gmtime(pkt.timestamp())) print 'validity code =', pkt.validity() print 'pkc type =', `pkt.pkc()` print 'e =', `pkt._e` print 'n =', `pkt._n` print 'cipher =', `pkt._cipher` if pkt._cipher == '\001': print 'following attributes are encrypted' print 'iv =', `pkt._iv` print 'd =', `pkt._d` print 'p =', `pkt._p` print 'q =', `pkt._q` print 'u =', `pkt._u` print 'checksum =', `pkt._cksum` print def desc_cke(pkt): print 'packet = cke' print 'iv =', `pkt.iv` print 'checksum =', `pkt.cksum` print 'ciphertext =', `pkt.ctxt` print def desc_pke(pkt): print 'packet = pke' print 'version =', pkt.version print 'keyid =', `pkt.keyid` print 'pkc type =', pkt.pkc_type print 'dek =', hex(pkt.dek)[:-1] print def desc_literal(pkt): print 'packet = literal data' print 'mode =', `pkt.fmode` print 'filename =', pkt.fname print 'time = ', time.asctime(time.gmtime(pkt.ftime)) print 'data = <%d octets of literal data>' % (len(pkt.data),) print DESC = { PGP.public_key_packet: desc_public_key, PGP.trust_packet: desc_trust, PGP.userid_packet: desc_userid, PGP.signature_packet: desc_signature, PGP.private_key_packet: desc_private_key, PGP.cke_packet: desc_cke, PGP.pke_packet: desc_pke, PGP.literal_packet: desc_literal, } if __name__ == '__main__': import sys count = 0 for arg in sys.argv[1:]: f = open(arg, 'rb') ps = PGP.packet_stream(f) while 1: pkt = ps.read() if pkt is None: break elif pkt: print '-'*70 DESC[pkt.__class__](pkt) count = count + ps.count() ps.close() print '-'*70 print 'Total octets processed =', count M2Crypto-0.22.6rc4/demo/pgp/pubring.pgp0000664000175000017500000000210012605232411017772 0ustar matejmatej0000000000000028iPH6Nړ[21Ka=b)57X0f9QV!SuEůUN3S5GUv@#dF_H9D~[NY76hoCNV$XFdaft 223a5- d 7x yUTtԔ;JDAMN}> +7VGP=?2WM[) -h{ `5DʤDf:9 fa9>\@# Billy boyL2W salYcomCXyp$gKc,Mկ1v RtN%02zX(͂S٫usilly test this is=2NF0;1H*ۮ!e=zW6Uu+X*\h!Gary Howland L2 sRP M9'B{r<-NF 7Vs+j5S`|W[name=2xѡ^V?B|f_͂ `GOL2 ۽riR 3v# O6H 6[8f|2.'Qsilly test this isL2 _r_W,I$+bI\uCz~h5y&Qb !c8+silly test this is2t펝jwgkf7 4f-KvMķ$V3XO $ֱmTױv eM0 "++ݒma@Fw[A ^`("o: mC($Xښ@yRU Zl跿l"n5i>;`/f'W6ut2(KϻΟHdaft 223a5- d 7x yUTtԔ;JDAMN}> +7VGP=?2WM[) -h{ `5DʤDf:9 fa9>\@#=Ogёvi1r%R[IY.'G un5&Qd|d1U0^ִk⣟XLΘUhSUDz)!:^IVC+fOB PdσwaύxGt֑:oDIL= ƪHпtz}X#ViץBF-)RaQ f%8aQ* :O>h1!U~jrK`O+[",drgmF |·^4 Uڟis`琫:E/g|)w]\|?SeDWx nU Billy boy2o;$/Ea T-.vd>kdmf&nU^˚@ BE<8Q:I!MIl=\37L DK>V7N`q~!o?9AV] ,.y,2Hyfcx'/'3K^BBA qWt\B(O}3X`Ø~I6_e7uo.6oM-c>uUH#L+/?US-~#DQ':d~j5βG6DzM֭]V뎉~P5} cG !=" |Or/5ʭ-5P |̰|ptBns7|cBwv[\+}2c57G-:g aMzCDG*L:`'2 Shʽ%IА@+n" rI(jr UfEJOx7D !N/6.5So-nZU>.&eZtHh[bXT&뙭daftM2Crypto-0.22.6rc4/demo/pkcs7/0000775000175000017500000000000012613362233016071 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/pkcs7/pkcs7-thawte.pem0000664000175000017500000000535112605232411021114 0ustar matejmatej00000000000000-----BEGIN PKCS7----- MIAGCSqGSIb3DQEHAqCAMIIH1wIBATELMAkGBSsOAwIaBQAwgAYJKoZIhvcNAQcB AACgggXgMIICxDCCAi2gAwIBAgIDAphPMA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD VQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRQwEgYDVQQHEwtEdXJiYW52 aWxsZTEPMA0GA1UEChMGVGhhd3RlMR0wGwYDVQQLExRDZXJ0aWZpY2F0ZSBTZXJ2 aWNlczEoMCYGA1UEAxMfUGVyc29uYWwgRnJlZW1haWwgUlNBIDE5OTkuOS4xNjAe Fw0wMDA1MTgxMTA4MTJaFw0wMTA1MTgxMTA4MTJaMGUxETAPBgNVBAQTCFN0cm9l ZGVyMRAwDgYDVQQqEwdNaWNoYWVsMRkwFwYDVQQDExBNaWNoYWVsIFN0cm9lZGVy MSMwIQYJKoZIhvcNAQkBFhRtaWNoYWVsQHN0cm9lZGVyLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAqzxf+ZpWoELOD7sXes/G9O6dSCkGeNL/G5l0k/b4 C9QnZyEh2S0vWI+g43G1uGhu6sgI5Y1SfrG08xGIUEcmexxnl6krTR/QlHr+t9If UXFTmEPAnuIpfPRUqhOQlNFB1DfwKVLb4J3b2947ulv4vpb4owVMC+WjDM5fo765 RXMCAwEAAaNSMFAwHwYDVR0RBBgwFoEUbWljaGFlbEBzdHJvZWRlci5jb20wDAYD VR0TAQH/BAIwADAfBgNVHSMEGDAWgBSIq/Fgg2ZV9ORYx0YdwGG9I9fDjDANBgkq hkiG9w0BAQQFAAOBgQCxx7Uvsnq1F/yOIPiUmlaTXLFAvvTj2trHAF4UFhkQGe6V IBHmDk62H1xJhA4AHNVz3Pe250S8Fu75OgOh2pRJ8KfB6cJU0gxz9ahRt48Qy6+m XUHk9135ru2u8I505nj4i37T6zK3+O/lZU+P79qdPHYwO6dNsYyaRFYLxGyXTjCC AxQwggJ9oAMCAQICAQswDQYJKoZIhvcNAQEEBQAwgdExCzAJBgNVBAYTAlpBMRUw EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy dmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFp bCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhhd3RlLmNv bTAeFw05OTA5MTYxNDAxNDBaFw0wMTA5MTUxNDAxNDBaMIGUMQswCQYDVQQGEwJa QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRQwEgYDVQQHEwtEdXJiYW52aWxsZTEP MA0GA1UEChMGVGhhd3RlMR0wGwYDVQQLExRDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEo MCYGA1UEAxMfUGVyc29uYWwgRnJlZW1haWwgUlNBIDE5OTkuOS4xNjCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEAs2lal9TQFgt6tcVd6SGcI3LNEkxL937Px/vK ciT0QlKsV5Xje2F6F4Tn/XI5OJS06u1lp5IGXr3gZfYZu5R5dkw+uWhwdYQc9BF0 ALwFLE8JAxcxzPRB1HLGpl3iiESwiy7ETfHw1oU+bPOVlHiRfkDpnNGNFVeOwnPl MN5G9U8CAwEAAaM3MDUwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBRy ScJzNMZV9At2coF+d/SH58ayDjANBgkqhkiG9w0BAQQFAAOBgQBrxlnpMfrptuyx A9jfcnL+kWBI6sZV3XvwZ47GYXDnbcKlN9idtxcoVgWL3Vx1b8aRkMZsZnET0BB8 a5FvhuAhNi3B1+qyCa3PLW3Gg1Kb+7v+nIed/LfpdJLkXJeu/H6syg1vcnpnLGtz 9Yb5nfUAbvQdB86dnoJjKe+TCX5V3jGCAdAwggHMAgEBMIGcMIGUMQswCQYDVQQG EwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRQwEgYDVQQHEwtEdXJiYW52aWxs ZTEPMA0GA1UEChMGVGhhd3RlMR0wGwYDVQQLExRDZXJ0aWZpY2F0ZSBTZXJ2aWNl czEoMCYGA1UEAxMfUGVyc29uYWwgRnJlZW1haWwgUlNBIDE5OTkuOS4xNgIDAphP MAkGBSsOAwIaBQCggYowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG 9w0BCQUxDxcNMDAwNzE2MTQ0MzQ0WjAjBgkqhkiG9w0BCQQxFgQU2jmj7l5rSw0y Vb/vlWAYkK/YBwkwKwYJKoZIhvcNAQkPMR4wHDAKBggqhkiG9w0DBzAOBggqhkiG 9w0DAgICAIAwDQYJKoZIhvcNAQEBBQAEgYBagl1y4nRwW+GLhZ5tElkh9Z/yFirz ZXI0jMywML/ADxsAf1yV2JIYCCk0V33QdrYy8MVqgErGXxGdA5aKnm5545Wf4Noz CLWF4FJc6RDSFp7dv2631TrswdFRRCHNds+dvP5v5EAiADvmEOYaDiWM07jp73jx TkkzxW9cevZDaQAAAAA= -----END PKCS7----- M2Crypto-0.22.6rc4/demo/pkcs7/test.py0000664000175000017500000000016712605232411017421 0ustar matejmatej00000000000000from M2Crypto import BIO, SMIME pf = BIO.openfile('pkcs7-thawte.pem') p7 = SMIME.load_pkcs7_bio(pf) print p7.type(1) M2Crypto-0.22.6rc4/demo/smime/0000775000175000017500000000000012613362233016154 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/smime/README0000664000175000017500000000315312605232411017031 0ustar matejmatej00000000000000 29 Nov 2000 ------------- - test.py works. - makesmime.py is sendsmime.py modified to not send SMTP, because I do not now have an SMTP server handy. - sendsmime.py should still work, because makesmime.py does. - unsmime.py doesn't work, possibly because the certificates used to generate the tested PKCS7 objects are no longer available. 20 Nov 2000 ------------- This directory contains various programs and supporting files demonstrating M2Crypto's S/MIME functionality. - test.py exercises the various S/MIME functionality. - sendsmime.py (optionally) signs and/or encrypts a message, then sends the output via SMTP. - makesmime.py is exactly like sendsmime.py, except it writes its output to sys.stdout. - unsmime.py decrypts and verifies an S/MIME SignedAndEnveloped message. It handles the S/MIME output of Netscape Messenger successfully. - ca.pem is M2Crypto's test CA certificate. - client.pem and client2.pem contain user certificates and their corresponding private keys. - clear.p7 is a clear-signed S/MIME message. - opaque.p7 is a signed S/MIME message. - ns.p7 is a clear-signed S/MIME message produced by Messenger. - ns.se.p7 is a signed-then-encrypted S/MIME message produced by Messenger. - m2.se.p7 is a signed-then-encrypted S/MIME message produced by sendsmime.py. I tested with export and strong versions of Netscape Communicator 4.7x. I have also done some interoperability testing with Sampo Kellomaki's smime tool. I am interested in interoperability testing with Outlook and other S/MIME tools. Write me if you want to collaborate. M2Crypto-0.22.6rc4/demo/smime/ca.pem0000664000175000017500000000230412605232411017234 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDWTCCAsKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAxMTIxNTA1NTU0NloXDTA0MTIxNDA1NTU0 NlowgYAxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxML TTJDcnlwdG8gQ0ExJDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3Rl cjEiMCAGCSqGSIb3DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAx8soJbS719LHK62VVVIQeC3oW0HvFArwPnA0LuEK q+LaqMOJg1rS7hvFdX03diV+XJw7cC0iECZYJNG4ii1xbY6KRmufkInaAwm54E3N e+YYVocaqUkcN6xVf6fwnLfPXbpFS/K2Umg11ObKMmi80JmiIdjcjRRCQZC7g1hf q+kCAwEAAaOB4DCB3TAdBgNVHQ4EFgQU6/qcBzEtQphfXLhiOHbt2KqBwMIwga0G A1UdIwSBpTCBooAU6/qcBzEtQphfXLhiOHbt2KqBwMKhgYakgYMwgYAxCzAJBgNV BAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0Ex JDAiBgNVBAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEiMCAGCSqGSIb3 DQEJARYTbmdwc0BuZXRtZW1ldGljLmNvbYIBADAMBgNVHRMEBTADAQH/MA0GCSqG SIb3DQEBBAUAA4GBAD+I14GuS5vJmyv1k7mUMbAicsWRHZ+zrGOq9L/L2LsA+lKQ dAzEZE2+Zv8LBPJVltbJJhcFNJS/ZMAjEm4xlJuCpvXVMxd/M5AM29aqekWlIK7J vsdDL8IuzpRkMniUiNKPhmB6IPIOslvUKx6QofcE0wDh6pg4VvIbCjkpZ7gf -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/smime/clear.p70000664000175000017500000000672112605232411017513 0ustar matejmatej00000000000000To: ngps@post1.com From: ngps@post1.com Subject: testing MIME-Version: 1.0 Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="----F0DD27AD8CDFF9AB55B87EE3A626E6D7" This is an S/MIME signed message ------F0DD27AD8CDFF9AB55B87EE3A626E6D7 S/MIME - Secure Multipurpose Internet Mail Extensions [RFC 2311, RFC 2312] - provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications - authentication, message integrity and non-repudiation of origin (using digital signatures) and privacy and data security (using encryption). S/MIME is built on the PKCS #7 standard. [PKCS7] S/MIME is implemented in Netscape Messenger and Microsoft Outlook. ------F0DD27AD8CDFF9AB55B87EE3A626E6D7 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" MIIHHAYJKoZIhvcNAQcCoIIHDTCCBwkCAQExCzAJBgUrDgMCGgUAMIICQwYJKoZI hvcNAQcBoIICNASCAjANClMvTUlNRSAtIFNlY3VyZSBNdWx0aXB1cnBvc2UgSW50 ZXJuZXQgTWFpbCBFeHRlbnNpb25zIFtSRkMgMjMxMSwgUkZDIDIzMTJdIC0gDQpw cm92aWRlcyBhIGNvbnNpc3RlbnQgd2F5IHRvIHNlbmQgYW5kIHJlY2VpdmUgc2Vj dXJlIE1JTUUgZGF0YS4gQmFzZWQgb24gdGhlDQpwb3B1bGFyIEludGVybmV0IE1J TUUgc3RhbmRhcmQsIFMvTUlNRSBwcm92aWRlcyB0aGUgZm9sbG93aW5nIGNyeXB0 b2dyYXBoaWMNCnNlY3VyaXR5IHNlcnZpY2VzIGZvciBlbGVjdHJvbmljIG1lc3Nh Z2luZyBhcHBsaWNhdGlvbnMgLSBhdXRoZW50aWNhdGlvbiwNCm1lc3NhZ2UgaW50 ZWdyaXR5IGFuZCBub24tcmVwdWRpYXRpb24gb2Ygb3JpZ2luICh1c2luZyBkaWdp dGFsIHNpZ25hdHVyZXMpDQphbmQgcHJpdmFjeSBhbmQgZGF0YSBzZWN1cml0eSAo dXNpbmcgZW5jcnlwdGlvbikuDQoNClMvTUlNRSBpcyBidWlsdCBvbiB0aGUgUEtD UyAjNyBzdGFuZGFyZC4gW1BLQ1M3XQ0KDQpTL01JTUUgaXMgaW1wbGVtZW50ZWQg aW4gTmV0c2NhcGUgTWVzc2VuZ2VyIGFuZCBNaWNyb3NvZnQgT3V0bG9vay4NCqCC AxAwggMMMIICdaADAgECAgECMA0GCSqGSIb3DQEBBAUAMHsxCzAJBgNVBAYTAlNH MREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNV BAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYO bmdwc0Bwb3N0MS5jb20wHhcNMDAwOTEwMDk1ODIwWhcNMDIwOTEwMDk1ODIwWjBZ MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xGDAWBgNVBAMTD00yQ3J5 cHRvIENsaWVudDEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkq hkiG9w0BAQEFAANLADBIAkEAoz3zUF0dmxSU+1fso+eTdmjDY71gWNeXWX28qsBJ 0UFmq4JCtw7Gv4fJ0TZgQHVIrXgKrUvzsquu8eiVjuP/NwIDAQABo4IBBDCCAQAw CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy dGlmaWNhdGUwHQYDVR0OBBYEFMcQhEeJ1x9d+8Rzag9yjCiutYKOMIGlBgNVHSME gZ0wgZqAFPuHI2nrnDqTFeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n cHNAcG9zdDEuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAKy2cWa2BF6cbBPE4ici //wOqkLDbsI3YZyUSj7ZPnefghx9EwRJfLB3/sXEf78OHL7yV6IMrvEVEAJCYs+3 w/lspCMJC0hOomxnt0vjyCCd0JeaEwihQGbOo9V0reXzrUy8yNkwo1w8mMSbIvqh +D5uTB0jKL/ml1EVLw3NJf68MYIBmjCCAZYCAQEwgYAwezELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5u Z3BzQHBvc3QxLmNvbQIBAjAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzELBgkq hkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAyMTIwODE3NTIyMVowIwYJKoZIhvcN AQkEMRYEFI/KcwJXhIg0bRzYLfAtDhxRMzghMFIGCSqGSIb3DQEJDzFFMEMwCgYI KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABEBrhZ8JVqGZ+S7dh+xKDwbF yRXiOQWEa2uxD1O5fD02VfGEzDSrV1sPdQ8AcM3o+ny5AyC11E4Fns2cIkXwZEwz ------F0DD27AD8CDFF9AB55B87EE3A626E6D7-- M2Crypto-0.22.6rc4/demo/smime/client.p120000664000175000017500000000310412605232411017747 0ustar matejmatej000000000000000@0 *H 00 *H 00 *H 0 *H  0zyD06zxu1lK[fSoeEm;E_ R j+%W_ְZXtLo?󭲾nF2 U竜~5= w׍^MBnWVYǝnS|ƣ bV(hA#I'Mc@BF0pdg\ݟ6ƶmPO iR36(gN{1?̒ዟ tD?u*>M@e~'JL_b\K`҅G5mAa~5f+ÆaMӒqrhhuv.#aHwM= kd3êRvC_o·ՊTTbP)TcO } #Ad0(;[e>Yh ,Nݾ^!@Ơ%p)V4,]6bz&叜j%1.9 WBuЎvCҫbf{BS-.\ՓEmo]}5[yyP%%:V_<`)f6 Eǫ9S0nY)_6I!% X-Mailer: Mozilla 4.5 [en] (WinNT; I) X-Accept-Language: en MIME-Version: 1.0 To: ngps@post1.com Subject: S/MIME signing Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------msD996346BF03A805B450DC20D" This is a cryptographically signed message in MIME format. --------------msD996346BF03A805B450DC20D Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit smime -vs- pgp war over? --------------msD996346BF03A805B450DC20D Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIIF8gYJKoZIhvcNAQcCoIIF4zCCBd8CAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC A9cwggPTMIIDPKADAgECAgEDMA0GCSqGSIb3DQEBBAUAMIG3MQswCQYDVQQGEwJTRzEvMC0G A1UEChMmRmFzdCBTZWN1cmUgQ2hlYXAgQ2VydGlmaWNhdGVzIFB0ZSBMdGQxMjAwBgNVBAsT KUZhc3QgU2VjdXJlIENoZWFwIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtG YXN0IFNlY3VyZSBDaGVhcCBLZXlNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEu Y29tMB4XDTk5MDkxNzA1NTAzOFoXDTAwMDkxNjA1NTAzOFowYDELMAkGA1UEBhMCU0cxGDAW BgNVBAoTD00yQ3J5cHRvIENsaWVudDEYMBYGA1UEAxMPTTJDcnlwdG8gQ2xpZW50MR0wGwYJ KoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA vp8eCa+KpzNCv0MWyicUImP+WHxlrxm5EummI1Qe77U4w0k8IQuue7QIURWKDjdZI97izzeQ SozHvgSsjCvuJlqifMoV0v7U4iUQoZkrXO3hzwM5VNr875M95SYeBjqWDUc0v3R6tka3xhg3 dMoEL3QR6gsiardPEwygdL7/FN0CAwEAAaOCAUMwggE/MAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTEHU/WosFL yRo8NT9ViQ8APbKBXTCB5AYDVR0jBIHcMIHZgBQOTokwY/jsgXmHJoyQ5DmTVN0c8KGBvaSB ujCBtzELMAkGA1UEBhMCU0cxLzAtBgNVBAoTJkZhc3QgU2VjdXJlIENoZWFwIENlcnRpZmlj YXRlcyBQdGUgTHRkMTIwMAYDVQQLEylGYXN0IFNlY3VyZSBDaGVhcCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTEkMCIGA1UEAxMbRmFzdCBTZWN1cmUgQ2hlYXAgS2V5TWFzdGVyMR0wGwYJ KoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNvbYIBADANBgkqhkiG9w0BAQQFAAOBgQBN4w1l4IXm DJke8XVyo3SFlre1nL/bjDB+hpYCgTQnceHAmSi6L8FljGs2KYGFePWLSCsOxA99q8lVtl7a sdoOtYkTluccWGqnWloyusOzlO2xgpoQxZ2iue3PT4Y4u8czMTs2AyanZyd6NdQoaYGfI2g0 tpgiDhSqcX8r/JYYVzGCAeMwggHfAgEBMIG9MIG3MQswCQYDVQQGEwJTRzEvMC0GA1UEChMm RmFzdCBTZWN1cmUgQ2hlYXAgQ2VydGlmaWNhdGVzIFB0ZSBMdGQxMjAwBgNVBAsTKUZhc3Qg U2VjdXJlIENoZWFwIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtGYXN0IFNl Y3VyZSBDaGVhcCBLZXlNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tAgED MAkGBSsOAwIaBQCgfTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP Fw0wMDAzMzEwNTExNTJaMB4GCSqGSIb3DQEJDzERMA8wDQYIKoZIhvcNAwICASgwIwYJKoZI hvcNAQkEMRYEFDIu42hsp6w5K/x7ejaVgiqgPYk4MA0GCSqGSIb3DQEBAQUABIGAkipjxn6+ NhIyRPGgrqY9zpDC8AGdt7sGFMKfxhJ+UoSb+lBH0imHSBhA/BnlfysyyDXCpit1Gxy/W/jn vHpI0lMLvvcKOtSQp9HUPAtawdeF6Zau8SovSBroUnxxY7DILJoKnaHheHF7G2MbYusyZCmi r3xZ4P0Ps3fhNEAmrH0= --------------msD996346BF03A805B450DC20D-- M2Crypto-0.22.6rc4/demo/smime/ns.se.p70000664000175000017500000001203312605232411017444 0ustar matejmatej00000000000000MIME-Version: 1.0 Content-Type: application/x-pkcs7-mime; name="smime.p7m" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7m" Content-Description: S/MIME Encrypted Message MIAGCSqGSIb3DQEHA6CAMIACAQAxggKyMIIBVQIBADCBvTCBtzELMAkGA1UEBhMCU0cxLzAt BgNVBAoTJkZhc3QgU2VjdXJlIENoZWFwIENlcnRpZmljYXRlcyBQdGUgTHRkMTIwMAYDVQQL EylGYXN0IFNlY3VyZSBDaGVhcCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMb RmFzdCBTZWN1cmUgQ2hlYXAgS2V5TWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3Qx LmNvbQIBAzANBgkqhkiG9w0BAQEFAASBgERIsZhX2nmvB4kOtcfqUpuWjK9njs8YixtPSS4w ugmAx3LhBMTgY1OlsbKi7etVPwEU2jSqgkwCHPeYeOQt6M9aQ66tcue7/fWjfMBfZ+tetwOb kpqlw//GyjhkJx2QBGPuw3Ye84ll1KA7x/CGxmk8g0YBHoLo9Xy1W1XHVUanMIIBVQIBADCB vTCBtzELMAkGA1UEBhMCU0cxLzAtBgNVBAoTJkZhc3QgU2VjdXJlIENoZWFwIENlcnRpZmlj YXRlcyBQdGUgTHRkMTIwMAYDVQQLEylGYXN0IFNlY3VyZSBDaGVhcCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTEkMCIGA1UEAxMbRmFzdCBTZWN1cmUgQ2hlYXAgS2V5TWFzdGVyMR0wGwYJ KoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNvbQIBBzANBgkqhkiG9w0BAQEFAASBgKFEdyFcaj2z 7LBp/rdEiDRNkyvjZtpEc3F1tvml2jmOuRZq/Gd0Ib4ELmAuC2qZ7AG+MNwlMeCQp1PKGjCk 3Af9hjcOX27c+qF3pSK35WOPrdQTaVLjqdNwejInEoBjGlHa83V1L/MTiD5ABOXGIZKOFS8m G0tPxoc3AhlYbHspMIAGCSqGSIb3DQEHATARBgUrDgMCBwQIvFFOv2EOARiggASBsBBa97DM xPCX8mZ2K/jjVl2LKtBP0uwG+nd48IiaoBERbJohEdzxTlIU3pj+QZ4ktmSSYo/4Os0eSCfK v2mG3d5SPxcE6HztA4FttvQ4IiByTQUU61vJhMoirV5Nvfkxk8i8xPMKMlJSruFBnIOteXQv vwVwBCIAkMhxBE9Sj+OfW5966d+LmB3yGEZa9GEW//4VbR6DNs1frEz7riUod0om5CA66bou 8kXxGTZ5fYydBDDdrsgcU7DBTlw2XayUmYS3Gp0vQvW4l/iiYEeYh+OrKkGYQGdsb5CcZr0F FfT2PRAEICA58XUUrt//zi0TzBTwDKAWoJWe/QfOXXEVQsfqCl1iBBhACmC4JLQRSulBCCpA F3E3daztLz81ycQEIDyHXxMGZFzZQCvy51fN7eRLl+yACoXKxKtVs6EKpJq9BBDDGI8CWqTZ DIMC98l4AV76BIIBAFKj+L6ZG8Sew6IpE5UVq1oS42UrmUDQRrYpZX3OHC8I9pr7mtlU/V0H mA55PmixsjcchT6wOF2wVD9G0rBCOlUfuYNTkhR/k51floP9fk9Oy69+jXxUb7r0AF1M2b13 XQpmnz6YPQPdPxgi8i34iT1oqRY1d4Nntmgl/3xbQ/9MGbgZQSDbduRiy+Zk3JPZzMSVWEVP Pt7anOrPmCKDAvlzpX9yKdyE4Ug68s2///S1JjCjGd65007oPXME3S+7WWylQXdjCe8EM/Li IE33DcRUFvbuo7q1ftxbwRKn32+Z1gkiG4j+DQ4fTO0RrhnTLUpaaOaX4N3psjSA/3Y+vKYE CAkYtbSSwRr5BAhmVVsaf0vm7QQIE77+DXI3Gt0ECIs/MQuPnwd6BAjpq83cshzQ1QQI3Soo r1XwQYIECES6t6POe3yxBAgmObWcpGTawQQI+6e28OKubqkESBlD4aGRdfOXkGSw5zN1pVK0 s37qLWOsO+jClvd4EmfB/JI/ABieNmfBHx2jweIazMA2b9wylRvYp/TMiDFkRl/thDqyj/sC 7QRIypPg5i7a745PX+HcyHhcy5lUxkpnK5pjAAHSUPTXNc/3H6PpU/8+qiPncfqNXVdoiiSa VMSmFMZI+YGDyf4twVuGZbdR5JV2BFCbQNJeSkEhEnZiMKshmNWXbjs4DzYlTO0Pq5D+9RYJ 1iy/kahcms+2nDNlrVf6jH/lCTpPCM/OJWrjaTdpiFzp/eEY39qbWk5AcIFYQ7xIcARIHVPX uhyuO+5BmO0MdMMOL/KlhRtosKHHRG7PH9huyWYFloA4aeoiOxeXkDJk3y0NkG+nJjdM/gWT 1J2HJi8opt0F0bn8t7MsBEgt2VgTZmkHT/yaJDInQEqrpe9PJ412M+2/kXAwt4VfYrEC3ocQ WQuNEpFc1kb6ZGJSYz0TvnW8DbP/GoZqQpF17p1vs1T0QhIESC1qr8SbwXjHjOdAh94Lp5jG b8kAl20P0hqqL+5qq661JzAdGotFN7sMOe07Xn3eaYEVe4htVHlIfYMPH2B0CYyHu9LH2ueG gwRQ7Dv1hygub3ioK/s9CkgAi83qUENz5RWYMtIiP7tbv34zq6DKwv0ioBY4MEKfR4cCuGzS 6I67vTvCgXPVxW9qHtoTTDfufUR6yOOa/gvuZt4ESN3fo5Kgpm+74AMeOVR0RZ1lZ+75E9KV wmiBGm5ORHGSmyt3MQMW+5UEloz8mxK39O6RtKBL7iKH3d0clJn63KXvUsf2l7/8swRIIVzc 1jGzpwOsUseKHaeLQuknjTuXAlyCTQYa3C0gEcEBElJY/TMevV+ZrlBB/nCwyaYbmH+WxxfQ +xF79+eIZ1+L5zGAlSNUBEhO1Gy1T77JUa+s4UUqGP+BNNsGDuR4YXWfCIA2vBfCFZVggkaD v1+uX2Rgim39wzMCLkXQ8ZXLWdWo7/XcllOrxJSH84uPat8EULZTtkbY1oW90JzGEJKbOkEA YaoQ7I0dKXnkLsY3Y54p1WW7fPQ4JLLhld2LpmZbYOntRJmn8LZWGWv9J3uYlAk9ujAfF10f 7/qV2zDB//oKBEih8QUPicP+mSdpvRlws5RfiKmcf9W7btoNALqqA2COEOHjjJHdX9b3EVlk vftz5n2AbaS7fenhIl1/rbhmBfub3eHwmInRoUEESHcpUKHCEe3dtGe6vB2VXR4U/MvKScZV RpHv6KGj0pFZwNasoZ9W5RB0dwAbhuD+xiimlv/m9XwhIQihgTUmarVdEbYcbl1aHgRIFMEp bOJ4D49qYR9DXZprlST9nZTgU/R1KTcZe2LsXBNa9xxlO9NYvZCSQSuRndIIwbAXjgezK1d0 fk+JSIyC8kaQzWBwDGdXBFDA3tUZzKed3JM+R/a8319iAemyyYgvk/izKKXncpOfCdBtVgHc cOC7LPs1BGxqGCyOzgD2KMQSclRZJo+siuRvJ2wlKCPjd3DHMk0IJ6EYWgRI3XuDbhKfLzEQ h9G5n3wQr8qizabBZ+xZEmJk7AUxA7ykEdSuLlV7qP/ujj9sZ9e/AaHG+mfjGRI01OPquZxW Pwt9nRpg1KqCBEjFQqB+hbkfT218E5+mFX/aotUq+tEoZ1Tg3Lq5WENZVwMNR0eFR69vN+gL SZU3nnLPEchS3pasz7ZBohL+kEBad4fZfKNWUa4ESO9adCvusxTvjlvf8Gu/lXU17gZuAHsj bMwSWyQeZKObCp7kOtK1nQCtLHkWHEpmx16eQWG57+makKYpjD4BSXFXGEwMf3Pw9AQQd6Po 6JLMr7k5LjkOcyCe/gQIJ2ORlLJDWKMECHz5jFYLkHrLBAhPDugA9fP+MgQIQq/w/QD4YBIE CGeYC0G4o7ElBAj3O1FpJvdU+wQIiOZHO6By7rAECN9TZKOJa8YbBDD/7QgWqJSNhck7fNEY tHmopW9OWfXfXUInzaQFBtLauNRj0C2OW/zB5dgsC3+9/jYECG3bevzH5HiDBBBHiuTo8yYJ 1FFJ/y4nIIXaBDC92swMrVUYZUpoNUjf02DsBiVP53Fon+CnKnEQ8gBCncIkb8DBnlZYeZd2 XISBWmEECNOMqXZKxL2vBBDDg2nHASKLEobcHqmPoIQFBBhcrb6prkWNKColNlf5ss49ocnK 68UgsNEECNJJEPZOUMW1BBApQ6CzF2t+QiJTdQwoApPzBBg8ZCeSHgypK9CWcWb2iMWiFuKc KUmIuskECFr2TQ/U6cWbBAisYHDp2/w4kgQISMieG/GdQlAEEGLN6GdGVz2wf1Hx93PJ4VsE EJRdLeaU3FsCwXEICvSKZPMEEIcEdqQkAhmsxfNoKA90QlUECDdUY0tvC48sBBBNOevphvxS 0dwE2Lzf6gLGBAjoSuhhSYuZBAQIRKWk1TxshoAECFUuzdHGuR3zBBjlvJQjSDrEPqg7unh2 ZaNy11cUKB07vPMECIbZbuiAcb81BBCyb6N/Aymqo24VwyE9/lTDBCCR0Sn7D8OfmpwUp0MJ zEdp+4eTPVu9W6bNj5cTwcG0VQQI9Z1/nYjZ93cECCZ7u+8p0rP8BAg6S5MaaL8mTQQIMt+W TF2XgOMEQLOZQ0FOc4oD9mBoXzN/NDmlEz0QWnZPnO/7OhVcuKPi6rtE+5RfdGDL/qxWGU6G 0qvFT0zTodnwjpzKnYAnoeMEUDPxz4djUsMXhHzpye9vc7N2/B8QUBubRaFPp/FoLv3jjwga +AawOtkkW1uLku0m6zdN7YYzXTsKlMhwDd3nZS4Vm/v11AnFChiDC2LFmLw0BCC/X36boypP pTObDByKlN6IldnnPEi4tl/6Cxr2+28LWgQohCdg9nl3s5COEnwQW+ggcvKodHHK9SdVRscS J4ykS0lWZ0ns4/g6/wQIKIXduWxdKJMAAAAAAAAAAAAA M2Crypto-0.22.6rc4/demo/smime/opaque.p70000664000175000017500000000520512605232411017713 0ustar matejmatej00000000000000To: ngps@post1.com From: ngps@mpost1.com Subject: testing MIME-Version: 1.0 Content-Disposition: attachment; filename="smime.p7m" Content-Type: application/x-pkcs7-mime; name="smime.p7m" Content-Transfer-Encoding: base64 MIIHHAYJKoZIhvcNAQcCoIIHDTCCBwkCAQExCzAJBgUrDgMCGgUAMIICQwYJKoZI hvcNAQcBoIICNASCAjANClMvTUlNRSAtIFNlY3VyZSBNdWx0aXB1cnBvc2UgSW50 ZXJuZXQgTWFpbCBFeHRlbnNpb25zIFtSRkMgMjMxMSwgUkZDIDIzMTJdIC0gDQpw cm92aWRlcyBhIGNvbnNpc3RlbnQgd2F5IHRvIHNlbmQgYW5kIHJlY2VpdmUgc2Vj dXJlIE1JTUUgZGF0YS4gQmFzZWQgb24gdGhlDQpwb3B1bGFyIEludGVybmV0IE1J TUUgc3RhbmRhcmQsIFMvTUlNRSBwcm92aWRlcyB0aGUgZm9sbG93aW5nIGNyeXB0 b2dyYXBoaWMNCnNlY3VyaXR5IHNlcnZpY2VzIGZvciBlbGVjdHJvbmljIG1lc3Nh Z2luZyBhcHBsaWNhdGlvbnMgLSBhdXRoZW50aWNhdGlvbiwNCm1lc3NhZ2UgaW50 ZWdyaXR5IGFuZCBub24tcmVwdWRpYXRpb24gb2Ygb3JpZ2luICh1c2luZyBkaWdp dGFsIHNpZ25hdHVyZXMpDQphbmQgcHJpdmFjeSBhbmQgZGF0YSBzZWN1cml0eSAo dXNpbmcgZW5jcnlwdGlvbikuDQoNClMvTUlNRSBpcyBidWlsdCBvbiB0aGUgUEtD UyAjNyBzdGFuZGFyZC4gW1BLQ1M3XQ0KDQpTL01JTUUgaXMgaW1wbGVtZW50ZWQg aW4gTmV0c2NhcGUgTWVzc2VuZ2VyIGFuZCBNaWNyb3NvZnQgT3V0bG9vay4NCqCC AxAwggMMMIICdaADAgECAgECMA0GCSqGSIb3DQEBBAUAMHsxCzAJBgNVBAYTAlNH MREwDwYDVQQKEwhNMkNyeXB0bzEUMBIGA1UECxMLTTJDcnlwdG8gQ0ExJDAiBgNV BAMTG00yQ3J5cHRvIENlcnRpZmljYXRlIE1hc3RlcjEdMBsGCSqGSIb3DQEJARYO bmdwc0Bwb3N0MS5jb20wHhcNMDAwOTEwMDk1ODIwWhcNMDIwOTEwMDk1ODIwWjBZ MQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xGDAWBgNVBAMTD00yQ3J5 cHRvIENsaWVudDEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkq hkiG9w0BAQEFAANLADBIAkEAoz3zUF0dmxSU+1fso+eTdmjDY71gWNeXWX28qsBJ 0UFmq4JCtw7Gv4fJ0TZgQHVIrXgKrUvzsquu8eiVjuP/NwIDAQABo4IBBDCCAQAw CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy dGlmaWNhdGUwHQYDVR0OBBYEFMcQhEeJ1x9d+8Rzag9yjCiutYKOMIGlBgNVHSME gZ0wgZqAFPuHI2nrnDqTFeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n cHNAcG9zdDEuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAKy2cWa2BF6cbBPE4ici //wOqkLDbsI3YZyUSj7ZPnefghx9EwRJfLB3/sXEf78OHL7yV6IMrvEVEAJCYs+3 w/lspCMJC0hOomxnt0vjyCCd0JeaEwihQGbOo9V0reXzrUy8yNkwo1w8mMSbIvqh +D5uTB0jKL/ml1EVLw3NJf68MYIBmjCCAZYCAQEwgYAwezELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5u Z3BzQHBvc3QxLmNvbQIBAjAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzELBgkq hkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAyMTIwODE3NTIyMVowIwYJKoZIhvcN AQkEMRYEFI/KcwJXhIg0bRzYLfAtDhxRMzghMFIGCSqGSIb3DQEJDzFFMEMwCgYI KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABEBrhZ8JVqGZ+S7dh+xKDwbF yRXiOQWEa2uxD1O5fD02VfGEzDSrV1sPdQ8AcM3o+ny5AyC11E4Fns2cIkXwZEwz M2Crypto-0.22.6rc4/demo/smime/sendsmime.py0000664000175000017500000000503412611255457020523 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME sender. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 import smtplib, string, sys def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'): msg_bio = BIO.MemoryBuffer(msg) sign = from_key encrypt = to_certs s = SMIME.SMIME() if sign: s.load_key(from_key, from_cert) if encrypt: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) else: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT|SMIME.PKCS7_DETACHED) msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. if encrypt: sk = X509.X509_Stack() for x in to_certs: sk.push(X509.load_cert(x)) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('rc2_40_cbc')) tmp_bio = BIO.MemoryBuffer() if sign: s.write(tmp_bio, p7) else: tmp_bio.write(msg) p7 = s.encrypt(tmp_bio) out = BIO.MemoryBuffer() out.write('From: %s\r\n' % from_addr) out.write('To: %s\r\n' % string.join(to_addrs, ", ")) out.write('Subject: %s\r\n' % subject) if encrypt: s.write(out, p7) else: if sign: s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) else: out.write('\r\n') out.write(msg) out.close() smtp = smtplib.SMTP() smtp.connect(smtpd) smtp.sendmail(from_addr, to_addrs, out.read()) smtp.quit() # XXX Cleanup the stack and store. msg = """ S/MIME - Secure Multipurpose Internet Mail Extensions [RFC 2311, RFC 2312] - provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications - authentication, message integrity and non-repudiation of origin (using digital signatures) and privacy and data security (using encryption). S/MIME is built on the PKCS #7 standard. [PKCS7] S/MIME is implemented in Netscape Messenger and Microsoft Outlook. """ if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) sendsmime(from_addr = 'ngps@post1.com', to_addrs = ['jerry','ngps@post1.com'], subject = 'S/MIME testing', msg = msg, from_key = 'client2.pem', #from_key = None, #to_certs = None) to_certs = ['client.pem']) Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/smime/test.py0000664000175000017500000001103012611255457017507 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME demo. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 ptxt = """ S/MIME - Secure Multipurpose Internet Mail Extensions [RFC 2311, RFC 2312] - provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications - authentication, message integrity and non-repudiation of origin (using digital signatures) and privacy and data security (using encryption). S/MIME is built on the PKCS #7 standard. [PKCS7] S/MIME is implemented in Netscape Messenger and Microsoft Outlook. """ def makebuf(): buf = BIO.MemoryBuffer(ptxt) return buf def sign(): print 'test sign & save...', buf = makebuf() s = SMIME.SMIME() s.load_key('client.pem') p7 = s.sign(buf, SMIME.PKCS7_DETACHED) out = BIO.openfile('clear.p7', 'w') out.write('To: ngps@post1.com\n') out.write('From: ngps@post1.com\n') out.write('Subject: testing\n') buf = makebuf() # Recreate buf, because sign() has consumed it. s.write(out, p7, buf) out.close() buf = makebuf() p7 = s.sign(buf) out = BIO.openfile('opaque.p7', 'w') out.write('To: ngps@post1.com\n') out.write('From: ngps@mpost1.com\n') out.write('Subject: testing\n') s.write(out, p7) out.close() print 'ok' def verify_clear(): print 'test load & verify clear...', s = SMIME.SMIME() x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('ca.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7('clear.p7') v = s.verify(p7, data) if v: print 'ok' else: print 'not ok' def verify_opaque(): print 'test load & verify opaque...', s = SMIME.SMIME() x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('ca.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7('opaque.p7') v = s.verify(p7, data) if v: print 'ok' else: print 'not ok' def verify_netscape(): print 'test load & verify netscape messager output...', s = SMIME.SMIME() #x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() #sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('ca.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7('ns.p7') v = s.verify(p7, data) print '\n', v, '\n...ok' def sv(): print 'test sign/verify...', buf = makebuf() s = SMIME.SMIME() # Load a private key. s.load_key('client.pem') # Sign. p7 = s.sign(buf, SMIME.PKCS7_DETACHED) # Output the stuff. buf = makebuf() # Recreate buf, because sign() has consumed it. bio = BIO.MemoryBuffer() s.write(bio, p7, buf) # Plumbing for verification: CA's cert. st = X509.X509_Store() st.load_info('ca.pem') s.set_x509_store(st) # Plumbing for verification: Signer's cert. x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Verify. p7, buf = SMIME.smime_load_pkcs7_bio(bio) v = s.verify(p7, buf, flags=SMIME.PKCS7_DETACHED) if v: print 'ok' else: print 'not ok' def ed(): print 'test encrypt/decrypt...', buf = makebuf() s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Add a cipher. s.set_cipher(SMIME.Cipher('bf_cbc')) # Encrypt. p7 = s.encrypt(buf) # Load target's private key. s.load_key('client.pem') # Decrypt. data = s.decrypt(p7) if data: print 'ok' else: print 'not ok' def zope_test(): print 'test zophistry...' f = open('client.pem') cert_str = f.read() key_bio = BIO.MemoryBuffer(cert_str) cert_bio = BIO.MemoryBuffer(cert_str) # XXX Kludge. s = SMIME.SMIME() s.load_key_bio(key_bio, cert_bio) # XXX unfinished... def leak_test(): # Seems ok, not leaking. while 1: ed() #sv() if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) ed() sign() verify_opaque() verify_clear() #verify_netscape() sv() #zope_test() #leak_test() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/smime/unsmime.py0000664000175000017500000000234612607370517020217 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME demo. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 import sys def decrypt_verify(p7file, recip_key, signer_cert, ca_cert): s = SMIME.SMIME() # Load decryption private key. s.load_key(recip_key) # Extract PKCS#7 blob from input. p7, bio = SMIME.smime_load_pkcs7_bio(p7file) # Decrypt. data = s.decrypt(p7) # Because we passed in a SignAndEnveloped blob, the output # of our decryption is a Signed blob. We now verify it. # Load the signer's cert. sk = X509.X509_Stack() s.set_x509_stack(sk) # Load the CA cert. st = X509.X509_Store() st.load_info(ca_cert) s.set_x509_store(st) # Verify. p7, bio = SMIME.smime_load_pkcs7_bio(BIO.MemoryBuffer(data)) if bio is not None: # Netscape Messenger clear-signs, when also encrypting. data = s.verify(p7, bio) else: # M2Crypto's sendsmime.py opaque-signs, when also encrypting. data = s.verify(p7) print data if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) decrypt_verify(BIO.File(sys.stdin), 'client.pem', 'client2.pem','ca.pem') Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/smime.howto/0000775000175000017500000000000012613362233017313 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/smime.howto/README0000664000175000017500000000011412605232411020162 0ustar matejmatej00000000000000 01 Apr 2001 ------------- These are the example programs from the HOWTO. M2Crypto-0.22.6rc4/demo/smime.howto/decrypt.py0000664000175000017500000000063512607370517021352 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, SMIME, X509 # Instantiate an SMIME object. s = SMIME.SMIME() # Load private key and cert. s.load_key('recipient_key.pem', 'recipient.pem') # Load the encrypted data. p7, data = SMIME.smime_load_pkcs7('encrypt.p7') # Decrypt p7. out = s.decrypt(p7) print out M2Crypto-0.22.6rc4/demo/smime.howto/dv.py0000664000175000017500000000174212607370517020311 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, SMIME, X509 # Instantiate an SMIME object. s = SMIME.SMIME() # Load private key and cert. s.load_key('recipient_key.pem', 'recipient.pem') # Load the signed/encrypted data. p7, data = SMIME.smime_load_pkcs7('se.p7') # After the above step, 'data' == None. # Decrypt p7. 'out' now contains a PKCS #7 signed blob. out = s.decrypt(p7) # Load the signer's cert. x509 = X509.load_cert('signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Load the signer's CA cert. In this case, because the signer's # cert is self-signed, it is the signer's cert itself. st = X509.X509_Store() st.load_info('signer.pem') s.set_x509_store(st) # Recall 'out' contains a PKCS #7 blob. # Transform 'out'; verify the resulting PKCS #7 blob. p7_bio = BIO.MemoryBuffer(out) p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) v = s.verify(p7) print v M2Crypto-0.22.6rc4/demo/smime.howto/encrypt.p70000664000175000017500000000126112605232411021242 0ustar matejmatej00000000000000From: sender@example.dom To: recipient@example.dom MIME-Version: 1.0 Content-Disposition: attachment; filename="smime.p7m" Content-Type: application/x-pkcs7-mime; name="smime.p7m" Content-Transfer-Encoding: base64 MIIBVwYJKoZIhvcNAQcDoIIBSDCCAUQCAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ KoZIhvcNAQEBBQAEgYCdBULuQ/kfjgk17dMwBHdY+vXfqR/B+vJnF0gXhK6gc5d4 gCkRefEyVu7lGAD2MOdD0cOLFvHdmGHFJqyJ8T+A1mmqrxMAiJImtqN586YnoTUb Cw5FaMEd20d6hpGeEVBFHkam0vQKdR1GLG1VPiFn+ytB06g7NNphsI5/uFGyLDA7 BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECPfuW3hoPVr0gBiA4CiFG4m74CT4wHPu q1fhEkG3zjraxn4= M2Crypto-0.22.6rc4/demo/smime.howto/encrypt.py0000664000175000017500000000166412607370517021367 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 def makebuf(text): return BIO.MemoryBuffer(text) # Make a MemoryBuffer of the message. buf = makebuf('a sign of our times') # Seed the PRNG. Rand.load_file('randpool.dat', -1) # Instantiate an SMIME object. s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert('recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Encrypt the buffer. p7 = s.encrypt(buf) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: sender@example.dom\n') out.write('To: recipient@example.dom\n') out.write('Subject: M2Crypto S/MIME testing\n') s.write(out, p7) print out.read() # Save the PRNG's state. Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/smime.howto/recipient.pem0000664000175000017500000000210212605232411021766 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIC9zCCAmCgAwIBAgIBADANBgkqhkiG9w0BAQQFADBhMQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xGTAXBgNVBAMTEFMvTUlNRSBSZWNpcGllbnQxJDAi BgkqhkiG9w0BCQEWFXJlY2lwaWVudEBleGFtcGxlLmRvbTAeFw0wMTAzMzExMTQy MTVaFw0wMjAzMzExMTQyMTVaMGExCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNy eXB0bzEZMBcGA1UEAxMQUy9NSU1FIFJlY2lwaWVudDEkMCIGCSqGSIb3DQEJARYV cmVjaXBpZW50QGV4YW1wbGUuZG9tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB gQDQwLwQSshbTn/GUZXnZUQEUDc61OUd+qcPpHfi76Y7ar+2NwsalQ3bu2i7edEK IZZWMFRnrOwE9PhmJHJIzfYDswgpHWtRy0P/Oyzt5kLBjvJYuMIqu8gZtWFz0G28 Q8tGvIuPdWba+9TT3LOv4CXNF1V0k0KgAPd1Uq2FUcBa2QIDAQABo4G+MIG7MB0G A1UdDgQWBBQe7b4CDEBuMJyiscil27YBdZBr9zCBiwYDVR0jBIGDMIGAgBQe7b4C DEBuMJyiscil27YBdZBr96FlpGMwYTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y Q3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBpZW50MSQwIgYJKoZIhvcNAQkB FhVyZWNpcGllbnRAZXhhbXBsZS5kb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG 9w0BAQQFAAOBgQAJbQXzP7AK9u2kyvl8oeZAeJQDRsip4PVMkYd64HW3Hq/9ud3g hj/laeUyfcga+c1c1yPUug5Ab+loeHhEEKsL9LqYFXzpFU1lXaID02zcqG7g3PWe r9RKsUqrn4ZbRQ+clidnIx4nYLuG6CPQ6ME/uFrYHMsmQEO/+KoJONf/cg== -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/smime.howto/recipient_key.pem0000664000175000017500000000156712605232411022654 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDQwLwQSshbTn/GUZXnZUQEUDc61OUd+qcPpHfi76Y7ar+2Nwsa lQ3bu2i7edEKIZZWMFRnrOwE9PhmJHJIzfYDswgpHWtRy0P/Oyzt5kLBjvJYuMIq u8gZtWFz0G28Q8tGvIuPdWba+9TT3LOv4CXNF1V0k0KgAPd1Uq2FUcBa2QIDAQAB AoGAVOMrFozycH65YtHmXVRGlmJwMxJDoS8+JBRDVBsTw/Gix9wWPdcC7amF60ac BLynv6Cjkg01ZMahBBgqCQUH1rii6Kg20MJJtpqvt1X+CAZkytVsQqwutSQXHj+g TzZVDxQiuPKMyVhKTSVqutqs2EyFgSKcYuodfms5xDk2EyECQQD6vnEAl2PHBoia 5wrauujbWTM6H5oioWvJgLaUNgUhJ86/Y+ewKoGxLdYaxx99KhKxN/04i2chIHk0 c53THOt9AkEA1SD1Rdm93FUMEor+BYEQgiN/4pWnSIsgUjyqV7lPv9QegdDTbVfm WuPNev6Z+qo9mpDWbvhCZhH159q7uGfzjQJAe88dLRWThuqK+TGsAmTYJbbdvI1u JjteZZjQjk4+KijlxUsnU60pbLsdRQudWMg1gpwKxKjQu2K1dljATUWyYQJARI83 l2K1+py5J3XixS6BevukdeUiTOnEWe/98/4+szyvG59rg+8UwQQq43fnXIVLD9+r u0LNSTxZ2F26qVV3OQJBAIBG0Gv9C44UlCPiJhmMqcpzexX20erOEGu+UiCUhHAC ZdWdFaD2dlmk0O/E82LxPPivkGv5DtkNpzCl+3Vo+kI= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/smime.howto/se.p70000664000175000017500000000627412605232411020176 0ustar matejmatej00000000000000From: sender@example.dom To: recipient@example.dom MIME-Version: 1.0 Content-Disposition: attachment; filename="smime.p7m" Content-Type: application/x-pkcs7-mime; name="smime.p7m" Content-Transfer-Encoding: base64 MIIIwwYJKoZIhvcNAQcDoIIItDCCCLACAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ KoZIhvcNAQEBBQAEgYCn4qL7Z8QlmVEMbO2zU5RUtBqw1cYPzxd/4ZF9H+djlL7f EDIYHidvTBksXwcBXSTxsKsSusGF95NtwaZf4D3eiR1ChdkeXaiWCUPAQr0Mw4+A EJa9eGBuLH+LXH0pDN5OhYb8hsL/EcV2OpOEjOe4aM/u3Ot5u1kK1582oikhCDCC B6UGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQImrxQEPwEHHeAggeACeVVKqKjySva zos9ahumXC7bMIcfesxQF0L2CcR4wQtnwuzESXNAnQabtlN6cXKLNFGWmilztaEZ zHFEEDqtqEeP5BmEkjnNFakhr49yrK/SZpVYYScsUHNcMDOwXMPKKxkk3qOKUlqQ m+WvvyaWwZ8kbZNkO+YY4BpOVDEQRH3HG7ngtLP3y/LSx7kcpTl0wi8On9pigZ46 4u9Odac7bNh5FVMOFiXbIXMuFJ1epy9agtX09eOK9JC9ZHnIl9IgGEL833d+l8MQ OdeKqvSTnNf0JKZs52uzUqluI4pywNIiJT1OeU3Ch2vdfvcOcTQohGhIEUb7NWEn Z02pBiZ0Tzg/T/sr8B60rPcRSSnGYAfQZPS86QgAMIEaqoHQVox+Qgigr2dynvWQ KO0ny4iJLhtRoxD7W7LxaZat6fWvbC4WXKwgis2UJnEWwe8DsoZ3XEnYid3ke2/F 2+ejHtugd6E4o05vRAO/pOVZUbc4mbZm2zoPgzwm0M9GqQcTOVy1tkpEc6mhrH6y AjbSeP/1YkZakDB9bl+TCw24lRquIUbGyNI9GM+oFYyciIYu6RfPhfoh9YU9wqS7 KcnHk3WG5AxJZ6tZAsz/i/DhtD5zxFsldKMy5OaeBjh6txmQ0aHXPYLmIEdxPSa0 BnrAeTam/1iOboXT1O2GkPiLJAJjWRAvK/QXsxJMGtSYEnwT+kkAZtU75FOyBuxI gQOHO98CGGEy5CI/e/Th+1yMqyiimqDmfVktN4KgzZXbjyv4xzpgNE6o85v7fUg1 1WoTF38GmbcIbVfBHaRwdWmSxeAsFltHb38u7pP8D24+3hC5OKsNLXxGFJhfp3HW 4A51fNAi3CaWIh9aZb+SYof8MmtZp9mjL0dKB1OZTyTXqkQ/yU3PIHE+ytM6men3 tzQefsJlnk/t/zBhxdZo+yCna/ZJe3KmrShoD4ob9prWs48ohDhG7cY4vfW0NuxX Im30y+JZe3A0Ktamq1VmpWDhW6Emo+Wk04nDTtU2AcClMoKWgcvIUp0HAgWDhrrx 6Rf1CiRZngJuCEheCMAvKT8IgcTt7vWRUpRoJrhlKR23GKEVA6T6DF9q8L4F82ul yzQ2kdec6s8bD1EQT7e0QcIqEn8RNoSa2aLxRG2JBWqv0AZflKyCjwx35mCv7AmN 17zPENkGdDgE9xcEEdEe4rkigJ8uaYauEofQsDgSHWQ2oAk91g5FLNImsRn3Z7uy qtjc9JTXOymowDXbdYebqNZTxJhXDUnrbawWqyCgohtytnVdW61wKsXV3oEp7PZc aL0ZZvVkVkUofaf/2gIGvQ9WnTfpUJ/bEAr0hDdtnmg1QPVu/v/l9eXAnbkh71GX OdFpIfvf0zVm/tn/7Vi+HfHRjupHSJBO+bIVQBt3uMLlovU48axSRXUnpIXdHYwN 3b/MabDQnzV1qvhGTRRj+o39RbDrueNSpXIleA7SzFqZO2LnaDZ/FKbca1CAL+Iy KsByJUz7cReE4gU8N3SKKv7ivaibmFG63cvwA1GMUsWZgIYD/xy2nCB4jPCodiFB wWUgAblxMcaidKox6Z1zK9oZA62QIX4XGl+0mE/xwxmt2fE5lSBhY8q7N7MvS/Nv RDLEgULBMRvcjgIwL4MZZYkUl7oAqQ2aHL45j7vp7U9vIK2j8bcp9v5K3jeccENJ qYn/35awflQ66lrrSUWH3evs5IO0FhKSn9c1GGTaZDA5TABzJKySmvphyAh1m24W ylzgXQkp/Zi2oWajZ50txiIBgB14dWhuCS4vcwkWjyKur/yGpkY5DILSHZyguqDk cwOgKRrC5myL7Zr0/5CwN6sBofOGb2Qhcx+4Cg6DnPwyMXKVTKYnXPvcTj2KvVW+ qzTIhur0rwC13lK1+sMs/+Esel99fohCTz7+tiebqkPaFcnx8hUgMrllYfGCMXQ/ hiY+1BVEyDWHWOjj5lxPwzNtPqbVz3uA//Rut/BozOpD/hEjCMVRbadSFZTM+x6+ nr39DHGZsOn3XSEZSU2C93v77Ls/vdJi6IdJTwCD/yoEK1OY60ciBvCpJ/lLVSQl PAdozKEAjqP+fX95MeAENtysXTsqbWawWeS7H/zXmwpWn3LnSJ48pymvwV6nJrYL YXHaiuMGIZim9jOT04AyK5LPZ2E9omwVFaHgi10iRigc9y5MixHvN9P5WQ9nP+/c kflFQXuph3RqBEWfG8vPFKFvqVQTN0lxUXoOXkKhZ7/Doe3orbfRw/xZUyKnfrzs O7MU7PVAubVNUXjKHs2UCYtVMUH0tSuDMkuWUd6d6cmkPht86KvopoXha6zRw1pu SE/nGq/o6bproWMPRfoCCN+xow9jeipTD7xkYbiw1+g/9hYaqUYm7QUbuYOrBtLe RAlm69yornWrh7+n3GXUSCFQz3nj6sE4JjXciQzhUfEFrCn+qDrgaviFKe0yVYbQ LRr3qtSM0gTVWn2XnOlnNuLdvx2UWV7KNNPrnRIoK3KvnfOJTl/RzkT1g+HaEvC3 MFNlSJNXN6Gavdr8pAdtnVGivdnM1iw0yFKuuzoF1F+cuN8rGMmp M2Crypto-0.22.6rc4/demo/smime.howto/se.py0000664000175000017500000000227412607370517020310 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 def makebuf(text): return BIO.MemoryBuffer(text) # Make a MemoryBuffer of the message. buf = makebuf('a sign of our times') # Seed the PRNG. Rand.load_file('randpool.dat', -1) # Instantiate an SMIME object. s = SMIME.SMIME() # Load signer's key and cert. Sign the buffer. s.load_key('signer_key.pem', 'signer.pem') p7 = s.sign(buf) # Load target cert to encrypt the signed message to. x509 = X509.load_cert('recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Create a temporary buffer. tmp = BIO.MemoryBuffer() # Write the signed message into the temporary buffer. s.write(tmp, p7) # Encrypt the temporary buffer. p7 = s.encrypt(tmp) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: sender@example.dom\n') out.write('To: recipient@example.dom\n') out.write('Subject: M2Crypto S/MIME testing\n') s.write(out, p7) print out.read() # Save the PRNG's state. Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/smime.howto/sendsmime.py0000664000175000017500000000504412611255457021663 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME sender. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME, X509 import smtplib, string, sys def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'): msg_bio = BIO.MemoryBuffer(msg) sign = from_key encrypt = to_certs s = SMIME.SMIME() if sign: s.load_key(from_key, from_cert) if encrypt: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) else: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT|SMIME.PKCS7_DETACHED) msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. if encrypt: sk = X509.X509_Stack() for x in to_certs: sk.push(X509.load_cert(x)) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('rc2_40_cbc')) tmp_bio = BIO.MemoryBuffer() if sign: s.write(tmp_bio, p7) else: tmp_bio.write(msg) p7 = s.encrypt(tmp_bio) out = BIO.MemoryBuffer() out.write('From: %s\r\n' % from_addr) out.write('To: %s\r\n' % string.join(to_addrs, ", ")) out.write('Subject: %s\r\n' % subject) if encrypt: s.write(out, p7) else: if sign: s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) else: out.write('\r\n') out.write(msg) out.close() smtp = smtplib.SMTP() smtp.connect(smtpd) smtp.sendmail(from_addr, to_addrs, out.read()) smtp.quit() # XXX Cleanup the stack and store. msg = """ S/MIME - Secure Multipurpose Internet Mail Extensions [RFC 2311, RFC 2312] - provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications - authentication, message integrity and non-repudiation of origin (using digital signatures) and privacy and data security (using encryption). S/MIME is built on the PKCS #7 standard. [PKCS7] S/MIME is implemented in Netscape Messenger and Microsoft Outlook. """ if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) sendsmime(from_addr = 'ngps@post1.com', to_addrs = ['popuser@nova.dyndns.org'], subject = 'S/MIME testing', msg = msg, #from_key = 'signer.pem', from_key = None, #to_certs = None) to_certs = ['recipient.pem']) Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/smime.howto/sign.p70000664000175000017500000000435712605232411020527 0ustar matejmatej00000000000000From: sender@example.dom To: recipient@example.dom Subject: M2Crypto S/MIME testing MIME-Version: 1.0 Content-Type: multipart/signed ; protocol="application/x-pkcs7-signature" ; micalg=sha1 ; boundary="----2221986D060512556B8AC18AAA106F39" This is an S/MIME signed message ------2221986D060512556B8AC18AAA106F39 a sign of our times ------2221986D060512556B8AC18AAA106F39 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" MIIE8AYJKoZIhvcNAQcCoIIE4TCCBN0CAQExCzAJBgUrDgMCGgUAMCIGCSqGSIb3 DQEHAaAVBBNhIHNpZ24gb2Ygb3VyIHRpbWVzoIIC5zCCAuMwggJMoAMCAQICAQAw DQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRYwFAYDVQQDEw1TL01JTUUgU2VuZGVyMSEwHwYJKoZIhvcNAQkBFhJzZW5kZXJA ZXhhbXBsZS5kb20wHhcNMDEwMzMxMTE0MDMzWhcNMDIwMzMxMTE0MDMzWjBbMQsw CQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBT ZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbTCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEA5c5Tj1CHTSOxa1q2q0FYiwMWYHptJpJcvtZm UwrgU5sHrA8OnCM0cDXEj0KPf3cfNjHffB8HWMzI4UEgNmFXQNsxoGZ+iqwxLlNj y9Mh7eFW/Bjq5hNXbouSlQ0rWBRkoxV64y+t6lQehb32WfYXQbKFxFJSXzSxOx3R 8YhSPd0CAwEAAaOBtjCBszAdBgNVHQ4EFgQUXOyolL1t4jaBwZFRM7MS8nBLzUow gYMGA1UdIwR8MHqAFFzsqJS9beI2gcGRUTOzEvJwS81KoV+kXTBbMQswCQYDVQQG EwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIx ITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbYIBADAMBgNVHRMEBTAD AQH/MA0GCSqGSIb3DQEBBAUAA4GBAHo3DrCHR86fSTVAvfiXdSswWqKtCEhUHRdC TLFGl4hDk2GyZxaFuqZwiURz/H7nMicymI2wkz8H/wyHFg8G3BIehURpj2v/ZWXY eovbgS7EZALVVkDj4hNl/IIHWd6Gtv1UODf7URbxtl3hQ9/eTWITrefT1heuPnar 8czydsOLMYIBujCCAbYCAQEwYDBbMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJD cnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNl bmRlckBleGFtcGxlLmRvbQIBADAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzEL BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAxMDMzMTE0NTgyMVowIwYJKoZI hvcNAQkEMRYEFOoeRUd8ExIYXfQq8BTFuKWrSP3iMFIGCSqGSIb3DQEJDzFFMEMw CgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIGAKMjEdSteeZg9ji1C Y2r6zuxDVVftpSLy9ZhYOblGYY2b3PhzI0XytdUoLdb+GlPImqE/F5FJCPvTAovq uLElbx/FuijA2ly7PQF2ekyFJ0EhvNWT1gcLhi1m0W+Hk/jgCQx7YRojT53Pa9fj zuHk7ZkSKe5rZlOJvPJtYREnvD8= ------2221986D060512556B8AC18AAA106F39-- M2Crypto-0.22.6rc4/demo/smime.howto/sign.py0000664000175000017500000000151412611255457020635 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import BIO, Rand, SMIME def makebuf(text): return BIO.MemoryBuffer(text) # Make a MemoryBuffer of the message. buf = makebuf('a sign of our times') # Seed the PRNG. Rand.load_file('randpool.dat', -1) # Instantiate an SMIME object; set it up; sign the buffer. s = SMIME.SMIME() s.load_key('signer_key.pem', 'signer.pem') p7 = s.sign(buf, SMIME.PKCS7_DETACHED) # Recreate buf. buf = makebuf('a sign of our times') # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: sender@example.dom\n') out.write('To: recipient@example.dom\n') out.write('Subject: M2Crypto S/MIME testing\n') s.write(out, p7, buf) print out.read() # Save the PRNG's state. Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/smime.howto/signer.pem0000664000175000017500000000204612605232411021302 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIC4zCCAkygAwIBAgIBADANBgkqhkiG9w0BAQQFADBbMQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIxITAfBgkq hkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbTAeFw0wMTAzMzExMTQwMzNaFw0w MjAzMzExMTQwMzNaMFsxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEW MBQGA1UEAxMNUy9NSU1FIFNlbmRlcjEhMB8GCSqGSIb3DQEJARYSc2VuZGVyQGV4 YW1wbGUuZG9tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlzlOPUIdNI7Fr WrarQViLAxZgem0mkly+1mZTCuBTmwesDw6cIzRwNcSPQo9/dx82Md98HwdYzMjh QSA2YVdA2zGgZn6KrDEuU2PL0yHt4Vb8GOrmE1dui5KVDStYFGSjFXrjL63qVB6F vfZZ9hdBsoXEUlJfNLE7HdHxiFI93QIDAQABo4G2MIGzMB0GA1UdDgQWBBRc7KiU vW3iNoHBkVEzsxLycEvNSjCBgwYDVR0jBHwweoAUXOyolL1t4jaBwZFRM7MS8nBL zUqhX6RdMFsxCzAJBgNVBAYTAlNHMREwDwYDVQQKEwhNMkNyeXB0bzEWMBQGA1UE AxMNUy9NSU1FIFNlbmRlcjEhMB8GCSqGSIb3DQEJARYSc2VuZGVyQGV4YW1wbGUu ZG9tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAejcOsIdHzp9J NUC9+Jd1KzBaoq0ISFQdF0JMsUaXiEOTYbJnFoW6pnCJRHP8fucyJzKYjbCTPwf/ DIcWDwbcEh6FRGmPa/9lZdh6i9uBLsRkAtVWQOPiE2X8ggdZ3oa2/VQ4N/tRFvG2 XeFD395NYhOt59PWF64+dqvxzPJ2w4s= -----END CERTIFICATE----- M2Crypto-0.22.6rc4/demo/smime.howto/signer_key.pem0000664000175000017500000000157312605232411022156 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDlzlOPUIdNI7FrWrarQViLAxZgem0mkly+1mZTCuBTmwesDw6c IzRwNcSPQo9/dx82Md98HwdYzMjhQSA2YVdA2zGgZn6KrDEuU2PL0yHt4Vb8GOrm E1dui5KVDStYFGSjFXrjL63qVB6FvfZZ9hdBsoXEUlJfNLE7HdHxiFI93QIDAQAB AoGBALqc4OgZSbYPjQyTfpD1IJTKLgqsgCR5aE0kR7WZuG7MDt/e3ktWn0ebsgFv 2J12u2bD+yqM++dVbK7WtvTR+QpMhb/0XMhXNsvmn5gOLdKlJjS0RXDDs2DzIS6p JNzAmn5zqTVteZAMDLk7ygkO++iGzwRz713ZgxRaKr5YWiLVAkEA+3ev1TTXNEOk wQ9fbukMrfUXesqwgrx9VZ1z1X5we42RIIMTYI1edpcujXYvgS3/jdzAWDS1Nqta 9QB3uy91ywJBAOnysIIQhHn+4zvaOA5vh85WczPhN9C+yRmV70eyL9h+aThUFS4c kg2jQOLp8MaxAkmk4xRbZBgehjmDr45b5fcCQQDpIGNlYFBmhpN129+YffugRgjX cJNFEKONPKRHd6mmEW9K2dmb+FNr0+p3gOq3csJpbQ7wdyTMov13B1D4ux4TAkAR URB1oCleKlrBjGaH0wOXZ1jBp1MNVYHnLez3Pp5CBSFetQKYVi8NaV8dLLnQyztj Hhxc3mLrUh8XVMMC45SDAkEAxRCKmkneLceIdwixLIUF0zr0OzJtgyhxMxvHu3ET gJcZqNN0y3EgPwcNihpBw7rjpp5e5sjlRNVqLqn8a5/Fog== -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/smime.howto/verify.py0000664000175000017500000000121112611255457021173 0ustar matejmatej00000000000000#!/usr/bin/env python """S/MIME HOWTO demo program. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import SMIME, X509 # Instantiate an SMIME object. s = SMIME.SMIME() # Load the signer's cert. x509 = X509.load_cert('signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Load the signer's CA cert. In this case, because the signer's # cert is self-signed, it is the signer's cert itself. st = X509.X509_Store() st.load_info('signer.pem') s.set_x509_store(st) # Load the data, verify it. p7, data = SMIME.smime_load_pkcs7('sign.p7') v = s.verify(p7, data) print v print data print data.read() M2Crypto-0.22.6rc4/demo/ssl/0000775000175000017500000000000012613362233015643 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/ssl/README0000664000175000017500000000155712605232411016526 0ustar matejmatej00000000000000 29 Nov 00 ----------- This directory contains SSL clients and servers written as demos and testbeds. The oldest ones are s_server.py and s_client.py: these are modeled after the eponymous demo programs in OpenSSL. Once I got them going, I moved on to Medusa and other "real-world" servers. The pair has been in a state of neglect and quite likely no longer work with the current M2Crypto. My current testbeds are the echod-* servers and echo.py. These should always work. Note that Python on the three platforms that I test on are built --with-threads. Python 2.0's httplib introduces HTTP/1.1 functionality and an interface substantially different from Python 1.5.2's HTTP/1.0 interface. M2Crypto.httpslib provides both interfaces. The demo programs are https_cli.py and urllib_cli.py; these have been tested with Apache/1.3.14 (Unix) mod_ssl/2.7.1 OpenSSL/0.9.6. M2Crypto-0.22.6rc4/demo/ssl/c.py0000664000175000017500000000300612607370517016445 0ustar matejmatej00000000000000#!/usr/bin/env python """C programming in Python. Have SWIG sweat the pointers. ;-) Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from socket import * import sys from M2Crypto import SSL, m2 HOST = '127.0.0.1' PORT = 9443 req_10 = 'GET / HTTP/1.0\r\n\r\n' req_11 = 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' def c_10(): c_style(HOST, PORT, req_10) def c_11(): c_style(HOST, PORT, req_11) def c_style(HOST, PORT, req): # Set up SSL context. ctx = m2.ssl_ctx_new(m2.sslv3_method()) m2.ssl_ctx_use_cert(ctx, 'client.pem') m2.ssl_ctx_use_privkey(ctx, 'client.pem') # Make the socket connection. s = socket(AF_INET, SOCK_STREAM) s.connect((HOST, PORT)) # Set up the SSL connection. sbio = m2.bio_new_socket(s.fileno(), 0) ssl = m2.ssl_new(ctx) m2.ssl_set_bio(ssl, sbio, sbio) m2.ssl_connect(ssl) sslbio = m2.bio_new(m2.bio_f_ssl()) m2.bio_set_ssl(sslbio, ssl, 0) # Push a buffering BIO over the SSL BIO. iobuf = m2.bio_new(m2.bio_f_buffer()) topbio = m2.bio_push(iobuf, sslbio) # Send the request. m2.bio_write(sslbio, req) # Receive the response. while 1: data = m2.bio_gets(topbio, 4096) if not data: break sys.stdout.write(data) # Cleanup. May be missing some necessary steps. ;-| m2.bio_pop(topbio) m2.bio_free(iobuf) m2.ssl_shutdown(ssl) m2.ssl_free(ssl) m2.ssl_ctx_free(ctx) s.close() if __name__ == '__main__': c_10() c_11() M2Crypto-0.22.6rc4/demo/ssl/c_bio.py0000664000175000017500000000300712607370517017277 0ustar matejmatej00000000000000#!/usr/bin/env python """C programming in Python. Have SWIG sweat the pointers. ;-) Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved.""" from socket import * import sys from M2Crypto import SSL, m2 HOST = '127.0.0.1' PORT = 9443 req_10 = 'GET / HTTP/1.0\r\n\r\n' req_11 = 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' def c_10(): c_style(HOST, PORT, req_10) def c_11(): c_style(HOST, PORT, req_11) def c_style(HOST, PORT, req): # Set up SSL context. ctx = m2.ssl_ctx_new(m2.sslv3_method()) m2.ssl_ctx_use_cert(ctx, 'client.pem') m2.ssl_ctx_use_privkey(ctx, 'client.pem') # Make the socket connection. s = socket(AF_INET, SOCK_STREAM) s.connect((HOST, PORT)) # Set up the SSL connection. sbio = m2.bio_new_socket(s.fileno(), 0) ssl = m2.ssl_new(ctx) m2.ssl_set_bio(ssl, sbio, sbio) m2.ssl_connect(ssl) sslbio = m2.bio_new(m2.bio_f_ssl()) m2.bio_set_ssl(sslbio, ssl, 0) # Push a buffering BIO over the SSL BIO. iobuf = m2.bio_new(m2.bio_f_buffer()) topbio = m2.bio_push(iobuf, sslbio) # Send the request. m2.bio_write(sslbio, req) # Receive the response. while 1: data = m2.bio_gets(topbio, 4096) if not data: break sys.stdout.write(data) # Cleanup. May be missing some necessary steps. ;-| m2.bio_pop(topbio) m2.bio_free(iobuf) m2.ssl_shutdown(ssl) m2.ssl_free(ssl) m2.ssl_ctx_free(ctx) s.close() if __name__ == '__main__': #c_10() c_11() M2Crypto-0.22.6rc4/demo/ssl/ca.der0000664000175000017500000000151112605232411016713 0ustar matejmatej000000000000000E00  *H 0{1 0 USG10U M2Crypto10U  M2Crypto CA1$0"UM2Crypto Certificate Master10 *H  ngps@post1.com0 000910085835Z 030910085835Z0{1 0 USG10U M2Crypto10U  M2Crypto CA1$0"UM2Crypto Certificate Master10 *H  ngps@post1.com00  *H 0ǁL;D*N<3vO.9,IKA#C?CH/zRufJTA:= Ċ`& KhBȭ&7@s>BLVѺ#ΗJ00U#i:ſ)QO(80U#0#i:ſ)QO(8}0{1 0 USG10U M2Crypto10U  M2Crypto CA1$0"UM2Crypto Certificate Master10 *H  ngps@post1.com0 U00  *H utOYzaRS6]T{瞀ßqvÈXV[b15ziPCX Y~NA'ӯ 065a7+dJH*J, LNvг>oyq 0])\; 43YpK W!,(EirTٴG8骽:+b=0{L  /2:4JVGc q3=Q7Hv#k/N6ӤH6 S! w ͻ"!0TiN/ȫA0ǤIsIa.&Z/댗Da"?Wt'|Ic:Yɂ/!Oc*V׺۾Q[e0?TQ C@ o5Hu7n4zS҅ g/NRߥUڐ!!/3٪eP^<0ꝔSxϓٲqcta9"PI#&=v %b3Cb~'pb 0) def handle_write(self): if self._ssl_accepting: s = self.socket.accept_ssl() if s: self._ssl_accepting = 0 else: try: n = self.send(self.buffer) if n == -1: pass elif n == 0: self.handle_close() else: self.buffer = self.buffer[n:] except SSL.SSLError, what: if str(what) == 'unexpected eof': self.handle_close() return else: raise def readable(self): return 1 def handle_read(self): if self._ssl_accepting: s = self.socket.accept_ssl() if s: self._ssl_accepting = 0 else: try: blob = self.recv(4096) if blob is None: pass elif blob == '': self.handle_close() else: self.buffer = self.buffer + blob except SSL.SSLError, what: if str(what) == 'unexpected eof': self.handle_close() return else: raise class ssl_echo_server(SSL.ssl_dispatcher): channel_class=ssl_echo_channel def __init__(self, addr, port, ssl_context): SSL.ssl_dispatcher.__init__(self) self.create_socket(ssl_context) self.set_reuse_addr() self.socket.setblocking(0) self.bind((addr, port)) self.listen(5) self.ssl_ctx=ssl_context def handle_accept(self): try: sock, addr = self.socket.accept() self.channel_class(sock) except: print '-'*40 import traceback traceback.print_exc() print '-'*40 return def writable(self): return 0 if __name__=='__main__': Rand.load_file('../randpool.dat', -1) ctx = echod_lib.init_context('sslv23', 'server.pem', 'ca.pem', \ #SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) SSL.verify_none) ctx.set_tmp_dh('dh1024.pem') ssl_echo_server('', 9999, ctx) asyncore.loop() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/echod-eg1.py0000664000175000017500000000267112607370517017766 0ustar matejmatej00000000000000#!/usr/bin/env python """Demo SSL server #1 for the HOWTO. Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" import SocketServer from M2Crypto import Err, Rand, SSL, threading def init_context(protocol, dhpfile, certfile, cafile, verify, verify_depth=10): ctx = SSL.Context(protocol) ctx.set_tmp_dh(dhpfile) ctx.load_cert(certfile) #ctx.load_verify_info(cafile) ctx.set_verify(verify, verify_depth) ctx.set_session_id_ctx('echod') ctx.set_info_callback() return ctx class ssl_echo_handler(SocketServer.BaseRequestHandler): buffer = 'Ye Olde Echo Servre\r\n' def handle(self): peer = self.request.get_peer_cert() if peer is not None: print 'Client CA =', peer.get_issuer().O print 'Client Subject =', peer.get_subject().CN self.request.write(self.buffer) while 1: buf = self.request.read() if not buf: break self.request.write(buf) def finish(self): self.request.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN) self.request.close() if __name__ == '__main__': Rand.load_file('randpool.dat', -1) threading.init() ctx = init_context('sslv23', 'dh1024.pem', 'server.pem', 'ca.pem', SSL.verify_peer) s = SSL.SSLServer(('', 9999), ssl_echo_handler, ctx) s.serve_forever() threading.cleanup() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/echod-forking.py0000664000175000017500000000117112607370517020743 0ustar matejmatej00000000000000#!/usr/bin/env python """A forking SSL 'echo' server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import DH, Rand, SSL import echod_lib class ssl_echo_handler(echod_lib.ssl_echo_handler): buffer = 'Ye Olde Forking Echo Servre\r\n' if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) ctx = echod_lib.init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) ctx.set_tmp_dh('dh1024.pem') s = SSL.ForkingSSLServer(('', 9999), ssl_echo_handler, ctx) s.serve_forever() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/echod-iterative.py0000664000175000017500000000122012607370517021273 0ustar matejmatej00000000000000#!/usr/bin/env python """A simple iterative SSL 'echo' server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import Rand, SSL import echod_lib class ssl_echo_handler(echod_lib.ssl_echo_handler): buffer='Ye Olde One-At-A-Time Echo Servre\r\n' if __name__=='__main__': Rand.load_file('../randpool.dat', -1) ctx=echod_lib.init_context('sslv23', 'server.pem', 'ca.pem', \ SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) #SSL.verify_none) ctx.set_tmp_dh('dh1024.pem') s=SSL.SSLServer(('', 9999), ssl_echo_handler, ctx) s.serve_forever() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/echod-thread.py0000664000175000017500000000272612607370517020562 0ustar matejmatej00000000000000#!/usr/bin/env python """Another multi-threading SSL 'echo' server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import Rand, SSL, threading import echod_lib import thread from socket import * buffer='Ye Newe Threading Echo Servre\r\n' def echo_handler(sslctx, sock, addr): sslconn = SSL.Connection(sslctx, sock) sslconn.setup_addr(addr) sslconn.setup_ssl() sslconn.set_accept_state() sslconn.accept_ssl() sslconn.write(buffer) while 1: try: buf = sslconn.read() if not buf: break sslconn.write(buf) except SSL.SSLError, what: if str(what) == 'unexpected eof': break else: raise except: break # Threading servers need this. sslconn.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN|SSL.SSL_SENT_SHUTDOWN) sslconn.close() if __name__=='__main__': threading.init() Rand.load_file('../randpool.dat', -1) ctx=echod_lib.init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) ctx.set_tmp_dh('dh1024.pem') sock = socket(AF_INET, SOCK_STREAM) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(('', 9999)) sock.listen(5) while 1: conn, addr = sock.accept() thread.start_new_thread(echo_handler, (ctx, conn, addr)) Rand.save_file('../randpool.dat') threading.cleanup() M2Crypto-0.22.6rc4/demo/ssl/echod-threading.py0000664000175000017500000000163512607370517021256 0ustar matejmatej00000000000000#!/usr/bin/env python """A multi-threading SSL 'echo' server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import DH, Rand, SSL, threading import echod_lib class ssl_echo_handler(echod_lib.ssl_echo_handler): buffer='Ye Olde Threading Echo Servre\r\n' def finish(self): # Threading servers need this. self.request.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN) self.request.close() if __name__=='__main__': try: threading.init() Rand.load_file('../randpool.dat', -1) ctx=echod_lib.init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) ctx.set_tmp_dh('dh1024.pem') s=SSL.ThreadingSSLServer(('', 9999), ssl_echo_handler, ctx) s.serve_forever() Rand.save_file('../randpool.dat') except: threading.cleanup() M2Crypto-0.22.6rc4/demo/ssl/echod_lib.py0000664000175000017500000000241612607370517020137 0ustar matejmatej00000000000000"""Support routines for the various SSL 'echo' servers. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import SocketServer from M2Crypto import SSL def init_context(protocol, certfile, cafile, verify, verify_depth=10): ctx = SSL.Context(protocol) ctx.load_cert_chain(certfile) ctx.load_verify_locations(cafile) ctx.set_client_CA_list_from_file(cafile) ctx.set_verify(verify, verify_depth) #ctx.set_allow_unknown_ca(1) ctx.set_session_id_ctx('echod') ctx.set_info_callback() return ctx class ssl_echo_handler(SocketServer.BaseRequestHandler): buffer = 'Ye Olde Echo Servre\r\n' def handle(self): peer = self.request.get_peer_cert() if peer is not None: print 'Client CA =', peer.get_issuer().O print 'Client Subject =', peer.get_subject().CN x = self.request.write(self.buffer) while 1: try: buf = self.request.read() if not buf: break self.request.write(buf) except SSL.SSLError, what: if str(what) == 'unexpected eof': break else: raise def finish(self): self.request.close() M2Crypto-0.22.6rc4/demo/ssl/ftp_tls.py0000664000175000017500000000157212607370517017704 0ustar matejmatej00000000000000#!/usr/bin/env python """Demo for M2Crypto.ftpslib's FTP/TLS client. This client interoperates with M2Crypto's Medusa-based FTP/TLS server as well as Peter Runestig's patched-for-TLS OpenBSD FTP server. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" from M2Crypto import SSL, ftpslib, threading def passive(): ctx = SSL.Context('sslv23') f = ftpslib.FTP_TLS(ssl_ctx=ctx) f.connect('127.0.0.1', 39021) f.auth_tls() f.set_pasv(1) f.login('ftp', 'ngps@') f.prot_p() f.retrlines('LIST') f.quit() def active(): ctx = SSL.Context('sslv23') f = ftpslib.FTP_TLS(ssl_ctx=ctx) f.connect('127.0.0.1', 39021) f.auth_tls() f.set_pasv(0) f.login('ftp', 'ngps@') f.prot_p() f.retrlines('LIST') f.quit() if __name__ == '__main__': threading.init() active() passive() threading.cleanup() M2Crypto-0.22.6rc4/demo/ssl/http_cli_20.py0000664000175000017500000000077512607370517020344 0ustar matejmatej00000000000000import httplib, sys def test_httplib(): h = httplib.HTTPConnection('127.0.0.1', 80) h.set_debuglevel(1) h.putrequest('GET', '/') h.putheader('Accept', 'text/html') h.putheader('Accept', 'text/plain') h.putheader('Connection', 'close') h.endheaders() resp = h.getresponse() f = resp.fp while 1: data = f.readline() if not data: break sys.stdout.write(data) f.close() h.close() if __name__=='__main__': test_httplib() M2Crypto-0.22.6rc4/demo/ssl/https_cli.py0000664000175000017500000000222512607370517020216 0ustar matejmatej00000000000000#!/usr/bin/env python """Demonstrations of M2Crypto.httpslib. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import sys from M2Crypto import Rand, SSL, httpslib, threading def test_httpslib(): ctx = SSL.Context('sslv23') ctx.load_cert_chain('client.pem') ctx.load_verify_locations('ca.pem', '') ctx.set_verify(SSL.verify_peer, 10) ctx.set_info_callback() h = httpslib.HTTPSConnection('localhost', 19443, ssl_context=ctx) h.set_debuglevel(1) h.putrequest('GET', '/') h.putheader('Accept', 'text/html') h.putheader('Accept', 'text/plain') h.putheader('Connection', 'close') h.endheaders() resp = h.getresponse() f = resp.fp c = 0 while 1: # Either of following two works. #data = f.readline(4096) data = resp.read(4096) if not data: break c = c + len(data) #print data sys.stdout.write(data) sys.stdout.flush() f.close() h.close() if __name__=='__main__': Rand.load_file('../randpool.dat', -1) #threading.init() test_httpslib() #threading.cleanup() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/https_cli_async.py0000664000175000017500000000710412607370517021414 0ustar matejmatej00000000000000#!/usr/bin/env python """Demo for client-side ssl_dispatcher usage. Note that connect() is blocking. (Need fix?) This isn't really a HTTPS client; it's just a toy. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import asyncore, sys, time from M2Crypto import Rand, SSL class https_client(SSL.ssl_dispatcher): def __init__(self, host, path, ssl_ctx): SSL.ssl_dispatcher.__init__(self) self.path = path self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % self.path self.create_socket(ssl_ctx) self.socket.connect((host, 19443)) self._can_read = 1 self._count = 0 def handle_connect(self): pass def readable(self): return self._can_read def handle_read(self): try: result = self.recv() if result is None: return elif result == '': self._can_read = 0 sys.stdout.write('%s: total: %5d\n' % (self.path, self._count,)) sys.stdout.flush() self.close() else: #print result l = len(result) self._count = self._count + l display = (time.time(), l, self.path) sys.stdout.write('%14.3f: read %5d from %s\n' % display) sys.stdout.flush() except SSL.SSLError, why: print 'handle_read:', why self.close() raise def writable(self): return (len(self.buffer) > 0) def handle_write(self): try: sent = self.send(self.buffer) self.buffer = self.buffer[sent:] except SSL.SSLError, why: print 'handle_write:', why self.close() if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) ctx = SSL.Context() url = ('/jdk118/api/u-names.html', '/postgresql/xfunc-c.html', '/python2.1/modindex.html') for u in url: https_client('localhost', u, ctx) asyncore.loop() Rand.save_file('../randpool.dat') # Here's a sample output. Server is Apache+mod_ssl on localhost. # $ python https_cli_async.py # 991501090.682: read 278 from /python2.1/modindex.html # 991501090.684: read 278 from /postgresql/xfunc-c.html # 991501090.742: read 4096 from /postgresql/xfunc-c.html # 991501090.743: read 4096 from /postgresql/xfunc-c.html # 991501090.744: read 4096 from /postgresql/xfunc-c.html # 991501090.744: read 4096 from /postgresql/xfunc-c.html # 991501090.755: read 4096 from /postgresql/xfunc-c.html # 991501090.756: read 278 from /jdk118/api/u-names.html # 991501090.777: read 4096 from /postgresql/xfunc-c.html # 991501090.778: read 4096 from /postgresql/xfunc-c.html # 991501090.778: read 4096 from /postgresql/xfunc-c.html # 991501090.782: read 4096 from /postgresql/xfunc-c.html # 991501090.813: read 4096 from /python2.1/modindex.html # 991501090.839: read 4096 from /jdk118/api/u-names.html # 991501090.849: read 4096 from /python2.1/modindex.html # 991501090.873: read 3484 from /postgresql/xfunc-c.html # 991501090.874: read 4096 from /jdk118/api/u-names.html # 991501090.874: read 4096 from /python2.1/modindex.html #/postgresql/xfunc-c.html: total: 40626 # 991501090.886: read 4096 from /jdk118/api/u-names.html # 991501090.886: read 2958 from /python2.1/modindex.html # 991501090.887: read 4096 from /jdk118/api/u-names.html #/python2.1/modindex.html: total: 15524 # 991501090.893: read 4096 from /jdk118/api/u-names.html # 991501090.894: read 2484 from /jdk118/api/u-names.html #/jdk118/api/u-names.html: total: 23242 # $ M2Crypto-0.22.6rc4/demo/ssl/https_srv.py0000664000175000017500000001052312607370517020261 0ustar matejmatej00000000000000"""This server extends BaseHTTPServer and SimpleHTTPServer thusly: 1. One thread per connection. 2. Generates directory listings. In addition, it has the following properties: 1. Works over HTTPS only. 2. Displays SSL handshaking and SSL session info. 3. Performs SSL renegotiation when a magic url is requested. TODO: 1. Cache stat() of directory entries. 2. Fancy directory indexing. 3. Interface ZPublisher. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. """ import os, sys from SimpleHTTPServer import SimpleHTTPRequestHandler from M2Crypto import Rand, SSL from M2Crypto.SSL.SSLServer import ThreadingSSLServer try: from cStringIO import StringIO except ImportError: from StringIO import StringIO def mkdirlist(path, url): dirlist = os.listdir(path) dirlist.sort() f = StringIO() f.write('Index listing for %s\r\n' % (url,)) f.write('

    Index listing for %s

    \r\n' % (url,)) f.write('
    \r\n')
        for d in dirlist:
            if os.path.isdir(os.path.join(path, d)):
                d2 = d + '/'
            else:
                d2 = d
            if url == '/':
                f.write('%s
    \r\n' % (d, d2)) else: f.write('%s
    \r\n' % (url, d, d2)) f.write('
    \r\n\r\n') f.reset() return f class HTTP_Handler(SimpleHTTPRequestHandler): server_version = "https_srv/0.1" reneg = 0 # Cribbed from SimpleHTTPRequestHander to add the ".der" entry, # which facilitates installing your own certificates into browsers. extensions_map = { '': 'text/plain', # Default, *must* be present '.html': 'text/html', '.htm': 'text/html', '.gif': 'image/gif', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.der': 'application/x-x509-ca-cert' } def send_head(self): if self.path[1:8] == '_reneg_': self.reneg = 1 self.path = self.path[8:] path = self.translate_path(self.path) if os.path.isdir(path): f = mkdirlist(path, self.path) filetype = 'text/html' else: try: f = open(path, 'rb') filetype = self.guess_type(path) except IOError: self.send_error(404, "File not found") return None self.send_response(200) self.send_header("Content-type", filetype) self.end_headers() return f def do_GET(self): #sess = self.request.get_session() #self.log_message('\n%s', sess.as_text()) f = self.send_head() if self.reneg: self.reneg = 0 self.request.renegotiate() sess = self.request.get_session() self.log_message('\n%s', sess.as_text()) if f: self.copyfile(f, self.wfile) f.close() def do_HEAD(self): #sess = self.request.get_session() #self.log_message('\n%s', sess.as_text()) f = self.send_head() if f: f.close() class HTTPS_Server(ThreadingSSLServer): def __init__(self, server_addr, handler, ssl_ctx): ThreadingSSLServer.__init__(self, server_addr, handler, ssl_ctx) self.server_name = server_addr[0] self.server_port = server_addr[1] def finish(self): self.request.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN) self.request.close() def init_context(protocol, certfile, cafile, verify, verify_depth=10): ctx=SSL.Context(protocol) ctx.load_cert(certfile) ctx.load_client_ca(cafile) ctx.load_verify_info(cafile) ctx.set_verify(verify, verify_depth) ctx.set_allow_unknown_ca(1) ctx.set_session_id_ctx('https_srv') ctx.set_info_callback() return ctx if __name__ == '__main__': from M2Crypto import threading as m2threading m2threading.init() if len(sys.argv) < 2: wdir = '.' else: wdir = sys.argv[1] Rand.load_file('../randpool.dat', -1) ctx = init_context('sslv23', 'server.pem', 'ca.pem', \ SSL.verify_none) #SSL.verify_peer | SSL.verify_fail_if_no_peer_cert) ctx.set_tmp_dh('dh1024.pem') os.chdir(wdir) httpsd = HTTPS_Server(('', 19443), HTTP_Handler, ctx) httpsd.serve_forever() Rand.save_file('../randpool.dat') m2threading.cleanup() M2Crypto-0.22.6rc4/demo/ssl/myapp.py0000664000175000017500000000137612605232411017345 0ustar matejmatej00000000000000""" Sample application for socklib and somelib. Copyright (c) 2007 Open Source Applications Foundation. All rights reserved. """ # Sample application that uses socklib to override socket.ssl in order # to make the 3rd party library use M2Crypto for SSL, instead of python # stdlib SSL. import socklib # sets M2Crypto.SSL.Connection as socket.ssl # Set up the secure context for socklib from M2Crypto import SSL def getContext(): ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('ca.pem') return ctx socklib.setSSLContextFactory(getContext) # Import and use 3rd party lib import somelib if __name__ == '__main__': c = somelib.HttpsGetSlash() c.get('verisign.com', 443) M2Crypto-0.22.6rc4/demo/ssl/s_client.py0000664000175000017500000000535712607370517020036 0ustar matejmatej00000000000000#!/usr/bin/env python """An M2Crypto implementation of OpenSSL's s_client. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from socket import * import getopt import string import sys from M2Crypto import SSL # s_server -www HOST='127.0.0.1' PORT=4433 REQ='GET / HTTP/1.0\r\n\r\n' class Config: pass def config(args): options=['connect=', 'verify=', 'cert=', 'key=', 'CApath=', 'CAfile=', \ 'reconnect', 'pause', 'showcerts', 'debug', 'nbio_test', 'state', \ 'nbio', 'crlf', 'sslv2', 'sslv3', 'tlsv1', 'no_sslv2', 'no_sslv3', \ 'no_tlsv1', 'bugs', 'cipher=', 'Verify='] optlist, optarg=getopt.getopt(args, '', options) cfg=Config() for opt in optlist: setattr(cfg, opt[0][2:], opt[1]) for x in (('tlsv1','no_tlsv1'),('sslv3','no_sslv3'),('sslv2','no_sslv2')): if hasattr(cfg, x[0]) and hasattr(cfg, x[1]): raise ValueError, 'mutually exclusive: %s and %s' % x if hasattr(cfg, 'connect'): (host, port)=string.split(cfg.connect, ':') cfg.connect=(host, int(port)) else: cfg.connect=(HOST, PORT) cfg.protocol=[] # First protocol found will be used. # Permutate the following tuple for preference. for p in ('tlsv1', 'sslv3', 'sslv2'): if hasattr(cfg, p): cfg.protocol.append(p) cfg.protocol.append('sslv23') return cfg def make_context(config): ctx=SSL.Context(config.protocol[0]) if hasattr(config, 'cert'): cert=config.cert else: cert='client.pem' if hasattr(config, 'key'): key=config.key else: key='client.pem' #ctx.load_cert(cert, key) if hasattr(config, 'verify'): verify=SSL.verify_peer depth=int(config.verify) elif hasattr(config, 'Verify'): verify=SSL.verify_peer | SSL.verify_fail_if_no_peer_cert depth=int(config.Verify) else: verify=SSL.verify_none depth=10 config.verify=verify config.verify_depth=depth ctx.set_verify(verify, depth) if hasattr(config, 'CAfile'): cafile=config.CAfile else: cafile='ca.pem' ctx.load_verify_location(cafile) return ctx def s_client(config): ctx=make_context(config) s=SSL.Connection(ctx) s.connect(config.connect) if config.verify != SSL.verify_none and not s.verify_ok(): print 'peer verification failed' peer=s.get_peer_cert() if peer is None: print 'unable to get peer certificate' else: print 'peer.as_text()' raise SystemExit s.send(REQ) while 1: data=s.recv() if not data: break print data s.close() if __name__=='__main__': cfg=config(sys.argv[1:]) s_client(cfg) M2Crypto-0.22.6rc4/demo/ssl/s_server.py0000664000175000017500000001157012607370517020060 0ustar matejmatej00000000000000#!/usr/bin/env python """An M2Crypto implementation of OpenSSL's s_server. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from socket import * import asyncore import cStringIO import getopt import string import sys from M2Crypto import SSL, BIO, DH, Err # s_server -www HOST='' PORT=4433 class Config: pass def config(args): options=['accept=', 'context=', 'verify=', 'Verify=', 'cert=', 'key=', \ 'dcert=', 'dkey=', 'nocert', 'crlf', 'debug', 'CApath=', 'CAfile=', \ 'quiet', 'no_tmp_rsa', 'state', 'sslv2', 'sslv3', 'tlsv1', \ 'no_sslv2', 'no_sslv3', 'no_tlsv1', 'bugs', 'cipher='] optlist, optarg=getopt.getopt(args, '', options) cfg=Config() for opt in optlist: setattr(cfg, opt[0][2:], opt[1]) for x in (('tlsv1','no_tlsv1'),('sslv3','no_sslv3'),('sslv2','no_sslv2')): if hasattr(cfg, x[0]) and hasattr(cfg, x[1]): raise ValueError, 'mutually exclusive: %s and %s' % x if hasattr(cfg, 'accept'): cfg.accept=string.split(cfg.connect, ':') else: cfg.accept=(HOST, PORT) cfg.protocol=[] # First protocol found will be used. # Permutate the following tuple for preference. for p in ('tlsv1', 'sslv3', 'sslv2'): if hasattr(cfg, p): cfg.protocol.append(p) cfg.protocol.append('sslv23') return cfg RESP_HEAD="""\ HTTP/1.0 200 ok Content-type: text/html
    
    Emulating s_server -www
    Ciphers supported in s_server.py
    """
    
    RESP_TAIL="""\
    
    """ class channel(SSL.ssl_dispatcher): def __init__(self, conn, debug): SSL.ssl_dispatcher.__init__(self, conn) self.socket.setblocking(0) self.buffer=self.fixup_buffer() self.debug=debug def fixup_buffer(self): even=0 buffer=cStringIO.StringIO() buffer.write(RESP_HEAD) for c in self.get_ciphers(): # This formatting works for around 80 columns. buffer.write('%-11s:%-28s' % (c.version(), c.name())) if even: buffer.write('\r\n') even=1-even buffer.write('\r\n%s' % RESP_TAIL) return buffer.getvalue() def handle_connect(self): pass def handle_close(self): self.close() def handle_error(self, exc_type, exc_value, exc_traceback): if self.debug: print 'handle_error()' #print exc_type, exc_value, exc_traceback print Err.get_error() self.handle_close() def writeable(self): return len(self.buffer) def handle_write(self): n=self.send(self.buffer) if n==-1: pass elif n==0: self.handle_close() else: self.buffer=self.buffer[n:] if self.debug: print 'handle_write():', n def readable(self): return 1 def handle_read(self): blob=self.recv() if blob is None: pass elif blob=='': self.handle_close() else: pass if self.debug: print 'handle_read():', blob class server(SSL.ssl_dispatcher): channel_class=channel def __init__(self, addr, port, config, ssl_context): asyncore.dispatcher.__init__(self) self.create_socket(ssl_context) self.set_reuse_addr() self.socket.setblocking(0) self.bind((addr, port)) self.listen(5) self.config=config self.debug=config.debug self.ssl_ctx=ssl_context def handle_accept(self): sock, addr=self.accept() print self.ssl_ctx.get_verify_mode() if (self.ssl_ctx.get_verify_mode() is SSL.verify_none) or sock.verify_ok(): self.channel_class(sock, self.debug) else: print 'client verification failed' sock.close() def writeable(self): return 0 def s_server(config): ctx=SSL.Context(config.protocol[0]) if hasattr(config, 'debug'): config.debug=1 else: config.debug=0 if hasattr(config, 'cert'): cert=config.cert else: cert='server.pem' if hasattr(config, 'key'): cert=config.key else: cert='server.pem' ctx.load_cert(cert) if hasattr(config, 'CAfile'): cafile=config.CAfile else: cafile='ca.pem' ctx.load_verify_location(cafile) if hasattr(config, 'verify'): verify=SSL.verify_peer depth=int(config.verify) elif hasattr(config, 'Verify'): verify=SSL.verify_peer | SSL.verify_fail_if_no_peer_cert depth=int(config.Verify) else: verify=SSL.verify_none depth=0 ctx.set_verify(verify, depth) ctx.set_tmp_dh('dh1024.pem') #ctx.set_info_callback() server(cfg.accept[0], cfg.accept[1], cfg, ctx) asyncore.loop() if __name__=='__main__': cfg=config(sys.argv[1:]) s_server(cfg) M2Crypto-0.22.6rc4/demo/ssl/server.pem0000664000175000017500000000411012605232411017643 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/ssl/server3.py0000664000175000017500000000617512607370517017626 0ustar matejmatej00000000000000#!/usr/bin/env python """ server3 from the book 'Network Security with OpenSSL', but modified to Python/M2Crypto from the original C implementation. Copyright (c) 2004-2005 Open Source Applications Foundation. Author: Heikki Toivonen """ from M2Crypto import SSL, Rand, threading, DH import thread from socket import * verbose_debug = 1 def verify_callback(ok, store): if not ok: print "***Verify Not ok" return ok dh1024 = None def init_dhparams(): global dh1024 dh1024 = DH.load_params('dh1024.pem') def tmp_dh_callback(ssl, is_export, keylength): global dh1024 if not dh1024: init_dhparams() return dh1024._ptr() def setup_server_ctx(): ctx = SSL.Context('sslv23') if ctx.load_verify_locations('ca.pem') != 1: print "***No CA file" #if ctx.set_default_verify_paths() != 1: # print "***No default verify paths" ctx.load_cert_chain('server.pem') ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 10, verify_callback) ctx.set_options(SSL.op_all | SSL.op_no_sslv2) ctx.set_tmp_dh_callback(tmp_dh_callback) #ctx.set_tmp_dh('dh1024.pem') if ctx.set_cipher_list('ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH') != 1: print "***No valid ciphers" if verbose_debug: ctx.set_info_callback() return ctx def post_connection_check(peerX509, expectedHost): if peerX509 is None: print "***No peer certificate" # Not sure if we can do any other checks return 1 def do_server_loop(conn): while 1: try: buf = conn.read() if not buf: break print buf except SSL.SSLError, what: if str(what) == 'unexpected eof': break else: raise except: break if conn.get_shutdown(): return 1 return 0 # How about something like: #def server_thread(ctx, ssl, addr): # conn = SSL.Connection(ctx, None) # conn.ssl = ssl # conn.setup_addr(addr) def server_thread(ctx, sock, addr): conn = SSL.Connection(ctx, sock) conn.set_post_connection_check_callback(post_connection_check) conn.setup_addr(addr) conn.set_accept_state() conn.setup_ssl() conn.accept_ssl() post_connection_check(conn) print 'SSL Connection opened' if do_server_loop(conn): conn.close() else: conn.clear() print 'SSL Connection closed' if __name__=='__main__': threading.init() Rand.load_file('../randpool.dat', -1) ctx = setup_server_ctx() # How about something like this? #conn_root = SSL.Connection(ctx) #conn_root.bind(('127.0.0.1', 9999)) #conn_root.listen(5) #while 1: # ssl, addr = conn_root.accept() # thread.start_new_thread(server_thread, (ctx, ssl, addr)) sock = socket(AF_INET, SOCK_STREAM) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(('', 9999)) sock.listen(5) while 1: conn, addr = sock.accept() thread.start_new_thread(server_thread, (ctx, conn, addr)) Rand.save_file('../randpool.dat') threading.cleanup() M2Crypto-0.22.6rc4/demo/ssl/sess.py0000664000175000017500000000422712607370517017206 0ustar matejmatej00000000000000"""M2Crypto.SSL.Session client demo: This program requests a URL from a HTTPS server, saves the negotiated SSL session id, parses the HTML returned by the server, then requests each HREF in a separate thread using the saved SSL session id. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import Err, Rand, SSL, X509, threading m2_threading = threading; del threading import formatter, getopt, htmllib, sys from threading import Thread from socket import gethostname def handler(sslctx, host, port, href, recurs=0, sslsess=None): s = SSL.Connection(sslctx) if sslsess: s.set_session(sslsess) s.connect((host, port)) else: s.connect((host, port)) sslsess = s.get_session() #print sslsess.as_text() if recurs: p = htmllib.HTMLParser(formatter.NullFormatter()) f = s.makefile("rw") f.write(href) f.flush() while 1: data = f.read() if not data: break if recurs: p.feed(data) if recurs: p.close() f.close() if recurs: for a in p.anchorlist: req = 'GET %s HTTP/1.0\r\n\r\n' % a thr = Thread(target=handler, args=(sslctx, host, port, req, recurs-1, sslsess)) print "Thread =", thr.getName() thr.start() if __name__ == '__main__': m2_threading.init() Rand.load_file('../randpool.dat', -1) host = '127.0.0.1' port = 9443 req = '/' optlist, optarg = getopt.getopt(sys.argv[1:], 'h:p:r:') for opt in optlist: if '-h' in opt: host = opt[1] elif '-p' in opt: port = int(opt[1]) elif '-r' in opt: req = opt[1] ctx = SSL.Context('sslv3') ctx.load_cert('client.pem') ctx.load_verify_info('ca.pem') ctx.load_client_ca('ca.pem') ctx.set_verify(SSL.verify_none, 10) req = 'GET %s HTTP/1.0\r\n\r\n' % req start = Thread(target=handler, args=(ctx, host, port, req, 1)) print "Thread =", start.getName() start.start() start.join() m2_threading.cleanup() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/sess2.py0000664000175000017500000000371212607370517017266 0ustar matejmatej00000000000000"""M2Crypto.SSL.Session client demo2: This program creates two sockets, each bound to a different local address. The first creates an SSL connection, the second then creates another SSL connection using the first's SSL session id. (This program only works if you've ifconfig'ed your interfaces correctly, of course.) Copyright (c) 1999-2001 Ng Pheng Siong. All rights reserved.""" from M2Crypto import Err, Rand, SSL, X509, threading m2_threading = threading; del threading import formatter, getopt, htmllib, sys from threading import Thread from socket import gethostname ADDR1 = '127.0.0.1', 9999 ADDR2 = '127.0.0.2', 9999 def handler(addr, sslctx, host, port, req, sslsess=None): s = SSL.Connection(sslctx) s.bind(addr) if sslsess: s.set_session(sslsess) s.connect((host, port)) else: s.connect((host, port)) sslsess = s.get_session() s.write(req) while 1: data = s.read(4096) if not data: break if addr != ADDR2: thr = Thread(target=handler, args=(ADDR2, sslctx, host, port, req, sslsess)) print "Thread =", thr.getName() thr.start() s.close() if __name__ == '__main__': m2_threading.init() Rand.load_file('../randpool.dat', -1) host = '127.0.0.1' port = 443 req = '/' optlist, optarg = getopt.getopt(sys.argv[1:], 'h:p:r:') for opt in optlist: if '-h' in opt: host = opt[1] elif '-p' in opt: port = int(opt[1]) elif '-r' in opt: req = opt[1] ctx = SSL.Context('sslv3') ctx.load_cert('client.pem') ctx.load_verify_info('ca.pem') ctx.set_verify(SSL.verify_none, 10) req = 'GET %s HTTP/1.0\r\n\r\n' % req start = Thread(target=handler, args=(ADDR1, ctx, host, port, req)) print "Thread =", start.getName() start.start() start.join() m2_threading.cleanup() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/sess2.ssldump.out0000664000175000017500000001051612605232411021117 0ustar matejmatej00000000000000New TCP connection #1: localhost(9999) <-> localhost(443) 1 1 0.0061 (0.0061) C>S Handshake ClientHello Version 3.0 cipher suites SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_RC4_128_SHA SSL_RSA_WITH_IDEA_CBC_SHA SSL_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_MD5 SSL_DHE_DSS_WITH_RC2_56_CBC_SHA SSL_RSA_EXPORT1024_WITH_RC4_56_SHA SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA SSL_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 SSL_RSA_EXPORT1024_WITH_RC4_56_MD5 SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 SSL_RSA_EXPORT_WITH_RC4_40_MD5 compression methods NULL 1 2 0.0068 (0.0006) S>C Handshake ServerHello Version 3.0 session_id[32]= f2 6e ab c1 e6 db fa 55 4d 77 97 be 0d 28 23 fe 53 8a d5 3b 31 58 1d 93 35 65 10 a9 06 6b a2 a6 cipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA compressionMethod NULL 1 3 0.0846 (0.0778) S>C Handshake Certificate 1 4 0.0848 (0.0001) S>C Handshake ServerKeyExchange 1 5 0.0848 (0.0000) S>C Handshake ServerHelloDone 1 6 0.2475 (0.1627) C>S Handshake ClientKeyExchange DiffieHellmanClientPublicValue[128]= 3c 8f 0f 93 8a 3a 1e 5c 07 cf 40 2f 7d bf 25 7a e8 2b ba 54 46 d5 54 40 22 90 38 f2 88 c3 62 8a ec b1 b7 f1 06 6d fa ba 46 dd f1 92 5f 44 18 44 8e df 33 30 64 79 e0 77 07 1f bc 10 dc 0d 6e 4b 4d 68 01 af 4a bf 83 62 de 87 d7 98 6c e3 9b af a2 a6 60 67 18 46 89 29 fa 1a 72 df 92 2d 9e 4f 2c b2 02 b3 ef b7 03 07 49 69 c5 b2 37 ae a1 0e 10 e1 79 25 a4 70 02 15 69 d9 47 2c c8 48 23 67 1 7 0.2475 (0.0000) C>S ChangeCipherSpec 1 8 0.2475 (0.0000) C>S Handshake 1 9 0.3239 (0.0763) S>C ChangeCipherSpec 1 10 0.3239 (0.0000) S>C Handshake 1 11 0.3266 (0.0027) C>S application_data 1 12 0.3566 (0.0299) S>C application_data 1 13 0.3571 (0.0005) S>C Alert 1 0.3574 (0.0003) S>C TCP FIN New TCP connection #2: 127.0.0.2(9999) <-> localhost(443) 2 1 0.0039 (0.0039) C>S Handshake ClientHello Version 3.0 resume [32]= f2 6e ab c1 e6 db fa 55 4d 77 97 be 0d 28 23 fe 53 8a d5 3b 31 58 1d 93 35 65 10 a9 06 6b a2 a6 cipher suites SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_RC4_128_SHA SSL_RSA_WITH_IDEA_CBC_SHA SSL_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_MD5 SSL_DHE_DSS_WITH_RC2_56_CBC_SHA SSL_RSA_EXPORT1024_WITH_RC4_56_SHA SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA SSL_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 SSL_RSA_EXPORT1024_WITH_RC4_56_MD5 SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 SSL_RSA_EXPORT_WITH_RC4_40_MD5 compression methods NULL 2 2 0.0055 (0.0016) S>C Handshake ServerHello Version 3.0 session_id[32]= f2 6e ab c1 e6 db fa 55 4d 77 97 be 0d 28 23 fe 53 8a d5 3b 31 58 1d 93 35 65 10 a9 06 6b a2 a6 cipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA compressionMethod NULL 2 3 0.0055 (0.0000) S>C ChangeCipherSpec 2 4 0.0055 (0.0000) S>C Handshake 2 5 0.0066 (0.0010) C>S ChangeCipherSpec 2 6 0.0066 (0.0000) C>S Handshake 1 14 0.3698 (0.0124) C>S Alert 1 0.3702 (0.0004) C>S TCP FIN 2 7 0.0996 (0.0930) C>S application_data 2 8 0.1224 (0.0227) S>C application_data 2 9 0.1244 (0.0019) S>C Alert 2 10 0.1248 (0.0004) C>S Alert 2 0.1254 (0.0005) C>S TCP FIN 2 0.1300 (0.0046) S>C TCP FIN M2Crypto-0.22.6rc4/demo/ssl/socklib.py0000664000175000017500000000251112607370517017651 0ustar matejmatej00000000000000""" socklib provides a way to transparently replace socket.ssl with M2Crypto.SSL.Connection. Usage: Import socklib before the 3rd party module that uses socket.ssl. Also, call socketlib.setSSLContextFactory() to set it up with a way to get secure SSL contexts. Copyright (c) 2007 Open Source Applications Foundation. All rights reserved. """ sslContextFactory = None def setSSLContextFactory(factory): global sslContextFactory sslContextFactory = factory from M2Crypto.SSL import Connection, Checker import socket class ssl_socket(socket.socket): def connect(self, addr, *args): self.addr = addr return super(ssl_socket, self).connect(addr, *args) def close(self): if hasattr(self, 'conn'): self.conn.close() socket.socket.close(self) def ssl(sock): sock.conn = Connection(ctx=sslContextFactory(), sock=sock) sock.conn.addr = sock.addr sock.conn.setup_ssl() sock.conn.set_connect_state() sock.conn.connect_ssl() check = getattr(sock.conn, 'postConnectionCheck', sock.conn.clientPostConnectionCheck) if check is not None: if not check(sock.conn.get_peer_cert(), sock.conn.addr[0]): raise Checker.SSLVerificationError, 'post connection check failed' return sock.conn socket.socket = ssl_socket socket.ssl = ssl M2Crypto-0.22.6rc4/demo/ssl/somelib.py0000664000175000017500000000117512605232411017646 0ustar matejmatej00000000000000""" Sample 3rd party lib to use with socklib and myapp. Copyright (c) 2007 Open Source Applications Foundation. All rights reserved. """ # This represents some 3rd party library we don't want to modify import socket class HttpsGetSlash(object): def __init__(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def get(self, host, port): self.socket.connect((host, port)) ssl_sock = socket.ssl(self.socket) ssl_sock.write('GET / HTTP/1.0\n\n') print ssl_sock.read() self.socket.close()M2Crypto-0.22.6rc4/demo/ssl/ss.py0000664000175000017500000000071412605232411016637 0ustar matejmatej00000000000000#!/usr/bin/env python import os, popen2, time from socket import * def main0(): cin, cout = popen2.popen2('openssl s_server') cout.write('Q\n') cout.flush() s = socket(AF_INET, SOCK_STREAM) s.connect(('', 4433)) s.close() def main(): pid = os.fork() if pid: time.sleep(1) os.kill(pid, 1) os.waitpid(pid, 0) else: os.execvp('openssl', ('s_server',)) if __name__ == '__main__': main() M2Crypto-0.22.6rc4/demo/ssl/twistedsslclient.py0000775000175000017500000000224012607370517021631 0ustar matejmatej00000000000000#!/usr/bin/env python """ Demonstrates M2Crypto.SSL.TwistedProtocolWrapper Copyright (c) 2005 Open Source Applications Foundation. All rights reserved. """ import twisted.internet.protocol as protocol import twisted.protocols.basic as basic import twisted.internet.reactor as reactor import M2Crypto.SSL.TwistedProtocolWrapper as wrapper import M2Crypto.SSL as SSL class EchoClient(basic.LineReceiver): def connectionMade(self): self.sendLine('Hello World!') def lineReceived(self, line): print 'received: "%s"' % line self.transport.loseConnection() class EchoClientFactory(protocol.ClientFactory): protocol = EchoClient def clientConnectionFailed(self, connector, reason): print 'connection failed' reactor.stop() def clientConnectionLost(self, connector, reason): print 'connection lost' reactor.stop() class ContextFactory: def getContext(self): return SSL.Context() if __name__ == '__main__': factory = EchoClientFactory() wrapper.connectSSL('localhost', 8000, factory, ContextFactory()) reactor.run() # This will block until reactor.stop() is called M2Crypto-0.22.6rc4/demo/ssl/twistedsslserver.py0000775000175000017500000000160712605232411021653 0ustar matejmatej00000000000000#!/usr/bin/env python """ Demonstrates M2Crypto.SSL.TwistedProtocolWrapper Copyright (c) 2005 Open Source Applications Foundation. All rights reserved. """ import sys import M2Crypto.SSL as SSL import M2Crypto.SSL.TwistedProtocolWrapper as wrapper import twisted.internet.protocol as protocol import twisted.internet.reactor as reactor import twisted.python.log as log class Echo(protocol.Protocol): def dataReceived(self, data): print 'received: "%s"' % data self.transport.write(data) def connectionMade(self): print 'connection made' class ContextFactory: def getContext(self): ctx = SSL.Context() ctx.load_cert('server.pem') return ctx if __name__ == '__main__': log.startLogging(sys.stdout) factory = protocol.Factory() factory.protocol = Echo wrapper.listenSSL(8000, factory, ContextFactory()) reactor.run() M2Crypto-0.22.6rc4/demo/ssl/xmlrpc_cli.py0000664000175000017500000000130312605232411020341 0ustar matejmatej00000000000000#!/usr/bin/env python """Demonstration of M2Crypto.xmlrpclib2. Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.""" from M2Crypto import Rand from M2Crypto.m2xmlrpclib import Server, SSL_Transport def ZServerSSL(): # Server is Zope-2.6.4 on ZServerSSL/0.12. zs = Server('https://127.0.0.1:8443/', SSL_Transport()) print zs.propertyMap() def xmlrpc_srv(): # Server is ../https/START_xmlrpc.py or ./xmlrpc_srv.py. zs = Server('https://127.0.0.1:39443', SSL_Transport()) print zs.Testing(1, 2, 3) print zs.BringOn('SOAP') if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) #ZServerSSL() xmlrpc_srv() Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/ssl/xmlrpc_srv.py0000664000175000017500000000136612607370517020431 0ustar matejmatej00000000000000"""Server demonstration of M2Crypto.xmlrpclib2. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" # M2Crypto from M2Crypto import DH, SSL from echod_lib import init_context # /F's xmlrpcserver.py. from xmlrpcserver import RequestHandler class xmlrpc_handler(RequestHandler): def call(self, method, params): print "XMLRPC call:", method, params return params def finish(self): self.request.set_shutdown(SSL.SSL_RECEIVED_SHUTDOWN | SSL.SSL_SENT_SHUTDOWN) self.request.close() if __name__ == '__main__': ctx = init_context('sslv23', 'server.pem', 'ca.pem', SSL.verify_none) ctx.set_tmp_dh('dh1024.pem') s = SSL.ThreadingSSLServer(('', 9443), xmlrpc_handler, ctx) s.serve_forever() M2Crypto-0.22.6rc4/demo/tinderbox/0000775000175000017500000000000012613362233017040 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/tinderbox/build_lib.py0000664000175000017500000000764512605232411021346 0ustar matejmatej00000000000000# Copyright (c) 2006-2007 Open Source Applications Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Trimmed down for M2Crypto build purposes import os, sys import glob import fnmatch import shutil import fileinput import errno import subprocess import killableprocess import tempfile _logFilename = 'tbox.log' _logPrefix = '' _logFile = None _logEcho = True _logEchoErrors = False def initLog(filename, prefix='', echo=True, echoErrors=False): """ Initialize log file and store log parameters Note: initLog assumes it is called only once per program """ global _logFilename, _logPrefix, _logFile, _logEcho, _logEchoErrors _logFilename = filename or _logFilename _logEcho = echo _logEchoErrors = echoErrors _logPrefix = prefix try: _logFile = open(_logFilename, 'w+') result = True except: result = False return result def closeLog(): """Need to close log to flush all data.""" _logFile.close() def log(msg, error=False, newline='\n'): """ Output log message to an open log file or to StdOut """ echo = _logEcho if _logFile is None: if error or _logEcho: echo = True else: _logFile.write('%s%s%s' % (_logPrefix, msg, newline)) if error and _logEchoErrors: sys.stderr.write('%s%s%s' % (_logPrefix, msg, newline)) if echo: sys.stdout.write('%s%s%s' % (_logPrefix, msg, newline)) sys.stdout.flush() def setpgid_preexec_fn(): os.setpgid(0, 0) def runCommand(cmd, env=None, timeout=-1, logger=log, ignorepreexec=False): """ Execute the given command and log all output Success and failure codes: >>> runCommand(['true']) 0 >>> runCommand(['false']) 1 Interleaved stdout and stderr messages: >>> runCommand(['python', '-c', r'print 1;import sys;sys.stdout.flush();print >>sys.stderr, 2;print 3']) 1 2 3 0 Now with timeout: >>> runCommand(['python', '-c', r'print 1;import sys;sys.stdout.flush();print >>sys.stderr, 2;print 3'], timeout=5) 1 2 3 0 Setting environment variable: >>> runCommand(['python', '-c', 'import os;print os.getenv("ENVTEST")'], env={'ENVTEST': '42'}) 42 0 Timeout: >>> runCommand(['sleep', '60'], timeout=5) -9 """ redirect = True if logger == log and _logFile is None: redirect = False else: if timeout == -1: output = subprocess.PIPE else: output = tempfile.TemporaryFile() if ignorepreexec: preexec_fn = None else: preexec_fn = setpgid_preexec_fn if redirect: p = killableprocess.Popen(cmd, env=env, stdin=subprocess.PIPE, stdout=output, stderr=subprocess.STDOUT, preexec_fn=preexec_fn) else: p = killableprocess.Popen(cmd, env=env, stdin=subprocess.PIPE, preexec_fn=preexec_fn) try: if timeout == -1 and redirect: for line in p.stdout: logger(line[:-1]) p.wait(timeout=timeout, group=True) except KeyboardInterrupt: try: p.kill(group=True) except OSError: p.wait(30) if timeout != -1 and redirect: output.seek(0) for line in output: logger(line[:-1]) return p.returncode M2Crypto-0.22.6rc4/demo/tinderbox/killableprocess.py0000664000175000017500000001753612607370517022613 0ustar matejmatej00000000000000# killableprocess - subprocesses which can be reliably killed # # Parts of this module are copied from the subprocess.py file contained # in the Python distribution. # # Copyright (c) 2003-2004 by Peter Astrand # # Additions and modifications written by Benjamin Smedberg # are Copyright (c) 2006 by the Mozilla Foundation # # # By obtaining, using, and/or copying this software and/or its # associated documentation, you agree that you have read, understood, # and will comply with the following terms and conditions: # # Permission to use, copy, modify, and distribute this software and # its associated documentation for any purpose and without fee is # hereby granted, provided that the above copyright notice appears in # all copies, and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of the # author not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. # # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. # IN NO EVENT SHALL THE AUTHOR 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. r"""killableprocess - Subprocesses which can be reliably killed This module is a subclass of the builtin "subprocess" module. It allows processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method. It also adds a timeout argument to Wait() for a limited period of time before forcefully killing the process. Note: On Windows, this module requires Windows 2000 or higher (no support for Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with Python 2.5+ or available from http://python.net/crew/theller/ctypes/ """ import subprocess import sys import os import time import types try: from subprocess import CalledProcessError except ImportError: # Python 2.4 doesn't implement CalledProcessError class CalledProcessError(Exception): """This exception is raised when a process run by check_call() returns a non-zero exit status. The exit status will be stored in the returncode attribute.""" def __init__(self, returncode, cmd): self.returncode = returncode self.cmd = cmd def __str__(self): return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) mswindows = (sys.platform == "win32") if mswindows: import winprocess else: import signal def call(*args, **kwargs): waitargs = {} if "timeout" in kwargs: waitargs["timeout"] = kwargs.pop("timeout") return Popen(*args, **kwargs).wait(**waitargs) def check_call(*args, **kwargs): """Call a program with an optional timeout. If the program has a non-zero exit status, raises a CalledProcessError.""" retcode = call(*args, **kwargs) if retcode: cmd = kwargs.get("args") if cmd is None: cmd = args[0] raise CalledProcessError(retcode, cmd) if not mswindows: def DoNothing(*args): pass class Popen(subprocess.Popen): if mswindows: def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): if not isinstance(args, types.StringTypes): args = subprocess.list2cmdline(args) if startupinfo is None: startupinfo = winprocess.STARTUPINFO() if None not in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES startupinfo.hStdInput = int(p2cread) startupinfo.hStdOutput = int(c2pwrite) startupinfo.hStdError = int(errwrite) if shell: startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW startupinfo.wShowWindow = winprocess.SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = comspec + " /c " + args # We create a new job for this process, so that we can kill # the process and any sub-processes self._job = winprocess.CreateJobObject() creationflags |= winprocess.CREATE_SUSPENDED creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT hp, ht, pid, tid = winprocess.CreateProcess( executable, args, None, None, # No special security 1, # Must inherit handles! creationflags, winprocess.EnvironmentBlock(env), cwd, startupinfo) self._child_created = True self._handle = hp self._thread = ht self.pid = pid winprocess.AssignProcessToJobObject(self._job, hp) winprocess.ResumeThread(ht) if p2cread is not None: p2cread.Close() if c2pwrite is not None: c2pwrite.Close() if errwrite is not None: errwrite.Close() def kill(self, group=True): """Kill the process. If group=True, all sub-processes will also be killed.""" if mswindows: if group: winprocess.TerminateJobObject(self._job, 127) else: winprocess.TerminateProcess(self._handle, 127) self.returncode = 127 else: if sys.platform == 'cygwin': cmd = "taskkill /f /pid " + str(self.pid) if group: cmd += " /t" os.system(cmd) elif group: os.killpg(self.pid, signal.SIGKILL) else: os.kill(self.pid, signal.SIGKILL) self.returncode = -9 def wait(self, timeout=-1, group=True): """Wait for the process to terminate. Returns returncode attribute. If timeout seconds are reached and the process has not terminated, it will be forcefully killed. If timeout is -1, wait will not time out.""" if self.returncode is not None: return self.returncode if mswindows: if timeout != -1: timeout = timeout * 1000 rc = winprocess.WaitForSingleObject(self._handle, timeout) if rc == winprocess.WAIT_TIMEOUT: self.kill(group) else: self.returncode = winprocess.GetExitCodeProcess(self._handle) else: if timeout == -1: subprocess.Popen.wait(self) return self.returncode starttime = time.time() # Make sure there is a signal handler for SIGCHLD installed oldsignal = signal.signal(signal.SIGCHLD, DoNothing) while time.time() < starttime + timeout - 0.01: pid, sts = os.waitpid(self.pid, os.WNOHANG) if pid != 0: self._handle_exitstatus(sts) signal.signal(signal.SIGCHLD, oldsignal) return self.returncode # time.sleep is interrupted by signals (good!) newtimeout = timeout - time.time() + starttime time.sleep(newtimeout) self.kill(group) signal.signal(signal.SIGCHLD, oldsignal) subprocess.Popen.wait(self) return self.returncode M2Crypto-0.22.6rc4/demo/tinderbox/slave.py0000775000175000017500000001141412607370517020537 0ustar matejmatej00000000000000#!/usr/bin/env python # """ This is a sample Tinderbox2 buildslave script. NOTE: WAIT at least 6 minutes after the last build before starting the next build! Create config.ini file with the following contents: [build] name = identify your build slave, for example Ubuntu 8.04 32-bit ;;optional fields: ;;uname = uname -a ;;swig = swig -version ;;cc = gcc --version ;;openssl = openssl version ;;python = python --version ;;clean = rm -fr m2crypto ;;svn = svn co http://svn.osafoundation.org/m2crypto/trunk m2crypto ;;patch = ;;build = python setup.py clean --all build ;; OR another way to do tests without setuptools: ;;build = PYTHONPATH=build/lib-something python tests/alltests.py ;;test = python setup.py test ;;wait = 3600 ;;timeout = 180 [email] from = your email to = Email Heikki Toivonen to get the address user = smtp username password = smtp password server = smtp server port = smtp port """ import time, smtplib, os, ConfigParser, tempfile import build_lib as bl # Change to True when you are troubleshooting this build script debug_script = False # These commands assume we are running on a unix-like system where default # build options work and all prerequisites are installed and in PATH etc. DEFAULT_COMMANDS = { 'uname': ['uname', '-a'], 'swig': ['swig', '-version'], 'cc': ['gcc', '--version'], 'openssl': ['openssl', 'version'], 'python': ['python', '--version'], 'clean': ['rm', '-rf', 'm2crypto'], 'svn': ['svn', 'co', 'http://svn.osafoundation.org/m2crypto/trunk', 'm2crypto'], 'patch': [], 'build': ['python', 'setup.py', 'clean', '--all', 'build'], 'test': ['python', 'setup.py', 'test'] } def load_config(cfg='config.ini'): config = {} cp = ConfigParser.ConfigParser() cp.read(cfg) for section in cp.sections(): for option in cp.options(section): config[option] = cp.get(section, option).strip() return config # XXX copied from test_ssl def zap_servers(): s = 's_server' fn = tempfile.mktemp() cmd = 'ps | egrep %s > %s' % (s, fn) os.system(cmd) f = open(fn) while 1: ps = f.readline() if not ps: break chunk = string.split(ps) pid, cmd = chunk[0], chunk[4] if cmd == s: os.kill(int(pid), 1) f.close() os.unlink(fn) def build(commands, config): status = 'success' cwd = os.getcwd() timeout = int(config.get('timeout') or 180) bl.initLog('tbox.log', echo=debug_script) starttime = int(time.time()) for command in commands: cmd = config.get(command) if not cmd: cmd = DEFAULT_COMMANDS[command] if not cmd: continue else: cmd = cmd.split() bl.log('*** %s, timeout=%ds' % (' '.join(cmd), timeout)) exit_code = bl.runCommand(cmd, timeout=timeout) if exit_code: bl.log('*** error exit code = %d' % exit_code) if command == 'test': status = 'test_failed' if os.name != 'nt': try: # If tests were killed due to timeout, we may have left # openssl processes running, so try killing zap_servers() except Exception, e: bl.log('*** error: tried to zap_servers: ' + str(e)) else: status = 'build_failed' break if command == 'svn': os.chdir('m2crypto') timenow = int(time.time()) bl.closeLog() os.chdir(cwd) return 'tbox.log', starttime, timenow, status def email(logpath, starttime, timenow, status, config): msg = """From: %(from)s To: %(to)s Subject: tree: M2Crypto tinderbox: tree: M2Crypto tinderbox: starttime: %(starttime)d tinderbox: timenow: %(timenow)d tinderbox: status: %(status)s tinderbox: buildname: %(buildname)s tinderbox: errorparser: unix tinderbox: END """ % {'from': config['from'], 'to': config['to'], 'starttime': starttime, 'timenow': timenow, 'status': status, 'buildname': config['name']} msg += open(logpath).read() server = smtplib.SMTP(host=config['server'], port=int(config['port'])) if debug_script: server.set_debuglevel(1) server.starttls() # if your server supports STARTTLS if config.get('user'): server.login(config['user'], config['password']) server.sendmail(config['from'], config['to'], msg) server.quit() if __name__ == '__main__': config = load_config() commands = ['uname', 'swig', 'cc', 'openssl', 'python', 'clean', 'svn', 'patch', 'build', 'test'] logpath, starttime, timenow, status = build(commands, config) email(logpath, starttime, timenow, status, config) M2Crypto-0.22.6rc4/demo/tinderbox/winprocess.py0000664000175000017500000002252212607370517021620 0ustar matejmatej00000000000000# A module to expose various thread/process/job related structures and # methods from kernel32 # # The MIT License # # Copyright (c) 2006 the Mozilla Foundation # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD LPVOID = c_void_p LPBYTE = POINTER(BYTE) LPDWORD = POINTER(DWORD) def ErrCheckBool(result, func, args): """errcheck function for Windows functions that return a BOOL True on success""" if not result: raise WinError() return args # CloseHandle() CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE) CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32)) CloseHandle.errcheck = ErrCheckBool # AutoHANDLE class AutoHANDLE(HANDLE): """Subclass of HANDLE which will call CloseHandle() on deletion.""" def Close(self): if self.value: CloseHandle(self) self.value = 0 def __del__(self): self.Close() def __int__(self): return self.value def ErrCheckHandle(result, func, args): """errcheck function for Windows functions that return a HANDLE.""" if not result: raise WinError() return AutoHANDLE(result) # PROCESS_INFORMATION structure class PROCESS_INFORMATION(Structure): _fields_ = [("hProcess", HANDLE), ("hThread", HANDLE), ("dwProcessID", DWORD), ("dwThreadID", DWORD)] def __init__(self): Structure.__init__(self) self.cb = sizeof(self) LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) # STARTUPINFO structure class STARTUPINFO(Structure): _fields_ = [("cb", DWORD), ("lpReserved", LPWSTR), ("lpDesktop", LPWSTR), ("lpTitle", LPWSTR), ("dwX", DWORD), ("dwY", DWORD), ("dwXSize", DWORD), ("dwYSize", DWORD), ("dwXCountChars", DWORD), ("dwYCountChars", DWORD), ("dwFillAttribute", DWORD), ("dwFlags", DWORD), ("wShowWindow", WORD), ("cbReserved2", WORD), ("lpReserved2", LPBYTE), ("hStdInput", HANDLE), ("hStdOutput", HANDLE), ("hStdError", HANDLE) ] LPSTARTUPINFO = POINTER(STARTUPINFO) STARTF_USESHOWWINDOW = 0x01 STARTF_USESIZE = 0x02 STARTF_USEPOSITION = 0x04 STARTF_USECOUNTCHARS = 0x08 STARTF_USEFILLATTRIBUTE = 0x10 STARTF_RUNFULLSCREEN = 0x20 STARTF_FORCEONFEEDBACK = 0x40 STARTF_FORCEOFFFEEDBACK = 0x80 STARTF_USESTDHANDLES = 0x100 # EnvironmentBlock class EnvironmentBlock: """An object which can be passed as the lpEnv parameter of CreateProcess. It is initialized with a dictionary.""" def __init__(self, dict): if not dict: self._as_parameter_ = None else: values = ["%s=%s" % (key, value) for (key, value) in dict.iteritems()] values.append("") self._as_parameter_ = LPCWSTR("\0".join(values)) # CreateProcess() CreateProcessProto = WINFUNCTYPE(BOOL, # Return type LPCWSTR, # lpApplicationName LPWSTR, # lpCommandLine LPVOID, # lpProcessAttributes LPVOID, # lpThreadAttributes BOOL, # bInheritHandles DWORD, # dwCreationFlags LPVOID, # lpEnvironment LPCWSTR, # lpCurrentDirectory LPSTARTUPINFO, # lpStartupInfo LPPROCESS_INFORMATION # lpProcessInformation ) CreateProcessFlags = ((1, "lpApplicationName", None), (1, "lpCommandLine"), (1, "lpProcessAttributes", None), (1, "lpThreadAttributes", None), (1, "bInheritHandles", True), (1, "dwCreationFlags", 0), (1, "lpEnvironment", None), (1, "lpCurrentDirectory", None), (1, "lpStartupInfo"), (2, "lpProcessInformation")) def ErrCheckCreateProcess(result, func, args): ErrCheckBool(result, func, args) # return a tuple (hProcess, hThread, dwProcessID, dwThreadID) pi = args[9] return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32), CreateProcessFlags) CreateProcess.errcheck = ErrCheckCreateProcess CREATE_BREAKAWAY_FROM_JOB = 0x01000000 CREATE_DEFAULT_ERROR_MODE = 0x04000000 CREATE_NEW_CONSOLE = 0x00000010 CREATE_NEW_PROCESS_GROUP = 0x00000200 CREATE_NO_WINDOW = 0x08000000 CREATE_SUSPENDED = 0x00000004 CREATE_UNICODE_ENVIRONMENT = 0x00000400 DEBUG_ONLY_THIS_PROCESS = 0x00000002 DEBUG_PROCESS = 0x00000001 DETACHED_PROCESS = 0x00000008 # CreateJobObject() CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type LPVOID, # lpJobAttributes LPCWSTR # lpName ) CreateJobObjectFlags = ((1, "lpJobAttributes", None), (1, "lpName", None)) CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32), CreateJobObjectFlags) CreateJobObject.errcheck = ErrCheckHandle # AssignProcessToJobObject() AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type HANDLE, # hJob HANDLE # hProcess ) AssignProcessToJobObjectFlags = ((1, "hJob"), (1, "hProcess")) AssignProcessToJobObject = AssignProcessToJobObjectProto( ("AssignProcessToJobObject", windll.kernel32), AssignProcessToJobObjectFlags) AssignProcessToJobObject.errcheck = ErrCheckBool # ResumeThread() def ErrCheckResumeThread(result, func, args): if result == -1: raise WinError() return args ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type HANDLE # hThread ) ResumeThreadFlags = ((1, "hThread"),) ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32), ResumeThreadFlags) ResumeThread.errcheck = ErrCheckResumeThread # TerminateJobObject() TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type HANDLE, # hJob UINT # uExitCode ) TerminateJobObjectFlags = ((1, "hJob"), (1, "uExitCode", 127)) TerminateJobObject = TerminateJobObjectProto( ("TerminateJobObject", windll.kernel32), TerminateJobObjectFlags) TerminateJobObject.errcheck = ErrCheckBool # WaitForSingleObject() WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type HANDLE, # hHandle DWORD, # dwMilliseconds ) WaitForSingleObjectFlags = ((1, "hHandle"), (1, "dwMilliseconds", -1)) WaitForSingleObject = WaitForSingleObjectProto( ("WaitForSingleObject", windll.kernel32), WaitForSingleObjectFlags) INFINITE = -1 WAIT_TIMEOUT = 0x0102 WAIT_OBJECT_0 = 0x0 WAIT_ABANDONED = 0x0080 # GetExitCodeProcess() GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type HANDLE, # hProcess LPDWORD, # lpExitCode ) GetExitCodeProcessFlags = ((1, "hProcess"), (2, "lpExitCode")) GetExitCodeProcess = GetExitCodeProcessProto( ("GetExitCodeProcess", windll.kernel32), GetExitCodeProcessFlags) GetExitCodeProcess.errcheck = ErrCheckBool M2Crypto-0.22.6rc4/demo/x509/0000775000175000017500000000000012613362233015547 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/demo/x509/ca.py0000664000175000017500000000622612607370517016521 0ustar matejmatej00000000000000#!/usr/bin/env python """ How to create a CA certificate with Python. WARNING: This sample only demonstrates how to use the objects and methods, not how to create a safe and correct certificate. Copyright (c) 2004 Open Source Applications Foundation. Author: Heikki Toivonen """ from M2Crypto import RSA, X509, EVP, m2, Rand, Err # XXX Do I actually need more keys? # XXX Check return values from functions def generateRSAKey(): return RSA.gen_key(2048, m2.RSA_F4) def makePKey(key): pkey = EVP.PKey() pkey.assign_rsa(key) return pkey def makeRequest(pkey): req = X509.Request() req.set_version(2) req.set_pubkey(pkey) name = X509.X509_Name() name.CN = 'My CA, Inc.' req.set_subject_name(name) ext1 = X509.new_extension('subjectAltName', 'DNS:foobar.example.com') ext2 = X509.new_extension('nsComment', 'Hello there') extstack = X509.X509_Extension_Stack() extstack.push(ext1) extstack.push(ext2) assert(extstack[1].get_name() == 'nsComment') req.add_extensions(extstack) req.sign(pkey, 'sha1') return req def makeCert(req, caPkey): pkey = req.get_pubkey() #woop = makePKey(generateRSAKey()) #if not req.verify(woop.pkey): if not req.verify(pkey): # XXX What error object should I use? raise ValueError, 'Error verifying request' sub = req.get_subject() # If this were a real certificate request, you would display # all the relevant data from the request and ask a human operator # if you were sure. Now we just create the certificate blindly based # on the request. cert = X509.X509() # We know we are making CA cert now... # Serial defaults to 0. cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) issuer = X509.X509_Name() issuer.CN = 'The Issuer Monkey' issuer.O = 'The Organization Otherwise Known as My CA, Inc.' cert.set_issuer(issuer) cert.set_pubkey(pkey) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) days = 30 m2.x509_gmtime_adj(notAfter, 60*60*24*days) cert.add_ext( X509.new_extension('subjectAltName', 'DNS:foobar.example.com')) ext = X509.new_extension('nsComment', 'M2Crypto generated certificate') ext.set_critical(0)# Defaults to non-critical, but we can also set it cert.add_ext(ext) cert.sign(caPkey, 'sha1') assert(cert.get_ext('subjectAltName').get_name() == 'subjectAltName') assert(cert.get_ext_at(0).get_name() == 'subjectAltName') assert(cert.get_ext_at(0).get_value() == 'DNS:foobar.example.com') return cert def ca(): key = generateRSAKey() pkey = makePKey(key) req = makeRequest(pkey) cert = makeCert(req, pkey) return (cert, pkey) if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) rsa = generateRSAKey() pkey = makePKey(rsa) req = makeRequest(pkey) print req.as_text() cert = makeCert(req, pkey) print cert.as_text() print cert.as_pem() cert.save_pem('my_ca_cert.pem') rsa.save_key('my_key.pem', 'aes_256_cbc') Rand.save_file('../randpool.dat') M2Crypto-0.22.6rc4/demo/x509/certdata2pem.py0000775000175000017500000000317412605232411020477 0ustar matejmatej00000000000000#!/usr/bin/env python """ Small utility to convert the Mozilla-format certificates (/mozilla/security/nss/lib/ckfw/builtins/certdata.txt in the Mozilla CVS) into PEM. Got the idea from http://curl.haxx.se/docs/parse-certs.txt. Copyright (c) 2007 Open Source Applications Foundation. """ import array from M2Crypto import X509 counter = 0 value = None name = None out = open('cacert.pem', 'wb') for line in open('certdata.txt'): line = line.strip() if line.startswith('CKA_LABEL'): assert value is None label_encoding, name, dummy = line.split('"') label, encoding = label_encoding.split() assert encoding == 'UTF8' elif line == 'CKA_VALUE MULTILINE_OCTAL': assert name is not None value = array.array('c') elif value is not None and line == 'END': assert name is not None print 'Writing ' + name x509 = X509.load_cert_string(value.tostring(), X509.FORMAT_DER) if not x509.verify(): print ' Skipping ' + name + ' since it does not verify' name = None value = None continue counter += 1 out.write(name + '\n' + '=' * len(name) + '\n\n') out.write('SHA1 Fingerprint=' + x509.get_fingerprint('sha1') + '\n') out.write(x509.as_text()) out.write(x509.as_pem()) out.write('\n') name = None value = None elif value is not None: assert name is not None for number in line.split('\\'): if not number: continue value.append(chr(int(number, 8))) print 'Wrote %d certificates' % counter M2Crypto-0.22.6rc4/demo/x509/client2.pem0000664000175000017500000000402012605232411017601 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDDjCCAnegAwIBAgIBAzANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n cHNAcG9zdDEuY29tMB4XDTAwMTEyMDEzMDMwNVoXDTAyMTEyMDEzMDMwNVowWzEL MAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRowGAYDVQQDExFNMkNyeXB0 byBDbGllbnQgMjEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20wXDANBgkq hkiG9w0BAQEFAANLADBIAkEAn9qneRYTKPokme3obiJa2NTz1Z2kcF3NHVh60Qod /TV/q4olPrZdFR2TDWt63Lgnygcsgf3u9pnhcEGk6IvntwIDAQABo4IBBDCCAQAw CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy dGlmaWNhdGUwHQYDVR0OBBYEFDKWFe6VWMhtRTE3/78+hAnSGxmvMIGlBgNVHSME gZ0wgZqAFPuHI2nrnDqTFeXFvylRT/7tKDgBoX+kfTB7MQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n cHNAcG9zdDEuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBABpE9xt1Hlq2dQZUXHuX HI57vc2mlWnhhM0wnNhsNZFwfXRHCZOo/JJBhEIT3Rgyz0ErrbOr1SN96HNDKXOD z6bh4NxB5DZ9sRPKEBj66zDsWJVMlom+Lkeal+GkVy36vpAyP1r+cTXyc9M2Gw/o FBMinMHH/BXvF5GJ+UleheZe -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIIBOgIBAAJBAJ/ap3kWEyj6JJnt6G4iWtjU89WdpHBdzR1YetEKHf01f6uKJT62 XRUdkw1rety4J8oHLIH97vaZ4XBBpOiL57cCAwEAAQJANXfspprUo9MvpPEn2pbR Lk/kk2IcW510e0laI0uwBj50djfHqvsU5ccuVLrxowngLGrFmM3G4lnMknR2NvH8 0QIhAMsK0AwStUNM/KyvIMikHHBOE9PrK7ARgKvlKl+0ieWPAiEAyYwonIVAtr1f M8vmrc6TM2YxzSq4+jyYktaaNhYw11kCIA5pmhMBUPSSBm2LkNwtKgeewzGLw/If i+6nubZJbnBpAiEAvJQvy4PCsTkvQr+d7zJB+O2920IGId1gxMOXNtQ8jsECIGvn Uz54oonshmTg+Kj2DxnUKQEzFAmQLbtFslp1m47v -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- MIIBFTCBwAIBADBbMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xGjAY BgNVBAMTEU0yQ3J5cHRvIENsaWVudCAyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBv c3QxLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCf2qd5FhMo+iSZ7ehuIlrY 1PPVnaRwXc0dWHrRCh39NX+riiU+tl0VHZMNa3rcuCfKByyB/e72meFwQaToi+e3 AgMBAAGgADANBgkqhkiG9w0BAQQFAANBAHI5KXfL6kIRoNjR8G9/uKiPUt4uVBKF ecGp87M5t2a92Z0KpWOMXSHZ0LLQKqwWzALvWcPPIj6S8F6ENdwpfMk= -----END CERTIFICATE REQUEST----- M2Crypto-0.22.6rc4/demo/x509/demo1.py0000664000175000017500000000273212605232411017125 0ustar matejmatej00000000000000#!/usr/bin/env python """X.509 certificate manipulation and such. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" import os from M2Crypto import X509 from M2Crypto.EVP import MessageDigest def demo1(): print 'Test 1: As DER...' cert1 = X509.load_cert('server.pem') der1 = cert1.as_der() dgst1 = MessageDigest('sha1') dgst1.update(der1) print 'Using M2Crypto:\n', `dgst1.final()`, '\n' cert2 = os.popen('openssl x509 -inform pem -outform der -in server.pem') der2 = cert2.read() dgst2 = MessageDigest('sha1') dgst2.update(der2) print 'Openssl command line:\n', `dgst2.final()`, '\n' def demo2(): print 'Test 2: As text...' cert = X509.load_cert('client2.pem') print 'version ', cert.get_version() print 'serial# ', cert.get_serial_number() print 'not before ', cert.get_not_before() print 'not after ', cert.get_not_after() issuer = cert.get_issuer() #print 'issuer ', issuer print 'issuer.C ', `issuer.C` print 'issuer.SP ', `issuer.SP` print 'issuer.L ', `issuer.L` print 'issuer.O ', `issuer.O` print 'issuer.OU ', `issuer.OU` print 'issuer.CN ', `issuer.CN` print 'issuer.Email', `issuer.Email` print 'subject ', cert.get_subject() #print cert.as_text(), '\n' def demo3(): cert = X509.load_cert('server.pem') while 1: x = cert.get_subject() if __name__ == "__main__": #demo1() demo2() #demo3() M2Crypto-0.22.6rc4/demo/x509/proxy_destroy.py0000664000175000017500000000221712607370517021064 0ustar matejmatej00000000000000#!/usr/bin/env python ############################################################################ # Matt Rodriguez, LBNL MKRodriguez@lbl.gov ############################################################################ """ Script that destroys a proxy certificate file by overwriting its contents before the file is removed """ import proxylib import optparse, os USAGEHELP = "proxy_destroy.py file1 file2 Destroys files listed" JUNK = "LalalAlalaLalalALalalAlalaLalalALalalAlalaLalalALalalAlalaLalalA" def scrub_file(filename): """ Overwrite the file with junk, before removing it """ s = os.stat(filename) proxy_file = file(filename, "w") size = s.st_size while size > 64: proxy_file.write(JUNK) size -= 64 proxy_file.flush() proxy_file.close() os.remove(filename) def main(): parser = optparse.OptionParser() parser.set_usage(USAGEHELP) opts, args = parser.parse_args() if len(args) is 0: proxy_file = proxylib.get_proxy_filename() scrub_file(proxy_file) for proxy_file in args: scrub_file(proxy_file) if __name__ == "__main__": main() M2Crypto-0.22.6rc4/demo/x509/proxy_info.py0000664000175000017500000000366012607370517020331 0ustar matejmatej00000000000000#!/usr/bin/env python ############################################################################ # Matt Rodriguez, LBNL MKRodriguez@lbl.gov ############################################################################ """ script that displays information about a proxy certificate """ import proxylib import time, datetime, calendar import sys, optparse FILEHELP = "Location of the proxy." def print_info(proxy_cert): """ Print information about the proxy cert """ cert = proxy_cert.getcert() print "Subject: ", cert.get_subject().as_text() print "Issuer: ", cert.get_issuer().as_text() pubkey = cert.get_pubkey() size = pubkey.size() print "Strength: ", size * 8 after = cert.get_not_after() after_tuple = time.strptime(str(after),"%b %d %H:%M:%S %Y %Z") expires = calendar.timegm(after_tuple) now = datetime.timedelta(seconds=time.time()) expires = datetime.timedelta(seconds=expires) td = expires - now if td.days < 0: print "Time left: Proxy has expired." else: hours = td.seconds / 3600 hours += td.days * 24 minutes = (td.seconds % 3600) / 60 seconds = (td.seconds % 3600) % 60 print "Time left: %d:%d:%d" % (hours, minutes, seconds) fraction = round((float(td.seconds) / float(3600 * 24)), 1) print "Days left: ", str(td.days) + str(fraction)[1:] def main(): parser = optparse.OptionParser() parser.add_option("-f", "--file", dest="filename", help=FILEHELP) (opts, args) = parser.parse_args() filename = opts.filename if filename is None: proxyfile = proxylib.get_proxy_filename() else: proxyfile = filename proxy_cert = proxylib.Proxy() try: proxy_cert.read(proxyfile) except IOError: print "The file: " + proxyfile + " does not exist." sys.exit(0) print_info(proxy_cert) if __name__ == "__main__": main() M2Crypto-0.22.6rc4/demo/x509/proxy_init.py0000664000175000017500000000331412607370517020335 0ustar matejmatej00000000000000#!/usr/bin/env python ############################################################################ # Matt Rodriguez, LBNL MKRodriguez@lbl.gov ############################################################################ """ script that generates a proxy certificate """ import proxylib import optparse import sys OUTHELP = "Location of the new proxy cert." CERTHELP = "Location of user certificate." KEYHELP = "Location of the user key." VALIDHELP = "h:m Proxy certificate is valid for h hours and m minutes." FULLPROXY = "Creates a limited proxy" def main(): parser = optparse.OptionParser() parser.add_option('-o', '--output', dest='output', help=OUTHELP) parser.add_option('-c', '--cert' , dest='cert', help=CERTHELP) parser.add_option('-k', '--key', dest='key', help=KEYHELP) parser.add_option('-v', '--valid', dest='valid', help=VALIDHELP) parser.add_option('-l', '--limited', action="store_true", default=False, dest='limited', help=VALIDHELP) (opts, args) = parser.parse_args() kw = {} kw['cert'] = opts.cert kw['key'] = opts.key if opts.valid is None: valid_tuple = (12, 0) else: valid = opts.valid.split(':') valid_tuple = tuple(map(int, valid)) kw['valid'] = valid_tuple kw['full'] = not opts.limited try: proxy_factory = proxylib.ProxyFactory(kw) except IOError: print "Can't find usercert or userkey. Use the -c or -k arguments" sys.exit(0) proxy_factory.generate() proxy_cert = proxy_factory.getproxy() if opts.output is None: proxy_cert.write(proxylib.get_proxy_filename()) else: proxy_cert.write(opts.output) if __name__ == "__main__": main() M2Crypto-0.22.6rc4/demo/x509/proxylib.py0000664000175000017500000002507112607370517020005 0ustar matejmatej00000000000000############################################################################ # Matt Rodriguez, LBNL #Copyright (c) 2003, The Regents of the University of California, #through Lawrence Berkeley National Laboratory #(subject to receipt of any required approvals from the U.S. Dept. of Energy). #All rights reserved. ############################################################################ """ API to generated proxy certificates """ import os, sys import struct import re import time, calendar, datetime import_regex = re.compile(r"\s*libssl.so.0.9.8\s*") errstr = "You must have the openssl 0.9.8 libraries in your LD_LIBRARY_PATH""" try: from M2Crypto import BIO, X509, RSA, EVP, ASN1 except ImportError, ex: if import_regex.match(str(ex)): print errstr sys.exit(-1) else: raise ex MBSTRING_FLAG = 0x1000 MBSTRING_ASC = MBSTRING_FLAG | 1 KEY_USAGE_VALUE = "Digital Signature, Key Encipherment, Data Encipherment" PCI_VALUE_FULL = "critical, language:Inherit all" PCI_VALUE_LIMITED = "critical, language:1.3.6.1.4.1.3536.1.1.1.9" def create_write_file(fname, perm=0600): """ Creates a file to write to while avoiding a possible race condition. This is essential for writing out the proxy file. Need to make sure there is no pre-existing file. """ if os.path.exists(fname): os.remove(fname) # Make sure the file doesn't exist. Will throw an exception if # it does. This would only happen if the code is attacked. fd = os.open(fname, os.O_CREAT|os.O_EXCL|os.O_WRONLY, perm) f = os.fdopen(fd, 'w') return f class ProxyFactoryException(Exception): """ Base class for exceptions in the ProxyFactory class """ class Proxy: """ class that holds proxy certificate information, consisting of an issuer cert a user cert and a key for the user cert """ def __init__(self): self._key = None self._cert = None self._issuer = None def read(self, proxypath=None): """ reads in a proxy certificate information """ if proxypath is None: proxypath = get_proxy_filename() proxyfile = open(proxypath) bio = BIO.File(proxyfile) self._cert = X509.load_cert_bio(bio) self._key = RSA.load_key_bio(bio) self._issuer = X509.load_cert_bio(bio) def getcert(self): """ Returns a X509 instance """ return self._cert def getkey(self): """ Returns a RSA instance """ return self._key def getissuer(self): """ Returns a X509 instance """ return self._issuer def setcert(self, cert): """ Sets the user cert should be a X509 instance """ self._cert = cert def setkey(self, key): """ Sets the user key should be a RSA instance """ self._key = key def setissuer(self, issuer): """ Sets the issuer cert should be a X509 instance """ self._issuer = issuer def write(self, proxypath=None): """ Writes the proxy information to a file """ proxyfile = create_write_file(proxypath) bio = BIO.File(proxyfile) bio.write(self._cert.as_pem()) self._key.save_key_bio(bio, cipher=None) bio.write(self._issuer.as_pem()) bio.close() os.chmod(proxypath, 0600) class ProxyFactory: """ Creates proxies """ def __init__(self, kw={'cert':None,'key':None,'valid':(12,0),'full':True}): self._usercert = get_usercert(kw['cert']) self._userkey = get_userkey(kw['key']) self._proxycert = None self._proxykey = None self._valid = kw['valid'] self._full = kw['full'] def generate(self): """ generates a new proxy like grid-proxy-init """ if not self._check_valid(): raise ProxyFactoryException("The issuer cert is expired") if self._proxycert is None: self._proxycert = X509.X509() key = EVP.PKey() self._proxykey = RSA.gen_key(512, 65537) key.assign_rsa(self._proxykey, capture=0) self._proxycert.set_pubkey(key) self._proxycert.set_version(2) self._set_times() issuer_name = self._usercert.get_subject() self._proxycert.set_issuer_name(issuer_name) serial_number = self._make_serial_number(self._proxycert) self._proxycert.set_serial_number(serial_number) self._set_subject() sign_pk = EVP.PKey() sign_pk.assign_rsa(self._userkey) self._add_extensions() self._proxycert.sign(sign_pk, 'md5') def set_proxycert(self, proxycert): """ This method is useful if you don't want to pay the costs associated with generating a new key pair. """ self._proxycert = proxycert def getproxy(self): """ Return a proxy instance """ proxy = Proxy() proxy.setissuer(self._usercert) proxy.setcert(self._proxycert) proxy.setkey(self._proxykey) return proxy def _set_subject(self): """ Internal method that sets the subject name """ subject_name = X509.X509_Name() serial_number = self._make_serial_number(self._proxycert) issuer_name = self._usercert.get_subject() issuer_name_txt = issuer_name.as_text() seq = issuer_name_txt.split(",") for entry in seq: name_component = entry.split("=") subject_name.add_entry_by_txt(field=name_component[0].strip(), type=MBSTRING_ASC, entry=name_component[1],len=-1, loc=-1, set=0) subject_name.add_entry_by_txt(field="CN", type=MBSTRING_ASC, entry=str(serial_number), len=-1, loc=-1, set=0) self._proxycert.set_subject_name(subject_name) def _set_times(self): """ Internal function that sets the time on the proxy certificate """ not_before = ASN1.ASN1_UTCTIME() not_after = ASN1.ASN1_UTCTIME() not_before.set_time(int(time.time())) offset = (self._valid[0] * 3600) + (self._valid[1] * 60) not_after.set_time(int(time.time()) + offset ) self._proxycert.set_not_before(not_before) self._proxycert.set_not_after(not_after) def _make_serial_number(self, cert): """ Lifted from the globus code """ message_digest = EVP.MessageDigest('sha1') pubkey = cert.get_pubkey() der_encoding = pubkey.as_der() message_digest.update(der_encoding) digest = message_digest.final() digest_tuple = struct.unpack('BBBB', digest[:4]) sub_hash = long(digest_tuple[0] + (digest_tuple[1] + ( digest_tuple[2] + ( digest_tuple[3] >> 1) * 256 ) * 256) * 256) return sub_hash def _add_extensions(self): """ Internal method that adds the extensions to the certificate """ key_usage_ext = X509.new_extension("keyUsage", KEY_USAGE_VALUE, 1) self._proxycert.add_ext(key_usage_ext) if self._full: pci_ext = X509.new_extension("proxyCertInfo", PCI_VALUE_FULL, 1, 0) else: pci_ext = X509.new_extension("proxyCertInfo", PCI_VALUE_LIMITED, 1, 0) self._proxycert.add_ext(pci_ext) def _check_valid(self): """ Internal method that ensures the issuer cert has valid, not_before and not_after fields """ before_time = self._usercert.get_not_before() after_time = self._usercert.get_not_after() before_tuple = time.strptime(str(before_time), "%b %d %H:%M:%S %Y %Z") after_tuple = time.strptime(str(after_time), "%b %d %H:%M:%S %Y %Z") starts = datetime.timedelta(seconds=calendar.timegm(before_tuple)) expires = datetime.timedelta(seconds=calendar.timegm(after_tuple)) now = datetime.timedelta(seconds=time.time()) time_delta = expires - now #cert has expired if time_delta.days < 0: return False #cert is not yet valid, not likely but should still return False time_delta = now - starts if time_delta.days < 0: return False return True #Utility Functions def get_proxy_filename(): """ function that returns the default proxy path which is /tmp/x509up_uuid """ if os.name == 'posix': proxy_filename = "x509up_u" + (str(os.getuid())) proxypath = os.path.join("/tmp", proxy_filename) elif os.name == 'nt': username = os.getenv("USERNAME") if username is None: raise RuntimeError("""USERNAME is not set in environment. Can't determine proxy file location""") proxy_filename = "x509up_u" + username drive = os.path.splitdrive(os.getcwd())[0] proxydir = drive + os.sep + "temp" proxypath = os.path.join(proxydir, proxy_filename) else: except_string = """get_proxy_filename is not supported on this platform Try explicitly specifying the location of the proxyfile""" raise RuntimeError(except_string) return proxypath def get_usercert(certfile=None): """ function that returns a X509 instance which is the user cert that is expected to be a ~/.globus/usercert.pem A check is performed to ensure the certificate has valid before and after times. """ if certfile is None: certfile = open(os.path.join(os.getenv("HOME"), ".globus","usercert.pem")) else: certfile = open(certfile) bio = BIO.File(certfile) cert = X509.load_cert_bio(bio) return cert def get_userkey(keyfile=None): """ function that returns a X509 instance which is the user cert that is expected to be a ~/.globus/userkey.pem """ if keyfile is None: keyfile = open(os.path.join(os.getenv("HOME"), ".globus","userkey.pem")) else: keyfile = open(keyfile) bio = BIO.File(keyfile) key = RSA.load_key_bio(bio) return key M2Crypto-0.22.6rc4/demo/x509/server-expired.pem0000664000175000017500000000400012605232411021203 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDBjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzER MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n cHNAcG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzEL MAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhv c3QxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEB BQADSwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh 5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQC MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl MB0GA1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7 hyNp65w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoT CE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlw dG8gQ2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3Qx LmNvbYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6 BoJuVwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++ 7QGG/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JE WUQ9Ho4EzbYCOQ== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh 5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAQJBAIqm/bz4NA1H++Vx5Ewx OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT ZIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4 nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2 HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNEH+vRWsAYU/gbx+OQB+7VOcBAiEA oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w= -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- MIIBDTCBuAIBADBTMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQ BgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20w XDANBgkqhkiG9w0BAQEFAANLADBIAkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5Ad NgLzJ1/MfsQQJ7hHVeHmTAjM664V+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABoAAw DQYJKoZIhvcNAQEEBQADQQA7uqbrNTjVWpF6By5ZNPvhZ4YdFgkeXFVWi5ao/TaP Vq4BG021fJ9nlHRtr4rotpgHDX1rr+iWeHKsx4+5DRSy -----END CERTIFICATE REQUEST----- M2Crypto-0.22.6rc4/demo/x509/server.pem0000664000175000017500000000411012605232411017547 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIDYjCCAsugAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCU0cx ETAPBgNVBAoTCE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UE AxMbTTJDcnlwdG8gQ2VydGlmaWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNu Z3BzQG5ldG1lbWV0aWMuY29tMB4XDTAzMDYyMjEzMzAxNFoXDTA0MDYyMTEzMzAx NFowXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwls b2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5leGFtcGxlLmRv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA37aKGZtFicl8xXXTLJ8/JD7c kd3t/teCX9i61lpaDQCKBoVrrursIvZihemMKI9g/u/+BLqt5g8mBdgUdYz0txc8 KEbV2hj+wwOX4H3XwD0Y+DysXiNHq7/tFdmzSVHoLxpY4zYzXbxQ/p049wvIyPRp /y3omcnx/TEUhkn+JmkCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4 QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTB H/mUYlww24mJlSxEtGdlwojO9zCBrQYDVR0jBIGlMIGigBTr+pwHMS1CmF9cuGI4 du3YqoHAwqGBhqSBgzCBgDELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv MRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8gQ2VydGlm aWNhdGUgTWFzdGVyMSIwIAYJKoZIhvcNAQkBFhNuZ3BzQG5ldG1lbWV0aWMuY29t ggEAMA0GCSqGSIb3DQEBBAUAA4GBAAvl6v0s3eFeGP4iAcrfysuK7jzFKhjDYuOy lVS3u33bZNLnMpM6OSEM9yPh4WpFCVHf+nYwC71pk4ilsLVXjKxymm2lNGcxLVuW iydFz4Ly9nmN7Ja9ygYT39dGAFP/wN7ELTpsbul8VfmqhNg9y81d8i/A1tK3AGA8 0QkPQNdP -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDftooZm0WJyXzFddMsnz8kPtyR3e3+14Jf2LrWWloNAIoGhWuu 6uwi9mKF6Ywoj2D+7/4Euq3mDyYF2BR1jPS3FzwoRtXaGP7DA5fgfdfAPRj4PKxe I0erv+0V2bNJUegvGljjNjNdvFD+nTj3C8jI9Gn/LeiZyfH9MRSGSf4maQIDAQAB AoGAHpeVtv62uarl9xKvuBBm0AwQmZnhq9HIsFaw5hMg8Vo7hbzFBvx1IirTOkC/ u+QvfW1QLVFh6m3z4ySzV4fZBtcd6F9SbSrZ0xsxIUB2NOSa1RGgiaP61bJnMMM1 xM3O9iwM5GZc3Gqy08QOCpDl0772VJ+9Gz3FA88mrc6rHQkCQQDz6RIatFjT28n8 1vy0nHwwZz2oXTpe/pyZPwoKj8zVsmrKhKwOw7l8ArxjP8zoHOE7AQBCXYDMNoFp IAF0yuqrAkEA6s0wMEdPpQeb0XHAfccyJQoeULxHdVFoz1wWmGSOm4YmQtR8/QJx luEgfpeRkzxBKt5Ls3MEkheIOw7xV24zOwJAMz+DaE0AZPNHS3K4ghJnHZxzng6I lzEUIjbWm0V/ml70hTy/EhMZw+6nOotLOHHo+QbK0SboSwAgzL/Gzo1cJQJANqpS 38qadleRJXAQWrg3qnvyluVe1aeAeVZ9RDmVIgxXeBO0jcs12uTLBe4PzHGo0mwy v7K1i7XC180gzzQu5QJBAOxITT9RoWSSozPvnirHd37sn+RsrNYkV07NAa80M20Z DkBPHeMVkNgigrQ6L6vWmbRDGQbGcMplAxnI5ppKCoU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/x509/x509auth.py0000664000175000017500000010456112607370517017526 0ustar matejmatej00000000000000#!/usr/bin/env python2 # # vim: ts=4 sw=4 nowrap # # ChannelHandler # ReceiveChannel # SendChannel # # SocketDispatcher # Loop # Poll # ReadEvent # WriteEvent # import sys, re, time, thread, os import getopt import exceptions import select import string import socket import StringIO import traceback from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN, EINTR, EISCONN STDOUT = sys.stdout IDstdin = 0 IDstdout = 1 IDstderr = 2 class ExitNow (exceptions.Exception): pass class AuthError(exceptions.Exception): def __init__ (self, msg): self.msg = msg def __str__ (self): return repr( self.msg ) #---------------------------------------------------------------- # # Class Security Certification # #---------------------------------------------------------------- import M2Crypto import random import base64 import sha class CertHandler: def __init__ ( self ): self.Nonce = None self.CurrentObj = {} #self.ServerName = socket.gethostbyaddr(socket.gethostname())[2][0] self.ServerName = 'AuthInstance' self.ObjNames = { 'C' : 'countryName', 'ST' : 'stateOrProvinceName', 'L' : 'localityName', 'O' : 'organizationName', 'OU' : 'organizationalUnitName', 'CN' : 'commonName', 'email' : 'emailAddress' } self.ObjMap = {} self.Params = { 'Digest' : 'sha1', 'Version' : 1, 'Serial' : 1, 'NotBefore' : ( 60 * 60 * 24 * 365 ), 'NotAfter' : ( 60 * 60 * 24 * 365 * 5 ), 'Issuer' : { 'countryName' : 'US', 'stateOrProvinceName' : 'florida', 'localityName' : 'tampas', 'organizationName' : 'watersprings', 'organizationalUnitName' : 'security', 'commonName' : 'Certificate Authority', 'emailAddress' : 'admin@security' }, 'Subject' : { 'countryName' : 'US', 'stateOrProvinceName' : 'florida', 'localityName' : 'miami', 'organizationName' : 'watersprings', 'organizationalUnitName' : 'security', 'commonName' : 'Certificate Authority', 'emailAddress' : 'admin@security' } } self.KeyEnv = { 'RsaPubKey' : [ '-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----' ], 'RsaPKey' : [ '-----BEGIN RSA PRIVATE KEY-----', '-----END RSA PRIVATE KEY-----' ], 'X509Cert' : [ '-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----' ] } self.CertContainer () self.ObjFromContainer ( ObjName='CA' ) self.ObjFromContainer ( ObjName=self.ServerName ) self.ServerObj = self.ObjMap[ self.ServerName ] def CertContainer (self): self.PemMap = { 'CA' : { 'Subject' : {'organizationalUnitName': 'security', 'organizationName': 'watersprings', 'commonName': 'Certificate Authority', 'stateOrProvinceName': 'florida', 'countryName': 'US', 'emailAddress': 'admin@security', 'localityName': 'miami'}, 'RsaPKey' : ['MIICXQIBAAKBgQDmAl+4+XdF34D3kBN58An29mA8/D+NUHVJW+XeE96uDJ9mw8f1', 'xguVYgfpMaiVihW/qDWZRu/NhWOfheKBVNstx5OcqIjY10vBvGAG17CQZhcon8eN', 'Kufg7XzON7e5WXXD8qyklhuesHtTEGGpZ1FfA+n+D/0JF3YfTBDeYyY2VQIDAQAB', 'AoGBAI53L/Uxx7fmzUoJ2pZvoKxwRIHhuDd+e3c5zbJ1WjsyJFWRtLw9tBUOCFpf', 'YM1nHzt8I97RulzxXxiC5B45ghu3S0s+B06oEOUxNLbjsai08DKBRFqM+IZIx11r', 'IM/tZsTdJg1KtKojRu63NDtOzR6a7ggTeMge5CDKpXVWpvVtAkEA+QF/q2NnsdmL', 'ak6ALl8QwMbvwujJcjLwvecHQJmB0jO9KF60Hh4VY8mTRIMZ/r9Wf+REsQcZtmhG', 'WRr12si5qwJBAOx4R0Wd/inoXOpvKheIoKgTg01FnLhT8uiLY59CuZRr6AcTELjC', 'Kvk6LyfhspYBkUwWAEwKxJ3kMeqXG+k8z/8CQQCy+GDKzqe5LKMHxWRb7/galuG9', 'NZOUgQiHdYXA6JRmgMl0Op07CGRXVIqEs7X7Y4rIYUj99ByG/muRn88VcTABAkBQ', 'Z6V0WoBtp4DQhfP+BIr8G4Zt49miI4lY4OyC3qFTgk1m+miZKgyKqeoW2Xtr3iSV', 'hnWbZZ3tQgZnCfKHoBHpAkAmf2OvfhLxaW1PwdjBdm9tFGVbzkLFDqdqww2aHRUx', 'sXonHyVG2EDm37qW7nzmAqUgQCueMhHREZQYceDrtLLO'], 'X509Cert' : ['MIICpzCCAhCgAwIBAQIBATANBgkqhkiG9w0BAQUFADCBmTERMA8GA1UECxMIc2Vj', 'dXJpdHkxFTATBgNVBAoTDHdhdGVyc3ByaW5nczEeMBwGA1UEAxMVQ2VydGlmaWNh', 'dGUgQXV0aG9yaXR5MRAwDgYDVQQIEwdmbG9yaWRhMQswCQYDVQQGEwJVUzEdMBsG', 'CSqGSIb3DQEJARYOYWRtaW5Ac2VjdXJpdHkxDzANBgNVBAcTBnRhbXBhczAeFw0w', 'MzAzMzExMDQ2MDVaFw0wOTAzMjkxMDQ2MDVaMIGYMREwDwYDVQQLEwhzZWN1cml0', 'eTEVMBMGA1UEChMMd2F0ZXJzcHJpbmdzMR4wHAYDVQQDExVDZXJ0aWZpY2F0ZSBB', 'dXRob3JpdHkxEDAOBgNVBAgTB2Zsb3JpZGExCzAJBgNVBAYTAlVTMR0wGwYJKoZI', 'hvcNAQkBFg5hZG1pbkBzZWN1cml0eTEOMAwGA1UEBxMFbWlhbWkwgZ8wDQYJKoZI', 'hvcNAQEBBQADgY0AMIGJAoGBAOYCX7j5d0XfgPeQE3nwCfb2YDz8P41QdUlb5d4T', '3q4Mn2bDx/XGC5ViB+kxqJWKFb+oNZlG782FY5+F4oFU2y3Hk5yoiNjXS8G8YAbX', 'sJBmFyifx40q5+DtfM43t7lZdcPyrKSWG56we1MQYalnUV8D6f4P/QkXdh9MEN5j', 'JjZVAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAK7f4YodUnT7Ygp7BWBBDHSq/r+tY', 'H69ly3W23U5VupaIglNiNQoMqnZpVVfcuIYltajrux5TSH4gPbenCg163Ua8RvF6', 'E2JElccprbKiCf9tf8l6Rxpsall4EF+CazP56DiUD1NfGLhWp9V2ga9SoynEo1P1', 'eztMBfk01atBJ/s='] }, 'AuthInstance' : { 'Subject' : {'commonName': 'AuthInstance', 'organizationalUnitName': 'security', 'emailAddress': 'ioclient@AuthInstance'}, 'RsaPKey' : ['MIICXQIBAAKBgQCwfB6CoOQTJTd6D4ua1G/H9hwqpdVUMMjG3O8Y93vYGesZdwtT', '1iEQX/6TWACBxa7jOC8hHUHe2lsPu7imHv8dDiD59Rzets7BM88HsJTemYrxSv5G', 'uh8FloB1KEtSHeCZSlDT/tzSX4M0JfVPmtx+0FsyDOVZ6jXjRIyIKgqDlwIDAQAB', 'AoGAYc8YFatXW6j3mwU8iL2NidPC/nvTxAoZa+UL+dlG4JhUrFNGitsUjf+1ljFi', 'bomBiFod/Is7c2euqgSOrDpnheYlogv2QpnP80YUpiv9OruaB9I1zqJ7QM7PrkrH', 'm1C36DzyzVY+4DMvTV29do4Mf6CKT8xf6hXlLK/NbqwO9NkCQQDYwxwCTWxrkX08', '+0c5KaTYxfqCByxOqoiKl97p6wHxNtlzdLeFoSZD0n3Q1c2v0DIXhcBPRPPaZBWC', 'yTayMkRzAkEA0G6I5mHQVNIx18Xmc75urC0QWrum9cj5VcyRvl3KCzB2kQoXkx6v', 'y0JN6YS37rSp8vmvIFNO/oHWSuEJlFYfTQJAajWv07D8Hvj61JaLH4c4Lr9TL8M0', 'Apesr7wajaOJIBgwFFJsWh3MEg9hdqJMVok9AimXQUAX/DpuD9dn5Yib4QJBAIdt', 'Kno2V7ylDkmahk/yDcrFRPkPMD5GpOrAjnnYSqzWglNe8U5gA+zXWfQ+jZwFut7q', 'qIUiXBM1nVzttuGwy4kCQQC3MHppypSWoFqd+TaxK3MX/HoZqaoRELXdeiniOt3Z', 'gFMJ4m6D9lL4segWDoDpequjDYxv2cl+wS1+qDOyeG3J'], 'X509Cert' : ['MIIBxDCCAS2gAwIBAQIBATANBgkqhkiG9w0BAQUFADAAMB4XDTAzMDMzMTEwNTE1', 'N1oXDTA5MDMyOTEwNTE1N1owUDEkMCIGCSqGSIb3DQEJARYVaW9jbGllbnRAQXV0', 'aEluc3RhbmNlMREwDwYDVQQLEwhzZWN1cml0eTEVMBMGA1UEAxMMQXV0aEluc3Rh', 'bmNlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwfB6CoOQTJTd6D4ua1G/H', '9hwqpdVUMMjG3O8Y93vYGesZdwtT1iEQX/6TWACBxa7jOC8hHUHe2lsPu7imHv8d', 'DiD59Rzets7BM88HsJTemYrxSv5Guh8FloB1KEtSHeCZSlDT/tzSX4M0JfVPmtx+', '0FsyDOVZ6jXjRIyIKgqDlwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFsXewlXnKpH', 'uSwxavmLPUqRk7o1D5E3ByTddBe3BY5NqEXk7Y2SJFtumiuUY5/sWB/aO8Xbqj/b', '/7Cwg9+bc9QqxeeIe/YvtFOmv1ELh2BC1Nof7zSa5rLa/+gPYCoogS4mLRMuUfRk', 'tVHhpoxL1B+UXp4jNeKeTgquOjpUiyBR'] }, '192.168.1.20' : { 'Subject' : {'commonName': '192.168.1.20', 'organizationalUnitName': 'security', 'emailAddress': 'ioclient@192.168.1.20'}, 'RsaPKey' : ['MIICWwIBAAKBgQDD285BGY+FHhfpRvcqupN8X2lPwUNq4G7k5kit5cyuQLfN0+eQ', 'I+VFZdtfJhCZC54dEIvNgA4I7563pRUD0S9rmN6kh/M0GgrKZjYNO+CvvG2dts26', 'MGK0eUQaSsvDf9phEA+0mSv9dsUrdyBTJBn4mXvApekYHt+mNLfCVLkM1QIDAQAB', 'AoGAMqcFB3cJ0/59Zpowz/8ip3axcKvluJ1EcLRRtY+JyML6BiQ4beGqqLD38/qP', 'LlV/1bpyvXnRp2P5IztxXORbo77IzDVzl62YesQATnecSCMLTaeOusy2EZZsjE0k', 'V2cR1rZvzyJPY+Fi8X54hiB+5IcKkPRX9LVw7+yBbBh4sKECQQD0Yi0/DGa3IetR', '9F+/jgN/VIcTd5KwMBW3Bw/+Bh78ZlZGaucpRiR1IQuD7sLTnhNS6RMJUxv10jnS', 'BGW9pjX5AkEAzSslOGFyJ5Aoy48rgC2kKwq6nFKJ/PmY92cnm0nqmwb2npbOtDxz', 'sPUdb7oYmUU/nVCJh3yb+KJIw2g9XxnUvQJAG8ybNwPTH1vlZ+Izjhe6gB5+axF8', 'BzzBC5vrDstldPKzN7lraD+JYCWNKMndMbNWoWTP/IyOrqzmVOSZKjShCQJAbzuE', 'C2QxaqeqpmnxkKWuCrPfZl8NdryvpPolK/jQG8qTrHlgibD4nCjYE7nWGkrD6Xs/', 'hNgXC56YSnDaTRQJFQJAD5GFACv9QgcMZhy1hza0yGDMSQ0WR8/y3CJhi3DPOuAf', 'MetGM1kLQR8bDFrl7yEs+Nufk8QTsE5ngZ7dGFgmuA=='], 'X509Cert' : ['MIIBxDCCAS2gAwIBAQIBATANBgkqhkiG9w0BAQUFADAAMB4XDTAzMDMzMTEwNTMw', 'NVoXDTA5MDMyOTEwNTMwNVowUDEkMCIGCSqGSIb3DQEJARYVaW9jbGllbnRAMTky', 'LjE2OC4xLjIwMREwDwYDVQQLEwhzZWN1cml0eTEVMBMGA1UEAxMMMTkyLjE2OC4x', 'LjIwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD285BGY+FHhfpRvcqupN8', 'X2lPwUNq4G7k5kit5cyuQLfN0+eQI+VFZdtfJhCZC54dEIvNgA4I7563pRUD0S9r', 'mN6kh/M0GgrKZjYNO+CvvG2dts26MGK0eUQaSsvDf9phEA+0mSv9dsUrdyBTJBn4', 'mXvApekYHt+mNLfCVLkM1QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAA5pWiXJOHCJ', 'P6kHcBITJuwv94zZ0dbHby1ljUfG/8z3Fmr8JRUcTuTtgVYH9M0O9QujIR8YLWSV', '0GeD3nkLRn0+ezam0CW0dF/Ph5vNXFP4a0DSEVv7T0G21VFmbUV3xrVeaXARFuLa', 'AtqRoSyBMajd3g0WNXDCgGEH7LvzJ5EP'] }, '192.168.1.26' : { 'Subject' : {'commonName': '192.168.1.26', 'organizationalUnitName': 'security', 'emailAddress': 'ioclient@192.168.1.26'}, 'RsaPKey' : ['MIICXQIBAAKBgQC5ILRHC3wFoqG9Egb96N3iGEnVrgvQikHyXYc/jFMUgB79rVJp', 'hY1MziGkSjSyc3RFMshkjHlMlARMPCNtomIikqAQaO4Eke2SYWyaOBoTdkeOy+yZ', 't/POpoGp3nRmKGed6NNcdMd5BO01GiatUb7X/Se3Yyvmj5UcEmv/hZQGFwIDAQAB', 'AoGBALdR5FMp0zE9X437iQLsErQuOwcmpzplfnJDHYfXK/nz+TxY4m/tuQNiZ7vp', 'Y4+Gdo+Dfx7aX89uD2dycd7B2wwTziBGIEjhusD8gtralVjhBDjCowSOkezWTeY+', '2h40NB4e1uypOZb0PXWvAL/l9xN7NBGioq9zmShT5c+FFO8RAkEA4k3QSaT1ScGI', '5II5JolvPnv6yS+0dCQTn1SC2ABWbH75NDUHMGAdNIf1sqhaLSQnY9GuXhb8XqX6', 'UUhoypUHzwJBANFrqnuEuTNKR0HVD31/2trPYLfZL6/9RUsR4mlvxPb0tX+T5LVL', '5he43zbura/lZqNxt0ZVeD03LanPN7bvZzkCQQCMAToIJa6+x6YKQOpchhA1pvwb', 'NZE9fQhKvT0JpwPQsak4/EmLSxsmYarGsdLANKrN3W4ztaLCZ4r6eIKkOhkPAkBz', 'ke4wYitucbRnUTRONuvJSx599x6JCcVey0zekO7qtlsfP7e8kVk2iDCu+QLjCj8d', 'Pdk9uFc1uSi7CH8ftniJAkBLNYF0kfGC+CaTuyfnIwiBZ/tjmm4UvHfwtlaZHJYc', 'QIjimBxVA7mujrv3xIBTiDMdxUhq9YIaKIEdlveaTwPK'], 'X509Cert' : ['MIIBxDCCAS2gAwIBAQIBATANBgkqhkiG9w0BAQUFADAAMB4XDTAzMDMzMTEwNTQx', 'NloXDTA5MDMyOTEwNTQxNlowUDEkMCIGCSqGSIb3DQEJARYVaW9jbGllbnRAMTky', 'LjE2OC4xLjI2MREwDwYDVQQLEwhzZWN1cml0eTEVMBMGA1UEAxMMMTkyLjE2OC4x', 'LjI2MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5ILRHC3wFoqG9Egb96N3i', 'GEnVrgvQikHyXYc/jFMUgB79rVJphY1MziGkSjSyc3RFMshkjHlMlARMPCNtomIi', 'kqAQaO4Eke2SYWyaOBoTdkeOy+yZt/POpoGp3nRmKGed6NNcdMd5BO01GiatUb7X', '/Se3Yyvmj5UcEmv/hZQGFwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAMPd5SXzpwZ+', '40SdOv/PeQ5cjieDm6QjndWE/T8nG2I5h6YRWbZPohsCClQjrTyZCMXwcUiCimuJ', 'BaMigI/YqP5THVv58Gu8DpoVZppz7uhUNS5hsuV9lxZUh1bRkUtL6n0qSTEdM34I', 'NJBJKGlf0skULg9BT4LJYTPGWJ0KosUl'] } } def CreateObj ( self, ObjName='CA' ): self.ObjMap[ObjName] = { 'RsaPKey' : None, 'PsaPubKey' : None, 'EvpPKey' : None, 'EvpPubKey' : None, 'X509Req' : None, 'X509Cert' : None, } self.CurrentObj = self.ObjMap[ObjName] def ObjFromContainer (self, ObjName='CA' ): if not self.ObjMap.has_key( ObjName ): self.CreateObj ( ObjName=ObjName ) self.PKeyFromPemRepr ( ObjName=ObjName ) self.CertFromPemRepr ( ObjName=ObjName ) def PKeyFromPemRepr ( self, ObjName=None, PemPKey=None ): def callback (): return '' if self.PemMap.has_key( ObjName ): UsedPemPKey = self.KeyEnv['RsaPKey'][0] + '\n' + string.join( self.PemMap[ObjName]['RsaPKey'], '\n' ) + '\n' + self.KeyEnv['RsaPKey'][1] + '\n' else: if not PemPKey: raise AuthError( 'no such Object "%s" in container - abort!' % ObjName ) else: UsedPemPKey = PemPKey self.CurrentObj['RsaPKey'] = M2Crypto.RSA.load_key_string( UsedPemPKey, callback ) self.CurrentObj['EvpPKey'] = M2Crypto.EVP.PKey ( md='sha1' ) self.CurrentObj['EvpPKey'].assign_rsa ( self.CurrentObj['RsaPKey'] ) self.CurrentObj['RsaPubKey'] = M2Crypto.RSA.new_pub_key( self.CurrentObj['RsaPKey'].pub () ) def CertFromPemRepr ( self, ObjName=None, PemCert=None ): if self.PemMap.has_key( ObjName ): UsedPemCert = self.KeyEnv['X509Cert'][0] + '\n' + string.join( self.PemMap[ObjName]['X509Cert'], '\n' ) + '\n' + self.KeyEnv['X509Cert'][1] + '\n' else: UsedPemCert = PemCert self.CurrentObj['X509Cert'] = M2Crypto.X509.load_cert_string( PemCert ) self.CurrentObj['EvpPubKey'] = self.CurrentObj['X509Cert'].get_pubkey () #self.CurrentObj['RsaPubKey'] = M2Crypto.RSA.rsa_from_pkey( self.CurrentObj['EvpPubKey'] ) def ObjNameFromPemCert ( self, PemCert=None ): """ generate objmap structure and fill it with values from PemCert return ObjName string """ X509Cert = M2Crypto.X509.load_cert_string( PemCert ) Subject = X509Cert.get_subject () SubjectTxt = Subject.print_ex () SubjectTxtList = re.split('[\n\r]', SubjectTxt ) SubjectMap = {} for Entry in SubjectTxtList: ( Key, Value ) = re.split('=', Entry) if self.ObjNames.has_key( Key ): SubjectMap[ self.ObjNames[Key] ] = Value else: SubjectMap[ Key ] = Value if not SubjectMap.has_key( 'commonName' ): return False ObjName = SubjectMap['commonName'] if not self.ObjMap.has_key( ObjName ): self.CreateObj( ObjName=ObjName ) self.CurrentObj = self.ObjMap[ObjName] self.CurrentObj['X509Cert'] = X509Cert self.CurrentObj['EvpPubKey'] = self.CurrentObj['X509Cert'].get_pubkey () self.CurrentObj['RsaPubKey'] = M2Crypto.RSA.rsa_from_pkey( self.CurrentObj['EvpPubKey'] ) else: self.CurrentObj = self.ObjMap[ ObjName ] return ObjName def ServerCert ( self ): self.ObjFromContainer( ObjName='X509Auth' ) def CreatePKey ( self ): def PassPhraseFkt (): return '' RsaKeyParams = { 'KeyLength' : 1024, 'PubExponent' : 0x10001, # -> 65537 'keygen_callback' : PassPhraseFkt } self.CurrentObj['RsaPKey'] = M2Crypto.RSA.gen_key( RsaKeyParams['KeyLength'], RsaKeyParams['PubExponent'], RsaKeyParams['keygen_callback'] ) self.CurrentObj['EvpPKey'] = M2Crypto.EVP.PKey ( md=self.Params['Digest'] ) self.CurrentObj['EvpPKey'].assign_rsa ( self.CurrentObj['RsaPKey'] ) #print self.EvpPKey def CreateCert ( self, SignEvpPKey=None ): """ generate new x509 certificate SignEvpKey pkey to sign x509 certification, if None this x509 cert will be self signed """ self.CurrentObj = self.ObjMap['CA'] self.CreatePKey () X509Cert = M2Crypto.X509.X509 () X509Cert.set_version ( self.Params['Version'] ) X509Cert.set_serial_number ( self.Params['Serial'] ) X509Cert.set_not_before ( int( time.time() - self.Params['NotBefore'] )) # 1 year in the past X509Cert.set_not_after ( int( time.time() + self.Params['NotAfter'] )) # 5 years in the future X509Cert.set_issuer ( self.Params['Issuer'] ) X509Cert.set_subject ( self.Params['Subject'] ) X509Cert.set_pubkey ( self.CurrentObj['EvpPKey'] ) if SignEvpPKey: X509Cert.sign ( SignEvpPKey, self.Params['Digest'] ) else: X509Cert.sign ( self.CurrentObj['EvpPKey'], self.Params['Digest'] ) self.CurrentObj['X509Cert'] = X509Cert self.DumpOutInternalPemRepr( ObjName='CA' ) def CreateObjCert (self, ObjName): """ generate Obj with new PKey and Request, signed by 'CA' ObjName the primary key to identify key-pair """ # new obj if not self.ObjMap.has_key( ObjName ): self.ObjMap[ObjName] = {} self.CurrentObj = self.ObjMap[ObjName] if not self.CurrentObj.has_key( 'Subject' ): self.CurrentObj['Subject'] = { 'organizationalUnitName' : 'security', 'commonName' : ObjName, 'emailAddress' : 'ioclient@' + ObjName } # new pkey self.CreatePKey () # new request self.CreateReq ( SignEvpPKey=self.ObjMap['CA']['EvpPKey'] ) # new certification if not self.Req2Cert ( SignEvpPKey=self.ObjMap['CA']['EvpPKey'] ): print "300 error occured while verifying - abort!" # shipout x509 certification self.DumpOutInternalPemRepr( ObjName=ObjName ) def CreateReq ( self, SignEvpPKey=None ): X509Req = M2Crypto.X509.Request () if self.Params['Version']: X509Req.set_version ( self.Params['Version'] ) X509Req.set_subject ( self.CurrentObj['Subject'] ) X509Req.set_pubkey ( self.CurrentObj['EvpPKey'] ) if SignEvpPKey: X509Req.sign ( SignEvpPKey, self.Params['Digest'] ) else: X509Req.sign ( self.CurrentObj['EvpPKey'], self.Params['Digest'] ) self.CurrentObj['X509Req'] = X509Req def Req2Cert ( self, SignEvpPKey=None ): X509Cert = M2Crypto.X509.X509 () Version = self.CurrentObj['X509Req'].get_version () X509Cert.set_version ( Version ) X509Cert.set_serial ( self.Params['Serial'] ) X509Cert.set_not_before ( int( time.time() - self.Params['NotBefore'] )) # 1 year in the past X509Cert.set_not_after ( int( time.time() + self.Params['NotAfter'] )) # 5 years in the future Issuer = self.ObjMap['CA']['X509Cert'].get_issuer () X509Cert.set_issuer_name ( Issuer ) X509Name_Subject = self.CurrentObj['X509Req'].get_subject () X509Cert.set_subject_name ( X509Name_Subject ) PKey = self.CurrentObj['X509Req'].get_pubkey () EvpPKey = M2Crypto.EVP.PKey( PKey ) X509Cert.set_pubkey ( EvpPKey ) if SignEvpPKey: X509Cert.sign ( SignEvpPKey, self.Params['Digest'] ) else: X509Cert.sign ( self.CurrentObj['EvpPKey'], self.Params['Digest'] ) self.CurrentObj['X509Cert'] = X509Cert if self.VerifyCert ( SignEvpPKey ): return True else: return False #-------------------------------- # CertHandler Verifying #-------------------------------- def ExtractPublicKeyFromCert ( self ): self.CurrentObj['EvpPubKey'] = self.CurrentObj['X509Cert'].get_pubkey () def VerifyCert ( self, EvpPKey ): if dir(EvpPKey).count('_ptr'): Result = self.CurrentObj['X509Cert'].verify ( EvpPKey._ptr() ) else: Result = self.CurrentObj['X509Cert'].verify ( EvpPKey ) if Result: return True return False #-------------------------------- # CertHandler DumpOut #-------------------------------- def DumpOutInternalPemRepr( self, ObjName='unknown', File='PyReprPem.txt' ): if File: open( File, 'w').write("\t\t\t\t'%s' : { " % ( ObjName )) else: sys.stdout.write("\t\t\t\t'%s' : { " % ( ObjName )) self.ShowX509CertSubject ( File ) self.RsaPKey2PemRepr ( File, Cipher=None ) # unprotectd pkey representation self.X509Cert2PemRepr ( File ) if File: open( File, 'a').write("\t\t\t\t\t }\n") else: sys.stdout.write("\t\t\t\t\t }\n") def ShowX509CertIssuer ( self, File=None ): IssuerName = self.CurrentObj['X509Cert'].get_issuer () print IssuerName.print_ex () def ShowX509CertSubject ( self, File=None ): Subject = self.CurrentObj['X509Cert'].get_subject () SubjectTxt = Subject.print_ex () SubjectTxtList = re.split('[\n\r]', SubjectTxt ) SubjectMap = {} for Entry in SubjectTxtList: ( Key, Value ) = re.split('=', Entry) if self.ObjNames.has_key( Key ): SubjectMap[ self.ObjNames[Key] ] = Value else: SubjectMap[ Key ] = Value if File: open( File, 'a').write("'Subject' : %s,\n" % ( repr( SubjectMap ) )) else: sys.stdout.write("Subject: %s\n" % ( repr( SubjectMap ) )) def RsaPKey2PemRepr ( self, File=None, Cipher=None ): """ converting pkey to PEM representation Cipher if set to None, the pkey will be unprotected!!!!! possible other value: 'des_ede3_cbc' """ PemRsaPKey = self.CurrentObj['RsaPKey'].repr_key_pem ( cipher=Cipher ) PemRsaPKeyList = re.split('[\n\r]', PemRsaPKey) if File: open( File, 'a').write("\t\t\t\t\t\t\t\t'RsaPKey' : %s,\n" % ( repr(PemRsaPKeyList[1:-2]) )) else: sys.stdout.write("\t\t\t\t\t\t\t\t'RsaPKey' : %s,\n" % ( repr(PemRsaPKeyList[1:-2]) )) def X509Cert2PemRepr ( self, File=None ): PemCert = self.CurrentObj['X509Cert'].repr_cert_pem () #print PemCert PemCertList = re.split('[\n\r]', PemCert) if File: open( File, 'a').write("\t\t\t\t\t\t\t\t'X509Cert' : %s\n" % ( repr(PemCertList[1:-2]) )) else: sys.stdout.write("\t\t\t\t\t\t\t\t'X509Cert' : %s\n" % ( repr(PemCertList[1:-2]) )) #-------------------------------- # CertHandler encryption / decryption #-------------------------------- def CreateNonce ( self ): """ creating some randomised data return new Nonce string """ random.seed () RawNonce = "%s_%f_%f" % ( os.getpid(), time.time(), random.random() ) sha1=M2Crypto.EVP.MessageDigest('sha1') sha1.update( RawNonce ) NonceDecrypted = sha1.digest() return NonceDecrypted def NonceEncryptPrivate ( self, NonceDecrypted, RsaPKey=None ): """ creating private encrypted string from NonceDecrypted """ padding = M2Crypto.RSA.pkcs1_padding if not RsaPKey: UsedRsaPKey = self.ServerObj['RsaPKey'] else: UsedRsaPKey = RsaPKey NoncePrivEncrypted = UsedRsaPKey.private_encrypt ( NonceDecrypted, padding ) return NoncePrivEncrypted def NonceEncryptPublic ( self, NonceDecrypted, RsaPubKey=None ): """ creating public encrypted string from NonceDecrypted """ padding = M2Crypto.RSA.pkcs1_padding if not RsaPubKey: UsedRsaPubKey = self.ServerObj['RsaPubKey'] else: UsedRsaPubKey = RsaPubKey NoncePubEncrypted = UsedRsaPubKey.public_encrypt ( NonceDecrypted, padding ) return NoncePubEncrypted def NonceDecryptPublic ( self, NoncePrivEncrypted, RsaPubKey=None ): """ creating decrypted string from NoncePrivEncrypted """ padding = M2Crypto.RSA.pkcs1_padding if not RsaPubKey: UsedRsaPubKey = self.ServerObj['RsaPubKey'] else: UsedRsaPubKey = RsaPubKey try: NonceDecrypted = UsedRsaPubKey.public_decrypt ( NoncePrivEncrypted, padding ) except: raise AuthError('decrypting of public key failed - abort!') return NonceDecrypted def NonceDecryptPrivate ( self, NoncePubEncrypted, RsaPKey=None ): padding = M2Crypto.RSA.pkcs1_padding if not RsaPKey: UsedRsaPKey = self.ServerObj['RsaPKey'] else: UsedRsaPKey = RsaPKey NonceDecrypted = UsedRsaPKey.private_decrypt ( NoncePubEncrypted, padding ) return NonceDecrypted def NonceVerify ( self, DecryptedNonce=None ): if self.CurrentObj['Nonce']['Decrypted'] == DecryptNonce: return True return False #-------------------------------- # CertHandler authentication request #-------------------------------- def ClientInit ( self, ObjName=None ): """ generating AuthString Nonce messagedigest 'sha1', encrypted with own instance private key Cert own instance X509 cert, PEM encoded any linefeed charaters stripped out of the base64 code return generated Nonce and AuthString """ if ObjName: if self.PemMap.has_key( ObjName ): UsedObjName = ObjName else: UsedObjName = self.ServerName else: UsedObjName = self.ServerName NonceDecrypted = self.CreateNonce () NoncePrivEncrypted = re.sub('\012', '', base64.encodestring( self.NonceEncryptPrivate ( NonceDecrypted, RsaPKey=self.ServerObj['RsaPKey'] )) ) PemCert = re.sub('\012', '', base64.encodestring( self.KeyEnv['X509Cert'][0] + '\n' + string.join( self.PemMap[UsedObjName]['X509Cert'], '\n' ) + '\n' + self.KeyEnv['X509Cert'][1] + '\n' )) InitString = re.sub('\012', '', base64.encodestring('%s:%s' % ( NoncePrivEncrypted, PemCert ))) return ( NonceDecrypted, InitString ) def ClientInitVerify ( self, InitString ): """ return decrypted Nonce from AuthString and ObjName from AuthString X509 Cert """ try: PemBaseString = base64.decodestring( InitString ) except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) try: ( Base64Nonce, Base64Cert ) = re.split(':', PemBaseString ) except: raise AuthError( 'cannot split PemBaseString into parts - abort!' ) try: NoncePrivEncrypted = base64.decodestring( Base64Nonce ) except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) try: PemCert = base64.decodestring( Base64Cert ) except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) try: X509Cert = M2Crypto.X509.load_cert_string( PemCert ) except: raise AuthError( 'cannot extract X509 cert from PEM representation - abort!' ) EvpPKey = self.ObjMap['CA']['EvpPKey'] if dir(EvpPKey).count('_ptr'): Result = X509Cert.verify ( EvpPKey._ptr() ) else: Result = X509Cert.verify ( EvpPKey ) if Result != 1: raise AuthError( 'verification of X509 cert with Certification Authority "CA" failed with code %d - abort!' % ( Result )) ClientObjName = self.ObjNameFromPemCert( PemCert=PemCert ) try: NonceDecrypted = self.NonceDecryptPublic( NoncePrivEncrypted, RsaPubKey=self.CurrentObj['RsaPubKey'] ) except: raise AuthError( 'wrong public key for encoding nonce - abort!' ) return ( NonceDecrypted, ClientObjName ) def ServerInit ( self, ClientObjName, ClientNonce ): """ NonceServer new Nonce from server encrypted with client publickey and base64 encoded NonceBounce the authrequest nonce encrypted with server privatekey and base64 encoded PemServerCert server X509 certification PEM encoded and base64 encoded """ if not self.ObjMap.has_key( ClientObjName ): if not self.PemMap.has_key( ClientObjName ): raise AuthError( 'cannot find ClientObjName - abort!' ) else: self.ObjFromContainer( ObjName=ClientObjName ) else: self.CurrentObj = self.ObjMap[ClientObjName] NonceDecrypted = self.CreateNonce () NonceServer = re.sub('\012', '', base64.encodestring( self.NonceEncryptPublic ( NonceDecrypted, RsaPubKey=self.CurrentObj['RsaPubKey'] )) ) NonceBounce = re.sub('\012', '', base64.encodestring( self.NonceEncryptPublic ( ClientNonce, RsaPubKey=self.CurrentObj['RsaPubKey'] )) ) PemServerCert = re.sub('\012', '', base64.encodestring( self.KeyEnv['X509Cert'][0] + '\n' + string.join( self.PemMap[self.ServerName]['X509Cert'], '\n' ) + '\n' + self.KeyEnv['X509Cert'][1] + '\n' ) ) InitString = re.sub('\012', '', base64.encodestring('%s:%s:%s' % ( NonceServer, NonceBounce, PemServerCert )) ) return ( NonceDecrypted, InitString ) def ServerInitVerify ( self, InitString, ObjName=None ): NonceDecrypted = '' ObjName = '' try: PemBaseString = base64.decodestring( InitString ) except: return False ( NonceServer, NonceBounce, ServerCert ) = re.split(':', PemBaseString ) NoncePubServer = base64.decodestring( NonceServer ) # NonceServer NoncePubBounce = base64.decodestring( NonceBounce ) # NonceBounce PemServerCert = base64.decodestring( ServerCert ) # PemServerCert try: X509Cert = M2Crypto.X509.load_cert_string( PemServerCert ) except: return False # verify X509 cert EvpPKey = self.ObjMap['CA']['EvpPKey'] if dir(EvpPKey).count('_ptr'): Result = X509Cert.verify ( EvpPKey._ptr() ) else: Result = X509Cert.verify ( EvpPKey ) if not Result: return False # verify Nonce from Server encrypted with my own publickey try: NonceDecrypted = self.NonceDecryptPrivate( NoncePubServer, RsaPKey=self.ServerObj['RsaPKey'] ) except: return False ServerObjName = self.ObjNameFromPemCert( PemCert=PemServerCert ) # verify Nonce bounced from Server encrypted with server privatekey try: NonceBounceDecrypted = self.NonceDecryptPrivate( NoncePubBounce, RsaPKey=self.CurrentObj['RsaPKey'] ) except: return False return ( NonceDecrypted, NonceBounceDecrypted, ServerObjName ) def ReplyInit ( self, ReplyObjName, ReplyBounce ): NonceDecrypted = self.CreateNonce () NoncePubInit = re.sub('\012', '', base64.encodestring( self.NonceEncryptPublic ( NonceDecrypted, RsaPubKey=self.ObjMap[ ReplyObjName ]['RsaPubKey'] )) ) NoncePubBounce = re.sub('\012', '', base64.encodestring( self.NonceEncryptPublic ( ReplyBounce, RsaPubKey=self.ObjMap[ ReplyObjName ]['RsaPubKey'] )) ) ReplyString = re.sub('\012', '', base64.encodestring('%s:%s' % ( NoncePubInit, NoncePubBounce )) ) return ( NonceDecrypted, ReplyString ) def ReplyVerify ( self, ReplyString ): try: PemBaseString = base64.decodestring( ReplyString ) except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) ( NoncePubInit, NoncePubBounce ) = re.split(':', PemBaseString ) try: NoncePubInit = base64.decodestring( NoncePubInit ) # new Nonce from Remote, encrypted with own publickey except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) try: NoncePubBounce = base64.decodestring( NoncePubBounce ) # bounced Nonce from Remote, encrypted with Remote privatekey except base64.binascii.Error, msg: raise base64.binascii.Error( msg ) # verify Nonce from Remote encrypted with my own publickey try: NonceRemote = self.NonceDecryptPrivate( NoncePubInit, RsaPKey=self.ServerObj['RsaPKey'] ) except: raise AuthError( 'cannot encode nonce with own private key - abort!' ) # verify Nonce bounced from Remote encrypted with Remote privatekey try: NonceBounced = self.NonceDecryptPrivate( NoncePubBounce, RsaPKey=self.ServerObj['RsaPKey'] ) except: raise AuthError( 'wrong public key for encoding nonce - abort!' ) return ( NonceRemote, NonceBounced ) #------------------------------------------------------------------------------------------- # TEST #------------------------------------------------------------------------------------------- def CreateCAForContainer ( self ): self.CreateCert () def CreateForContainer ( self, ObjName ): """ create new pkey pair and x509 cert for specified objname result will be written in file "PyReprPem.txt" """ self.ObjFromContainer ( ObjName='AuthInstance' ) self.CreateObjCert ( ObjName=ObjName ) def Test ( self ): #self.CreateCert () #self.ExtractPublicKeyFromCert () #self.VerifyCert () ( ClientInitNonce, ClientInitString ) = self.ClientInit () ( ClientSendNonce, ClientObjName ) = self.ClientInitVerify ( InitString=ClientInitString ) ( ServerInitNonce, ServerInitString ) = self.ServerInit ( ClientObjName=ClientObjName, ClientNonce=ClientSendNonce ) ( ServerSendNonce, ClientBounceNonce, ServerObjName ) = self.ServerInitVerify ( InitString=ServerInitString ) if ClientInitNonce == ClientBounceNonce : print '100 Test Nonce bounced True' else: print '100 Test Nonce bounced False - abort!' ( ReplyInitNonce, ReplyInitString ) = self.ReplyInit ( ReplyObjName=ClientObjName, ReplyBounce=ServerSendNonce ) ( ReplySendNonce, NonceBounced ) = self.ReplyVerify ( ReplyString=ReplyInitString ) if ServerInitNonce == NonceBounced : print '100 Test Nonce bounced True' else: print '100 Test Nonce bounced False - abort!' ( Reply2InitNonce, Reply2InitString ) = self.ReplyInit ( ReplyObjName=ClientObjName, ReplyBounce=ServerSendNonce ) ( Reply2SendNonce, Nonce2Bounced ) = self.ReplyVerify ( ReplyString=Reply2InitString ) if ServerInitNonce == Nonce2Bounced : print '100 Test Nonce bounced True' else: print '100 Test Nonce bounced False - abort!' #self.NonceEncryptPrivate () #self.NonceDecryptPublic () #self.NonceVerify () #----------------------------------------------------------------------------------------------- # MAIN # # x509auth.py --ca # will create a file "PyReprPem.txt" in the current directory # append the contents of the file to the CertContainer in this script # # x509auth.py --cert # creates a file "PyReprPem.txt" in the current directory # append the contents of the file to the CertContainer in this script # # x509auth.py --test # running authentification tests with bounced nonce # #----------------------------------------------------------------------------------------------- if __name__ == '__main__': run = CertHandler () if len( sys.argv ) > 1: if sys.argv[1] == '--test': run.Test () elif sys.argv[1] == '--ca': run.CreateCert() elif sys.argv[1] == '--cert': run.CreateForContainer( sys.argv[2] ) sys.exit( 0 ) M2Crypto-0.22.6rc4/demo/bio_mem_rw.py0000664000175000017500000000177312605232411017536 0ustar matejmatej00000000000000#!/usr/bin/env python2.0 """Demonstrates the use of m2.bio_set_mem_eof_return(). Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import m2 m2.lib_init() use_mem = 1 if use_mem: bio = m2.bio_new(m2.bio_s_mem()) else: bio = m2.bio_new_file('XXX', 'wb') ciph = m2.bf_cbc() filt = m2.bio_new(m2.bio_f_cipher()) m2.bio_set_cipher(filt, ciph, 'key', 'iv', 1) m2.bio_push(filt, bio) m2.bio_write(filt, '12345678901234567890') m2.bio_flush(filt) m2.bio_pop(filt) m2.bio_free(filt) if use_mem: m2.bio_set_mem_eof_return(bio, 0) xxx = m2.bio_read(bio, 100) print `xxx`, len(xxx) m2.bio_free(bio) if use_mem: bio = m2.bio_new(m2.bio_s_mem()) m2.bio_write(bio, xxx) m2.bio_set_mem_eof_return(bio, 0) else: bio = m2.bio_new_file('XXX', 'rb') ciph = m2.bf_cbc() filt = m2.bio_new(m2.bio_f_cipher()) m2.bio_set_cipher(filt, ciph, 'key', 'iv', 0) m2.bio_push(filt, bio) yyy = m2.bio_read(filt, 100) print `yyy` m2.bio_pop(filt) m2.bio_free(filt) m2.bio_free(bio) M2Crypto-0.22.6rc4/demo/dhtest.py0000664000175000017500000000121312607370517016713 0ustar matejmatej00000000000000#!/usr/bin/env python """DH demonstration. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import DH, Rand def test(): print 'generating dh params:' a = DH.gen_params(128, 2) b = DH.set_params(a.p, a.g) a.gen_key() b.gen_key() print 'p = ', `a.p` print 'g = ', `a.g` print 'a.pub =', `a.pub` print 'a.priv =', `a.priv` print 'b.pub =', `b.pub` print 'b.priv =', `b.priv` print 'a.key = ', `a.compute_key(b.pub)` print 'b.key = ', `b.compute_key(a.pub)` if __name__=='__main__': Rand.load_file('randpool.dat', -1) test() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/dsa1024pvtkey.pem0000664000175000017500000000124012605232411020056 0ustar matejmatej00000000000000-----BEGIN DSA PRIVATE KEY----- MIIBvQIBAAKBgQD08iE3LXjSB/lA6Gq19XMzfmTvRBgFn+t9qNN6awFhrkowgyrI HaR6oCCHSvUcjdC0JcJdz8lSqofZkPknX6EEDkmlzZiUhtTZf0XiooeKigAiSlE2 PpoS4RFcOOqOwVwRJI3mC2lzypI46/OPS0IOZFsxhXQpn1xnkmpEt83ZwwIVAPNw e6agkM25mv12Il7IuBBNl3cPAoGBAKOES1BV2E3zWj6gXOXFP02dk5A+zd7z4Qj+ cx5euat07cAHYU0BZGJMTXlHSGf7YQOePuaxs9vTtSeUb1TeMFEr63Jispc9Kzce rd+E/IjiX7KCMbeGHnhtzC0FU/squZ76vp1TAXSozpfBvn73zAwAFPo/rHO4k6kH lXAez1QqAoGBAN6iYzbOnMckBtouHGBrdF4ea750DYnH5O2cij+yjgLMttuaxmZe 0iFtJpXp6m4IHKAzIGgKhUGabAz+4O2/ZnmNu0oZzXkpBLL84pksDd0nObtgueL6 sdTbhGl1kqpWRiK9T16gwqYxdcZiG5M5qbWtJIWWdv3mI9ql0XfUPWfpAhUA8e81 iGFXunNE3ecKjCOKUL2EnEA= -----END DSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/dsa_bench.py0000664000175000017500000001212112607370517017326 0ustar matejmatej00000000000000#!/usr/bin/env python """ DSA demo and benchmark. Usage: python -O dsa_bench.py [option option option ...] where options may include: makenewkey showpubkey showdigest showprofile md5 sha1 sha256 sha512 NB: DSA is formally defined with SHA-1 and key length 1024. The OpenSSL implementation actually supports most any hashing algorithm and key length, as long as the key length is longer than the digest length. If not SHA-1 and 1024, you should be very clear. The use of "DSA" without any qualifiers implies SHA-1 and 1024. Larry Bugbee November 2006 Some portions are Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004 OSAF. All Rights Reserved. """ from M2Crypto import DSA, EVP, Rand from M2Crypto.EVP import MessageDigest import sys, base64 # -------------------------------------------------------------- # program parameters makenewkey = 0 # 1 = make/save new key, 0 = use existing showpubkey = 0 # 1 = show the public key value showdigest = 0 # 1 = show the digest value showprofile = 0 # 1 = use the python profiler hashalgs = ['md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'] # default hashing algorithm hashalg = 'sha1' # default key length keylen = 1024 # number of speed test loops N1 = N2 = 100 # -------------------------------------------------------------- # functions def test(dsa, dgst): print ' testing signing and verification...', try: r,s = dsa.sign(dgst) except Exception, e: print '\n\n *** %s *** \n' % e sys.exit() if not dsa.verify(dgst, r, s): print 'not ok' else: print 'ok' def test_asn1(dsa, dgst): # XXX Randomly fails: bug in there somewhere... (0.9.4) print ' testing asn1 signing and verification...', blob = dsa.sign_asn1(dgst) if not dsa.verify_asn1(dgst, blob): print 'not ok' else: print 'ok' def speed(): from time import time t1 = time() for i in range(N1): r,s = dsa.sign(dgst) print ' %d signings: %8.2fs' % (N1, (time() - t1)) t1 = time() for i in range(N2): dsa.verify(dgst, r, s) print ' %d verifications: %8.2fs' % (N2, (time() - t1)) def test_speed(dsa, dgst): print ' measuring speed...' if showprofile: import profile profile.run('speed()') else: speed() print # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def main(keylen, hashalg): global dsa, dgst # this exists ONLY for speed testing Rand.load_file('randpool.dat', -1) pvtkeyfilename = 'DSA%dpvtkey.pem' % (keylen) pubkeyfilename = 'DSA%dpubkey.pem' % (keylen) if makenewkey: print ' making and saving a new key' dsa = DSA.gen_params(keylen) dsa.gen_key() dsa.save_key(pvtkeyfilename, None ) # no pswd callback dsa.save_pub_key(pubkeyfilename) else: print ' loading an existing key' dsa = DSA.load_key(pvtkeyfilename) print ' dsa key length:', len(dsa) if not dsa.check_key(): raise 'key is not initialised' if showpubkey: dsa_pub = dsa.pub pub_pem = base64.encodestring(dsa_pub) print ' PEM public key is: \n',pub_pem # since we are testing signing and verification, let's not # be fussy about the digest. Just make one. md = EVP.MessageDigest(hashalg) md.update('can you spell subliminal channel?') dgst = md.digest() print ' hash algorithm: %s' % hashalg if showdigest: print ' %s digest: \n%s' % (hashalg, base64.encodestring(dgst)) test(dsa, dgst) # test_asn1(dsa, dgst) test_speed(dsa, dgst) Rand.save_file('randpool.dat') # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def print_usage(): print """ Usage: python -O %s [option option option ...] where options may include: makenewkey showpubkey showdigest showprofile md5 sha1 sha256 sha512 """ % sys.argv[0] sys.exit() # -------------------------------------------------------------- # -------------------------------------------------------------- if __name__=='__main__': for arg in sys.argv[1:]: if arg in hashalgs: hashalg = arg; continue if arg == 'makenewkey': makenewkey = 1; continue if arg == 'showpubkey': showpubkey = 1; continue if arg == 'showdigest': showdigest = 1; continue if arg == 'showprofile': showprofile = 1; continue try: keylen = int(arg) except: print '\n *** argument "%s" not understood ***' % arg print_usage() main(keylen, hashalg) # -------------------------------------------------------------- # -------------------------------------------------------------- # -------------------------------------------------------------- M2Crypto-0.22.6rc4/demo/dsatest.pem0000664000175000017500000000062412605232411017211 0ustar matejmatej00000000000000-----BEGIN DSA PRIVATE KEY----- MIH4AgEAAkEA0NGZ0GRXdPLh/0c980Ot8ZbfV/DvJ19ZzsDhKXRxNNw36Ms4lb9Y ZMnJ1CliIDkpHx8sXEak0vkdeB2efGGBPQIVAJY7PF7CiA+jj+t3EyHf/sgVagPP AkEApkvDehftx8Kt+3GRsYkEgcKqsU6tue+QQOFOFYsCbMq/3rxIEKk0q1PqHfid +BsMiEY4FFmF5BqmgGAf6+V9twJATbbgPKi/EboVrtBdkTM52LSCQHPa/CEcj322 0s5Ix1dwojdQaNpq6HhCm6+g9SXPENy9I/PK85YnawI4A6w1pQIULRB2HSm1X14c +guvmhIobv6wE50= -----END DSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/dsatest.py0000664000175000017500000000231012607370517017066 0ustar matejmatej00000000000000#!/usr/bin/env python """DSA demonstration. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import DSA, EVP, Rand md=EVP.MessageDigest('sha1') md.update('can you spell subliminal channel?') dgst=md.digest() d=DSA.load_key('dsatest.pem') def test(): print 'testing signing...', r,s=d.sign(dgst) if not d.verify(dgst, r, s): print 'not ok' else: print 'ok' def test_asn1(): # XXX Randomly fails: bug in there somewhere... (0.9.4) print 'testing asn1 signing...', blob=d.sign_asn1(dgst) if not d.verify_asn1(dgst, blob): print 'not ok' else: print 'ok' def speed(): from time import time N1 = 5242 N2 = 2621 t1 = time() for i in range(N1): r,s = d.sign(dgst) print '%d signings: %8.2fs' % (N1, (time() - t1)) t1 = time() for i in range(N2): d.verify(dgst, r, s) print '%d verifications: %8.2fs' % (N2, (time() - t1)) def test_speed(): print 'measuring speed...' import profile profile.run('speed()') if __name__=='__main__': Rand.load_file('randpool.dat', -1) test() test_asn1() #test_speed() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/demo/rsa.priv.pem0000664000175000017500000000076112605232411017310 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBANQNY7RD9BarYRsmMazM1hd7a+u3QeMPFZQ7Ic+BmmeWHvvVP4Yj yu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQJAIHCz8h37N4ScZHThYJgt oIYHKpZsg/oIyRaKw54GKxZq5f7YivcWoZ8j7IQ65lHVH3gmaqKOvqdAVVt5imKZ KQIhAPPsr9i3FxU+Mac0pvQKhFVJUzAFfKiG3ulVUdHgAaw/AiEA3ozHKzfZWKxH gs8v8ZQ/FnfI7DwYYhJC0YsXb6NSvR8CIHymwLo73mTxsogjBQqDcVrwLL3GoAyz V6jf+/8HvXMbAiEAj1b3FVQEboOQD6WoyJ1mQO9n/xf50HjYhqRitOnp6ZsCIQDS AvkvYKc6LG8IANmVv93g1dyKZvU/OQkAZepqHZB2MQ== -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/rsa.priv0.pem0000664000175000017500000000115412605232411017365 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,244DDAFE6F991A53 h1/NnMxq2ku9UkBG2tfM7hCFWmOvwMbVQBYgS4jLm3ENvWRgkm7pCqjCug99Uo5o r+NhzqyvSBH+eX3ojVAfpMxkL0TIjMrogRq2TD75v6hTGu/fd4Yrw7vZaKRbLzoh rG6m7zdbiQwNyh0bTbbo3WmQ07FXkXrDqihLaZTJOvHNLS1lKwRjIS0MqtyhOfPj NNwuNEs6AFz4k6UxNMRXhyU2SXn5SOgZZB12SCIsYA034rwKFKqNRoneaLSlhtut 1z/BlJaLiZDHJmtxtgz5h3Ss9fQ9J0pLnybx+EM70TPM3hz47/8cQiEYIVg7+QFW jNYaGIA6IOcyB7fwX5e/zFy5yXAsmuIw/iP0sYa29hdUG++T8Mp2knrBBwQO77OS WRz219dMQQRyyn2jpN5x23AZyz4gHj4YKMm3KO06Y2k= -----END RSA PRIVATE KEY----- This is the same key as rsa.priv.pem. Passphrase is 'qwerty'. M2Crypto-0.22.6rc4/demo/rsa.pub.pem0000664000175000017500000000026612605232411017116 0ustar matejmatej00000000000000-----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANQNY7RD9BarYRsmMazM1hd7a+u3QeMP FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ== -----END PUBLIC KEY----- M2Crypto-0.22.6rc4/demo/rsa1024pvtkey.pem0000664000175000017500000000156712605232411020110 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDE3rnXDvA4lrIUj7ZXQM2ODLw0NnjKXh7+O3GPttvoFoacK1qk BRO+aO4hPhvQumySTz+N2RkIsT9PTx6yfyWWwYC1zbbv2cxlCBisGAvrUSL6IfHX ND2/vVN+QmOd/b4hfC/ekRo2ylrnX0pOXv/JxiblV9WumiZsBEuhUvxCnQIDAQAB AoGBALdaLEDkM8ywZQiLVCptO0RaDgqe1N68zCbBXCGaD7NXD2VxZ0itRdcnyOiC /MroZWfakPleQVd8JNeLe66IhosAJd7Zbjf/npYnD4zD1x54zRrSuBquXhz+ev7U tZONPxU5QCf/aow4z1s/M+knLyy+0lAUlWwTgOrd5VCQ8suBAkEA5/v48HZW8pQC 2zxQUFfsnRu6DxJuQ1UvWp51FNUYZM2LjpwgGyCNkCw+nuxPgM1HnOTAMVXkZdwL 7XG0Gm5ZoQJBANlAKKUc7ItOfN5TeD154Qz9FLtZUgWnWfawvEqiHJ0cPrzyv9v6 wu19QxP6ORZBWyr8c20/p2fNrk+7YOZAH30CQQDZ9p1HEWlQMlEcu+aaFoJyewKt 9pszGG6NriRDlpR84cMmEvr3gfaAZ5HOsCli031dpHAP6qvWKJHsXtDhpJ0BAkBs fANP4A+myLzF8Hx8hl4BNGej3kh9FkJwU3TS9/y935rck4OG/8NTAFf8o9jZ6izy XDnvdffMeALxQapzj9WpAkBQt2yjU3V3bKkNl0XwTk/VK8WGEWTBF1byZv/6VZOb q/vOPSexrQmu+T8+lljraJISfIpMSWZhR4oarmnGVRPX -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/demo/rsa_bench.py0000664000175000017500000001310112607370517017343 0ustar matejmatej00000000000000#!/usr/bin/env python """ RSA signing demo and benchmark. Usage: python -O rsa_bench.py [option option option ...] where options may include: makenewkey showdigest showprofile md5 sha1 sha256 sha512 Larry Bugbee November 2006 Some portions are Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004 OSAF. All Rights Reserved. """ from M2Crypto import RSA, EVP, Rand from M2Crypto.EVP import MessageDigest import sys, base64 # -------------------------------------------------------------- # program parameters makenewkey = 0 # 1 = make/save new key, 0 = use existing showpubkey = 0 # 1 = show the public key value showdigest = 0 # 1 = show the digest value showprofile = 0 # 1 = use the python profiler hashalgs = ['md5', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'] # default hashing algorithm hashalg = 'sha1' # default key parameters keylen = 1024 exponent = 65537 ''' There is some temptation to use an RSA exponent of 3 because 1) it is easy to remember and 2) it minimizes the effort of signature verification. Unfortunately there a couple of attacks based on the use of 3. From a draft RFC (Easklake, Dec 2000): A public exponent of 3 minimizes the effort needed to verify a signature. Use of 3 as the public exponent is weak for confidentiality uses since, if the same data can be collected encrypted under three different keys with an exponent of 3 then, using the Chinese Remainder Theorem [NETSEC], the original plain text can be easily recovered. This applies to confidentiality so it is not of major concern here. The second attack is a protocol implementation weakness and can be patched, but has the patch been applied? ...correctly? It is arguably better to get into the habit of using a stronger exponent and avoiding these and possible future attacks based on 3. I suggest getting in the habit of using something stronger. Some suggest using 65537. ''' # number of speed test loops N1 = N2 = 100 # -------------------------------------------------------------- # functions def test(rsa, dgst): print ' testing signing and verification...', try: sig = rsa.sign(dgst) except Exception, e: print '\n\n *** %s *** \n' % e sys.exit() if not rsa.verify(dgst, sig): print 'not ok' else: print 'ok' def test_asn1(rsa, dgst): print ' testing asn1 signing and verification...', blob = rsa.sign_asn1(dgst) if not rsa.verify_asn1(dgst, blob): print 'not ok' else: print 'ok' def speed(): from time import time t1 = time() for i in range(N1): sig = rsa.sign(dgst) print ' %d signings: %8.2fs' % (N1, (time() - t1)) t1 = time() for i in range(N2): rsa.verify(dgst, sig) print ' %d verifications: %8.2fs' % (N2, (time() - t1)) def test_speed(rsa, dgst): print ' measuring speed...' if showprofile: import profile profile.run('speed()') else: speed() print # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def main(keylen, hashalg): global rsa, dgst # this exists ONLY for speed testing Rand.load_file('randpool.dat', -1) pvtkeyfilename = 'rsa%dpvtkey.pem' % (keylen) pubkeyfilename = 'rsa%dpubkey.pem' % (keylen) if makenewkey: print ' making and saving a new key' rsa = RSA.gen_key(keylen, exponent) rsa.save_key(pvtkeyfilename, None ) # no pswd callback rsa.save_pub_key(pubkeyfilename) else: print ' loading an existing key' rsa = RSA.load_key(pvtkeyfilename) print ' rsa key length:', len(rsa) if not rsa.check_key(): raise 'key is not initialised' # since we are testing signing and verification, let's not # be fussy about the digest. Just make one. md = EVP.MessageDigest(hashalg) md.update('can you spell subliminal channel?') dgst = md.digest() print ' hash algorithm: %s' % hashalg if showdigest: print ' %s digest: \n%s' % (hashalg, base64.encodestring(dgst)) test(rsa, dgst) # test_asn1(rsa, dgst) test_speed(rsa, dgst) Rand.save_file('randpool.dat') # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def print_usage(): print """ Usage: python -O %s [option option option ...] where options may include: makenewkey showdigest showprofile md5 sha1 sha256 sha512 """ % sys.argv[0] sys.exit() # -------------------------------------------------------------- # -------------------------------------------------------------- if __name__=='__main__': for arg in sys.argv[1:]: if arg in hashalgs: hashalg = arg; continue if arg == 'makenewkey': makenewkey = 1; continue if arg == 'showpubkey': showpubkey = 1; continue if arg == 'showdigest': showdigest = 1; continue if arg == 'showprofile': showprofile = 1; continue try: keylen = int(arg) except: print '\n *** argument "%s" not understood ***' % arg print_usage() main(keylen, hashalg) # -------------------------------------------------------------- # -------------------------------------------------------------- # -------------------------------------------------------------- M2Crypto-0.22.6rc4/demo/rsatest.py0000664000175000017500000000231212607370517017106 0ustar matejmatej00000000000000#!/usr/bin/env python """RSA demonstration. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved.""" from M2Crypto import RSA, EVP, Rand msg="The magic words are squeamish ossifrage." sha1=EVP.MessageDigest('sha1') sha1.update(msg) dgst=sha1.digest() priv=RSA.load_key('rsa.priv.pem') pub=RSA.load_pub_key('rsa.pub.pem') def test_encrypt(padding): print 'testing public-key encryption:', padding padding=eval('RSA.'+padding) ctxt=pub.public_encrypt(dgst, padding) ptxt=priv.private_decrypt(ctxt, padding) if ptxt!=dgst: print 'public_encrypt -> private_decrypt: not ok' def test_sign(padding): print 'testing private-key signing:', padding padding=eval('RSA.'+padding) ctxt=priv.private_encrypt(dgst, padding) ptxt=pub.public_decrypt(ctxt, padding) if ptxt!=dgst: print 'private_decrypt -> public_encrypt: not ok' def test0(): print 'testing misc.' print `pub.e`, `pub.n` print `priv.e`, `priv.n` if __name__=='__main__': Rand.load_file('randpool.dat', -1) test_encrypt('pkcs1_padding') test_encrypt('pkcs1_oaep_padding') #test_encrypt('sslv23_padding') test_sign('pkcs1_padding') Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/doc/0000775000175000017500000000000012613362233014663 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/doc/ZServerSSL-HOWTO.html0000664000175000017500000003303012212052026020417 0ustar matejmatej00000000000000 ZServerSSL HOWTO

    ZServerSSL HOWTO

    Author: Ng Pheng Siong
    Id:ZServerSSL-HOWTO,v 1.1 2003/06/22 17:40:13 ngps Exp
    Date: 2003-06-22
    Web-Site:http://chandlerproject.org/Projects/MeTooCrypto

    Introduction

    ZServerSSL adds to Zope's ZServer the following:

    • HTTPS server
    • WebDAV-source-over-HTTPS server

    With the HTTPS server, ZServerSSL also provides WebDAV-over-HTTPS and XMLRPC-over-HTTPS access to Zope.

    These instructions apply to both Un*x and Windows installations of Zope 2.6.1. To avoid cluttering the presentation, Windows pathnames are shown in Un*x fashion.

    Preparation

    1. Download M2Crypto 0.11, contained in the file m2crypto-0.11.zip.
    2. Unpack m2crypto-0.11.zip. This will create a directory m2crypto-0.11. Henceforth, we refer to this directory as $M2.
    3. Install M2Crypto per the instructions in $M2/INSTALL.

    The ZServerSSL distribution is in $M2/demo/Zope. We shall refer to this directory as $ZSSL.

    Installation

    Below, we refer to your Zope top-level directory as $ZOPE.

    1. Copy $ZSSL/z2s.py into $ZOPE.

    2. Depending on your operating system, modify $ZOPE/start or $ZOPE/start.bat to invoke $ZOPE/z2s.py, instead of $ZOPE/z2.py. The files $ZSSL/starts and $ZSSL/starts.bat serve as examples.

    3. Copy $ZSSL/dh1024.pem into $ZOPE. This file contains Diffie-Hellman parameters for use by the SSL protocol.

    4. Copy $ZSSL/randpool.dat into $ZOPE. This file contains seed material for the OpenSSL PRNG. Alternatively, create $ZOPE/randpool.dat thusly:

      $ dd if=/dev/urandom of=randpool.dat bs=1024 count=1
      
    5. Copy $ZSSL/ca.pem to $ZOPE. This file contains an example Certification Authority (CA) certificate. For information on operating your own CA, see howto.ca.html or one of numerous similar documents available on the web.

    6. Copy $ZSSL/server.pem to $ZOPE. This file contains an RSA key pair and its X.509v3 certificate issued by the above CA. You may also create your own key/certificate bundle.

    7. Copy $ZSSL/ZServer/HTTPS_Server.py to $ZOPE/ZServer.

    8. Copy $ZSSL/ZServer/__init__.py to $ZOPE/ZServer. This overwrites the existing $ZOPE/ZServer/__init__.py. Alternatively, apply the following patch to $ZOPE/ZServer/__init__.py:

      --- __init__.py.org     Sat Jun 21 23:20:41 2003
      +++ __init__.py Tue Jan  7 23:30:53 2003
      @@ -84,6 +84,7 @@
       import asyncore
       from medusa import resolver, logger
       from HTTPServer import zhttp_server, zhttp_handler
      +from HTTPS_Server import zhttps_server, zhttps_handler
       from PCGIServer import PCGIServer
       from FCGIServer import FCGIServer
       from FTPServer import FTPServer
      
    9. Copy $ZSSL/ZServer/medusa/https_server.py to $ZOPE/ZServer/medusa.

    10. Stop Zope, if it is running.

    11. Start Zope with ZServerSSL thusly:

      ./starts -X -f 9021 -w 9080 -W 9081 -y 9443 -Y 9444
      

      This starts the following:

      • an FTP server on port 9021
      • a HTTP server on port 9080
      • a WebDAV-source server on port 9081
      • a HTTPS server on port 9443
      • a WebDAV-source-over-HTTPS server on port 9444

    Testing

    Below, we assume your Zope server is running on localhost.

    HTTPS

    This testing is done with Mozilla 1.1 on FreeBSD.

    1. With a browser, connect to https://localhost:9443/. Browse around. Check out your browser's HTTPS informational screens.
    2. Connect to https://localhost:9443/manage. Verify that you can access Zope's management functionality.

    WebDAV-over-HTTPS

    This testing is done with Cadaver 0.21.0 on FreeBSD.

    $ cadaver https://localhost:9443/
    WARNING: Untrusted server certificate presented:
    Issued to: M2Crypto, SG
    Issued by: M2Crypto, SG
    Do you wish to accept the certificate? (y/n) y
    dav:/> ls
    Listing collection `/': succeeded.
    Coll:   Channels                               0  Jun 19 00:04
    Coll:   Control_Panel                          0  Jun  6 00:13
    Coll:   Examples                               0  Jun  6 00:12
    Coll:   catalog                                0  Jun 12 11:53
    Coll:   ngps                                   0  Jun 16 15:34
    Coll:   portal                                 0  Jun 21 15:21
    Coll:   skunk                                  0  Jun 18 21:18
    Coll:   temp_folder                            0  Jun 22 17:57
    Coll:   zope                                   0  Jun 20 15:27
            acl_users                              0  Dec 30  1998
            browser_id_manager                     0  Jun  6 00:12
            default.css                         3037  Jun 21 16:38
            error_log                              0  Jun  6 00:12
            index_html                           313  Jun 12 13:36
            portal0                                0  Jun 21 15:21
            session_data_manager                   0  Jun  6 00:12
            standard_error_message              1365  Jan 21  2001
            standard_html_footer                  50  Jun 12 12:30
            standard_html_header                  80  Jan 21  2001
            standard_template.pt                 282  Jun  6 00:12
            zsyncer                                0  Jun 17 15:28
    dav:/> quit
    Connection to `localhost' closed.
    $ 
    

    WebDAV-Source-over-HTTPS

    This testing is done with Mozilla 1.1 on FreeBSD.

    1. Open the Mozilla Composer window.
    2. Click "File", "Open Web Location". A dialog box appears.
    3. Enter https://localhost:9444/index_html for the URL.
    4. Select "Open in new Composer window."
    5. Click "Open". A new Composer window will open with index_html loaded.

    Python with M2Crypto

    This testing is done with M2Crypto 0.11 and Python 2.2.2 on FreeBSD.

    HTTPS

    >>> from M2Crypto import Rand, SSL, m2urllib
    >>> url = m2urllib.FancyURLopener()
    >>> url.addheader('Connection', 'close')
    >>> u = url.open('https://127.0.0.1:9443/')
    send: 'GET / HTTP/1.1\r\nHost: 127.0.0.1:9443\r\nAccept-Encoding: identity\r\nUser-agent: Python-urllib/1.15\r\nConnection: close\r\n\r\n'
    reply: 'HTTP/1.1 200 OK\r\n'
    header: Server: ZServerSSL/0.11
    header: Date: Sun, 22 Jun 2003 13:42:34 GMT
    header: Connection: close
    header: Content-Type: text/html
    header: Etag: 
    header: Content-Length: 535
    >>> while 1:
    ...     data = u.read()
    ...     if not data: break
    ...     print data
    ... 
    
    <html><head>
    <base href="https://127.0.0.1:9443/" />
    <title>Zope</title></head><body bgcolor="#FFFFFF">
    
    <h1>NgPS Desktop Portal</h1>
    
    &nbsp;&nbsp;So many hacks.<br>
    &nbsp;&nbsp;So little time.<br>
    
    <h2>Link Farm</h2>
    <ul>
    <li><a href="http://localhost:8080/portal">Portal</a></li>
    <li><a href="http://localhost/">Local Apache Home Page</a></li>
    </ul>
    
    <hr><a href="http://www.zope.org/Credits" target="_top"><img src="https://127.0.0.1:9443/p_/ZopeButton" width="115" height="50" border="0" alt="Powered by Zope" /></a></body></html>
    
    >>> u.close()
    >>> 
    

    XMLRPC-over-HTTPS

    >>> from M2Crypto.m2xmlrpclib import Server, SSL_Transport
    >>> zs = Server('https://127.0.0.1:9443/', SSL_Transport())
    >>> print zs.propertyMap()
    [{'type': 'string', 'id': 'title', 'mode': 'w'}]
    >>> 
    

    Conclusion

    Well, it works! ;-)

    M2Crypto-0.22.6rc4/doc/howto.ca.html0000664000175000017500000005007612212052026017272 0ustar matejmatej00000000000000HOWTO: Creating your own CA with OpenSSL

    HOWTO: Creating your own CA with OpenSSL

    Pheng Siong Ng

    ngps@post1.com

    Revision History
    Revision $Revision: 1.1 $$Date: 2003/06/22 16:41:18 $


    Introduction

    This is a HOWTO on creating your own certification authority (CA) with OpenSSL.

    I last created a CA about a year ago, when I began work on M2Crypto and needed certificates for the SSL bits. I accepted the tools' default settings then, e.g., certificate validity of 365 days; this meant that my certificates, including my CA's certificate, have now expired.

    Since I am using these certificates for M2Crypto's demonstration programs (and I have forgotten the passphrase to the CA's private key), I decided to discard the old CA and start afresh. I also decided to document the process, hence this HOWTO.


    The Procedure

    I use CA.pl, a Perl program written by Steve Hanson and bundled with OpenSSL.

    The following are the steps to create a CA:

    1. Choose a directory to do your CA work. All commands are executed within this directory. Let's call the directory demo.

    2. Copy CA.pl and openssl.cnf into demo.

    3. Apply the following patch to CA.pl, which allows it to generate a CA certificate with a validity period of 1095 days, i.e., 3 years:

          --- CA.pl.org   Sat Mar 31 12:40:13 2001
          +++ CA.pl       Sat Mar 31 12:41:15 2001
          @@ -97,7 +97,7 @@
                          } else {
                              print "Making CA certificate ...\n";
                              system ("$REQ -new -x509 -keyout " .
          -                       "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS");
          +                       "${CATOP}/private/$CAKEY -out ${CATOP}/$CACERT -days 1095");
                              $RET=$?;
                          }
                      }
          
    4. Create a new CA like this:

          ./CA.pl -newca
          
          A certificate filename (or enter to create) <enter>
          
          Making CA certificate ...
          Using configuration from openssl.cnf
          Generating a 1024 bit RSA private key
          ............++++++
          ......................++++++
          writing new private key to './demoCA/private/cakey.pem'
          Enter PEM pass phrase: <secret passphrase here>
          Verifying password - Enter PEM pass phrase: <secret passphrase again>
          -----
          You are about to be asked to enter information that will be incorporated
          into your certificate request.
          What you are about to enter is what is called a Distinguished Name or a DN.
          There are quite a few fields but you can leave some blank
          For some fields there will be a default value,
          If you enter '.', the field will be left blank.
          -----
          Country Name (2 letter code) [AU]:SG
          State or Province Name (full name) [Some-State]:.
          Locality Name (eg, city) []:..
          Organization Name (eg, company) [Internet Widgits Pty Ltd]:DemoCA
          Organizational Unit Name (eg, section) []:.
          Common Name (eg, YOUR name) []:DemoCA Certificate Master
          Email Address []:certmaster@democa.dom
          

      This creates a new CA in the directory demoCA. The CA's self-signed certificate is in demoCA/cacert.pem and its RSA key pair is in demoCA/private/cakey.pem.

      demoCA/private/cakey.pem looks like this:

          cat demoCA/private/cakey.pem
          
          -----BEGIN RSA PRIVATE KEY-----
          Proc-Type: 4,ENCRYPTED
          DEK-Info: DES-EDE3-CBC,19973A9DBBB601BA
      
          eOq9WFScNiI4/UWEUaSnGTKpJv2JYuMD3HwQox2Q3Cd4zGqVjJ6gF3exa5126cKf
          X/bMVnwbPpuFZPiAIvaLyCjT6pYeXTBbSzs7/GQnvEOv+nYnDUFWi0Qm92qLk0uy
          pFi/M1aWheN3vir2ZlAw+DW0bOOZhj8tC7Co7lMYb0YE271b6/YRPZCwQ3GXAHUJ
          +aMYxlUDrK45aCUa/1CZDzTgk7h9cDgx2QJSIvYMYytCfI3zsuZMJS8/4OXLL0bI
          lKmAc1dwB3DqGJt5XK4WJesiNfdxeCNEgAcYtEAgYZTPIApU+kTgTCIxJl2nMW7j
          ax+Q1z7g+4MpgG20WD633D4z4dTlDdz+dnLi0rvuvxiwt+dUhrqiML1tyi+Z6EBH
          jU4/cLBWev3rYfrlp4x8J9mDte0YKOk3t0wQOHqRetTsIfdtjnFp/Hu3qDmTCWjD
          z/g7PPoO/bg/B877J9WBPbL/1hXXFYo88M+2aGlPOgDcFdiOqbLb2DCscohMbbVr
          A4mgiy2kwWfIE73qiyV7yyG8FlRvr1iib+jbT3LTGf743utYAAs7HNGuOUObhoyt
          jYvBD7ACn35P5YX7KTqvqErwdijxYCaNBCnvmRtmYSaNw9Kv1UJTxc5Vx7YLwIPk
          E9KyBgKI7vPOjWBZ27+zOvNycmv1ciNtpALAw4bWtXnhCDVTHaVDy34OkheMzNCg
          2cjcBFzOkMIjcI03KbTQXOFIQGlsTWXGzkNf/zBQ+KksT1MCj+zBXSCvlDASMckg
          kef21pGgUqPF14gKGfWX3sV4bjc1vbrRwq6zlG3nMuYqR5MtJJY9eQ==
          -----END RSA PRIVATE KEY-----
          
    5. Next, generate a certificate request.

          ./CA.pl -newreq
          
          Using configuration from openssl.cnf
          Generating a 1024 bit RSA private key
          ..........++++++
          ..............++++++
          writing new private key to 'newreq.pem'
          Enter PEM pass phrase: <another secret passphrase here>
          Verifying password - Enter PEM pass phrase: <another secret passphrase again>
          -----
          You are about to be asked to enter information that will be incorporated
          into your certificate request.
          What you are about to enter is what is called a Distinguished Name or a DN.
          There are quite a few fields but you can leave some blank
          For some fields there will be a default value,
          If you enter '.', the field will be left blank.
          -----
          Country Name (2 letter code) [AU]:SG
          State or Province Name (full name) [Some-State]:..
          Locality Name (eg, city) []:.
          Organization Name (eg, company) [Internet Widgits Pty Ltd]:M2Crypto
          Organizational Unit Name (eg, section) []:.
          Common Name (eg, YOUR name) []:localhost
          Email Address []:admin@server.example.dom
          
          Please enter the following 'extra' attributes
          to be sent with your certificate request
          A challenge password []:<enter>
          An optional company name []:<enter>
          Request (and private key) is in newreq.pem
          

      The certificate request and private key in newreq.pem looks like this:

          cat newreq.pem
          
          -----BEGIN RSA PRIVATE KEY-----
          Proc-Type: 4,ENCRYPTED
          DEK-Info: DES-EDE3-CBC,41B2874DF3D02DD4
          
          mg611EoVkLEooSTv+qTM0Ddmm/M1jE/Jy5RD/sc3LSMhuGu9xc26OgsTJmkQuIAh
          J/B4lAw8G59VTG6DykeEtrG0rUBx4bggc7PKbFuiN423YjJODWcHvVgnPOzXMQt+
          lY4tPl5+217MRHyx2NsWGrpkQNdu3GeSPOVMl3jeQiaXupONbwQ7rj42+X/VtAJP
          W4D1NNwu8aGCPyShsEXHc/fI1WDpphYWke97pOjIZVQESFZOPty5HjIYZux4U+td
          W81xODtq2ecJXc8fn2Wpa9y5VD1LT7oJksOuL1+Z04OVaeUe4x0swM17HlBm2kVt
          fe/C/L6kN27MwZhE331VjtTjSGl4/gknqQDbLOtqT06f3OISsDJETm2itllyhgzv
          C6Fi3N03rGFmKectijC+tws5k+P+HRG6sai33usk8xPokJqA+HYSWPz1XVlpRmv4
          kdjQOdST7ovU62mOTgf3ARcduPPwuzTfxOlYONe5NioO1APVHBrInQwcpLkpOTQR
          vI4roIN+b75/nihUWGUJn/nbbBa2Yl0N5Gs1Tyiy9Z+CcRT2TfWKBBFlEUIFl7Mb
          J9fTV3DI+k+akbR4il1NkQ8EcSmCr3WpA0I9n0EHI7ZVpVaHxc0sqaPFl8YGdFHq
          1Qk53C/w6+qPpDzT3yKFmG2LZytAAM1czvb6RbNRJJP2ZrpBwn/h99sUTo/yPfxY
          nueYmFJDm0uVNtG0icXGNUfSfnjKNTtHPAgyKGetRIC3kgJz/bo2w7EI6iEjBAzK
          l5TRm4x6ZJxwuXXMiJCehMMd8TC8ybwWO4AO19B3ebFFeTVsUgxSGA==
          -----END RSA PRIVATE KEY-----
          -----BEGIN CERTIFICATE REQUEST-----
          MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw
          EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l
          eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r
          uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM
          MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv
          tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB
          AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi
          PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K
          9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC
          -----END CERTIFICATE REQUEST-----
          

      Decoding the certificate request gives the following:

          openssl req -text -noout < newreq.pem
          
          Using configuration from /usr/local/pkg/openssl/openssl.cnf
          Certificate Request:
              Data:
                  Version: 0 (0x0)
                  Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom
                  Subject Public Key Info:
                      Public Key Algorithm: rsaEncryption
                      RSA Public Key: (1024 bit)
                          Modulus (1024 bit):
                              00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50:
                              91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e:
                              6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13:
                              21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4:
                              c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac:
                              4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f:
                              6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9:
                              6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f:
                              0b:6f:e7:1c:bc:a6:59:97:ef
                          Exponent: 65537 (0x10001)
                  Attributes:
                      a0:00
              Signature Algorithm: md5WithRSAEncryption
                  7a:68:46:9e:58:4b:9e:42:66:9c:be:c1:d8:a0:40:4c:23:2f:
                  fc:12:96:eb:e8:f9:68:ed:a6:f3:f4:62:80:4c:26:ee:15:30:
                  a7:99:8b:8d:39:47:ba:3c:a0:4c:22:3d:d9:6b:ae:58:8a:36:
                  49:c5:98:72:88:68:22:93:2d:17:14:e7:d4:9c:03:a0:03:10:
                  85:94:ce:a9:94:cc:fe:42:b3:a8:eb:49:1a:37:34:a7:e0:d5:
                  b7:74:f4:3d:4a:f6:bb:10:91:17:3d:52:bb:fd:99:10:48:b2:
                  b7:9d:1a:76:04:08:d7:91:68:ae:51:d7:2c:e9:3a:8c:27:8a:
                  75:c2
          
    6. Now, sign the certificate request:

          ./CA.pl -sign
          
          Using configuration from openssl.cnf
          Enter PEM pass phrase: <CA's passphrase>
          Check that the request matches the signature
          Signature ok
          The Subjects Distinguished Name is as follows
          countryName           :PRINTABLE:'SG'
          organizationName      :PRINTABLE:'M2Crypto'
          commonName            :PRINTABLE:'localhost'
          emailAddress          :IA5STRING:'admin@server.example.dom'
          Certificate is to be certified until Mar 31 02:57:30 2002 GMT (365 days)
          Sign the certificate? [y/n]:y
          
          
          1 out of 1 certificate requests certified, commit?  [y/n]y
          Write out database with 1 new entries
          Data Base Updated
          Signed certificate is in newcert.pem
          

      newcert.pem looks like this:

          cat newcert.pem
          
          Certificate:
              Data:
                  Version: 3 (0x2)
                  Serial Number: 1 (0x1)
                  Signature Algorithm: md5WithRSAEncryption
                  Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom
                  Validity
                      Not Before: Mar 31 02:57:30 2001 GMT
                      Not After : Mar 31 02:57:30 2002 GMT
                  Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom
                  Subject Public Key Info:
                      Public Key Algorithm: rsaEncryption
                      RSA Public Key: (1024 bit)
                          Modulus (1024 bit):
                              00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50:
                              91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e:
                              6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13:
                              21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4:
                              c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac:
                              4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f:
                              6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9:
                              6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f:
                              0b:6f:e7:1c:bc:a6:59:97:ef
                          Exponent: 65537 (0x10001)
                  X509v3 extensions:
                      X509v3 Basic Constraints: 
          Certificate:
              Data:
                  Version: 3 (0x2)
                  Serial Number: 1 (0x1)
                  Signature Algorithm: md5WithRSAEncryption
                  Issuer: C=SG, O=DemoCA, CN=DemoCA Certificate Master/Email=certmaster@democa.dom
                  Validity
                      Not Before: Mar 31 02:57:30 2001 GMT
                      Not After : Mar 31 02:57:30 2002 GMT
                  Subject: C=SG, O=M2Crypto, CN=localhost/Email=admin@server.example.dom
                  Subject Public Key Info:
                      Public Key Algorithm: rsaEncryption
                      RSA Public Key: (1024 bit)
                          Modulus (1024 bit):
                              00:af:59:d8:63:54:2b:96:5d:6b:b8:1f:c5:aa:50:
                              91:ae:be:67:be:ea:5d:20:df:b7:c0:5e:ea:f7:5e:
                              6d:bc:44:28:73:be:1b:9e:ee:9b:f0:86:db:19:13:
                              21:cd:dc:e6:bd:0e:12:cc:57:d5:10:0b:8c:32:e4:
                              c7:7b:26:cf:ab:9b:61:ed:80:eb:4c:d8:b3:28:ac:
                              4e:06:7a:84:d8:a6:2e:5f:d5:f6:d8:0d:4a:87:8f:
                              6c:a0:92:45:83:a9:0f:6f:d3:14:82:26:41:88:c9:
                              6f:b5:be:ca:dc:21:df:83:0e:56:6a:05:a7:2e:5f:
                              0b:6f:e7:1c:bc:a6:59:97:ef
                          Exponent: 65537 (0x10001)
                  X509v3 extensions:
                      X509v3 Basic Constraints: 
                          CA:FALSE
                      Netscape Comment: 
                          OpenSSL Generated Certificate
                      X509v3 Subject Key Identifier: 
                          B3:D6:89:88:2F:B1:15:40:EC:0A:C0:30:35:3A:B7:DA:72:73:1B:4D
                      X509v3 Authority Key Identifier: 
                          keyid:F9:6A:A6:34:97:6B:BC:BB:5A:17:0D:19:FC:62:21:0B:00:B5:0E:29
                          DirName:/C=SG/O=DemoCA/CN=DemoCA Certificate Master/Email=certmaster@democa.dom
                          serial:00
          
              Signature Algorithm: md5WithRSAEncryption
          
    7. In certain situations, e.g., where your certificate and private key are to be used in an unattended SSL server, you may wish to not encrypt the private key, i.e., leave the key in the clear. This decision should be governed by your site's security policy and threat model, of course.

          openssl rsa < newkey.pem > newkey2.pem
          
          read RSA key
          Enter PEM pass phrase:<secret passphrase here>
          writing RSA key
          

      newkey2.pem looks like this:

          cat newkey2.pem
          
          -----BEGIN RSA PRIVATE KEY-----
          MIICXgIBAAKBgQCvWdhjVCuWXWu4H8WqUJGuvme+6l0g37fAXur3Xm28RChzvhue
          7pvwhtsZEyHN3Oa9DhLMV9UQC4wy5Md7Js+rm2HtgOtM2LMorE4GeoTYpi5f1fbY
          DUqHj2ygkkWDqQ9v0xSCJkGIyW+1vsrcId+DDlZqBacuXwtv5xy8plmX7wIDAQAB
          AoGAbAkU8w3W1Qu15Hle1bJSL7GMReoreqeblOBmMAZz4by0l6sXZXJpjWXo86f/
          +dASMYTMPC4ZTYtv06N07AFbjL+kDfqDMTfzQkYMHp1LAq1Ihbq1rHWSBH5n3ekq
          KiY8JKpv8DR5Po1iKaXJFuDByGDENJwYbSRSpSK3P+vkWWECQQDkEUE/ZPqqqZkQ
          2iWRPAsCbEID8SAraQl3DdCLYs/GgARfmmj4yUHEwkys9Jo1H8k4BdxugmaUwNi5
          YQ/CVzrXAkEAxNO80ArbGxPUmr11GHG/bGBYj1DUBkHZSc7dgxZdtUCLGNxQnNsg
          Iwq3n6j1sUzS3UW6abQ8bivYNOUcMKJAqQJBANQxFaLU4b/NQaODQ3aoBZpAfP9L
          5eFdvbet+7zjt2r5CpikgkwOfAmDuXEltx/8LevY0CllW+nErx9zJgVrwUsCQQCu
          76H5JiznPBDSF2FjgHWqVVdgyW4owY3mU739LHvNBLicN/RN9VPy0Suy8/CqzKT9
          lWPBXzf2k3FuUdNkRlFBAkEAmpXoybuiFR2S5Bma/ax96lVs0/VihhfC1zZP/X/F
          Br77+h9dIul+2DnyOl50zu0Sdzst1/7ay4JSDHyiBCMGSQ==
          -----END RSA PRIVATE KEY-----
          

    That's it! The certificate, newcert.pem, and the private key - newkey.pem (encrypted) or newkey2.pem (unencrypted) - are now ready to be used. You may wish to rename the files to more intuitive names.

    You should also keep the CA's certificate demo/cacert.pem handy for use when developing and deploying SSL or S/MIME applications.


    Conclusion

    We've walked through the basic steps in the creation of a CA and certificates using the tools that come with OpenSSL. We did not cover more advanced topics such as constraining a certificate to be SSL-only or S/MIME-only.

    There exist several HOWTOs similar to this one on the net. This one is written specifically to facilitate discussions in my other HOWTOs on developing SSL and S/MIME applications in Python using M2Crypto.


    $Id:howto.ca.html 583 2007-10-01 19:23:12Z heikki $

    M2Crypto-0.22.6rc4/doc/howto.smime.html0000664000175000017500000011054312611255457020035 0ustar matejmatej00000000000000HOWTO: Programming S/MIME in Python with M2Crypto

    HOWTO: Programming S/MIME in Python with M2Crypto

    Pheng Siong Ng

    ngps@post1.com

    Revision History
    Revision $Id$


    Introduction

    M2Crypto is a Python interface to OpenSSL. It makes available to the Python programmer SSL functionality to implement clients and servers, S/MIME v2, RSA, DSA, DH, symmetric ciphers, message digests and HMACs.

    This document demonstrates programming S/MIME with M2Crypto.


    S/MIME

    S/MIME - Secure Multipurpose Internet Mail Extensions [RFC 2311, RFC 2312] - provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications - authentication, message integrity and non-repudiation of origin (using digital signatures), and privacy and data security (using encryption).


    Keys and Certificates

    To create an S/MIME-signed message, you need an RSA key pair (this consists of a public key and a private key) and an X.509 certificate of said public key.

    To create an S/MIME-encrypted message, you need an X.509 certificate for each recipient.

    To create an S/MIME-signed and -encrypted message, first create a signed message, then encrypt the signed message with the recipients' certificates.

    You may generate key pairs and obtain certificates by using a commercial certification authority service.

    You can also do so using freely-available software. For many purposes, e.g., automated S/MIME messaging by system administration processes, this approach is cheap and effective.

    We now work through using OpenSSL to generate key pairs and certificates. This assumes you have OpenSSL installed properly on your system.

    First, we generate an X.509 certificate to be used for signing:

        openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out signer.pem
        
        Using configuration from /usr/local/pkg/openssl/openssl.cnf
        Generating a 1024 bit RSA private key
        ..++++++
        ....................++++++
        writing new private key to 'privkey.pem'
        -----
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [AU]:SG
        State or Province Name (full name) [Some-State]:.
        Locality Name (eg, city) []:.
        Organization Name (eg, company) [Internet Widgits Pty Ltd]:M2Crypto
        Organizational Unit Name (eg, section) []:.
        Common Name (eg, YOUR name) []:S/MIME Sender
        Email Address []:sender@example.dom
        

    This generates a 1024-bit RSA key pair, unencrypted, into privkey.pem; it also generates a self-signed X.509 certificate for the public key into signer.pem. The certificate is valid for 365 days, i.e., a year.

    Let's rename privkey.pem so that we know it is a companion of signer.pem's:

        mv privkey.pem signer_key.pem
        

    To verify the content of signer.pem, execute the following:

        openssl x509 -noout -text -in signer.pem
        
        Certificate:
            Data:
                Version: 3 (0x2)
                Serial Number: 0 (0x0)
                Signature Algorithm: md5WithRSAEncryption
                Issuer: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom
                Validity
                    Not Before: Mar 24 12:56:16 2001 GMT
                    Not After : Mar 24 12:56:16 2002 GMT
                Subject: C=SG, O=M2Crypto, CN=S/MIME Sender/Email=sender@example.dom
                Subject Public Key Info:
                    Public Key Algorithm: rsaEncryption
                    RSA Public Key: (1024 bit)
                        Modulus (1024 bit):
                            00:a9:d6:e2:b5:11:3b:ae:3c:e2:17:31:70:e1:6e:
                            01:f4:19:6d:bd:2a:42:36:2b:37:34:e2:83:1d:0d:
                            11:2e:b4:99:44:db:10:67:be:97:5f:5b:1a:26:33:
                            46:23:2f:95:04:7a:35:da:9d:f9:26:88:39:9e:17:
                            cd:3e:eb:a8:19:8d:a8:2a:f1:43:da:55:a9:2e:2c:
                            65:ed:04:71:42:ce:73:53:b8:ea:7e:c7:f0:23:c6:
                            63:c5:5e:68:96:64:a7:b4:2a:94:26:76:eb:79:ea:
                            e3:4e:aa:82:09:4f:44:87:4a:12:62:b5:d7:1f:ca:
                            f2:ce:d5:ba:7e:1f:48:fd:b9
                        Exponent: 65537 (0x10001)
                X509v3 extensions:
                    X509v3 Subject Key Identifier: 
                        29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99
                    X509v3 Authority Key Identifier: 
                        keyid:29:FB:38:B6:BF:E2:40:BB:FF:D5:71:D7:D5:C4:F0:83:1A:2B:C7:99
                        DirName:/C=SG/O=M2Crypto/CN=S/MIME Sender/Email=sender@example.dom
                        serial:00
        
                    X509v3 Basic Constraints: 
                        CA:TRUE
            Signature Algorithm: md5WithRSAEncryption
                68:c8:6b:1b:fa:7c:9a:39:35:76:18:15:c9:fd:89:97:62:db:
                7a:b0:2d:13:dd:97:e8:1b:7a:9f:22:27:83:24:9d:2e:56:ec:
                97:89:3c:ef:16:55:80:5a:18:7c:22:d0:f6:bb:e3:a4:e8:59:
                30:ff:99:5a:93:3e:ea:bc:ee:7f:8d:d6:7d:37:8c:ac:3d:74:
                80:ce:7a:99:ba:27:b9:2a:a3:71:fa:a5:25:ba:47:17:df:07:
                56:96:36:fd:60:b9:6c:96:06:e8:e3:7b:9f:4b:6a:95:71:a8:
                34:fc:fc:b5:88:8b:c4:3f:1e:24:f6:52:47:b2:7d:44:67:d9:
                83:e8
        

    Next, we generate a self-signed X.509 certificate for the recipient. Note that privkey.pem will be recreated.

        openssl req -newkey rsa:1024 -nodes -x509 -days 365 -out recipient.pem
        
        Using configuration from /usr/local/pkg/openssl/openssl.cnf
        Generating a 1024 bit RSA private key
        .....................................++++++
        .................++++++
        writing new private key to 'privkey.pem'
        -----
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [AU]:SG
        State or Province Name (full name) [Some-State]:.
        Locality Name (eg, city) []:.
        Organization Name (eg, company) [Internet Widgits Pty Ltd]:M2Crypto
        Organizational Unit Name (eg, section) []:.
        Common Name (eg, YOUR name) []:S/MIME Recipient
        Email Address []:recipient@example.dom
        

    Again, rename privkey.pem:

        mv privkey.pem recipient_key.pem
        

    In the examples to follow, S/MIME Sender, , shall be the sender of S/MIME messages, while S/MIME Recipient, , shall be the recipient of S/MIME messages.

    Armed with the key pairs and certificates, we are now ready to begin programming S/MIME in Python.

    Note: The private keys generated above are not passphrase-protected, i.e., they are in the clear. Anyone who has access to such a key can generate S/MIME-signed messages with it, and decrypt S/MIME messages encrypted to it's corresponding public key.

    We may passphrase-protect the keys, if we so choose. M2Crypto will prompt the user for the passphrase when such a key is being loaded.


    M2Crypto.SMIME

    The Python programmer accesses M2Crypto's S/MIME functionality through class SMIME in the module M2Crypto.SMIME. Typically, an SMIME object is instantiated; the object is then set up for the intended operation: sign, encrypt, decrypt or verify; finally, the operation is invoked on the object.

    M2Crypto.SMIME makes extensive use of M2Crypto.BIO: M2Crypto.BIO is a Python abstraction of the BIO abstraction in OpenSSL. A commonly used BIO abstraction in M2Crypto is M2Crypto.BIO.MemoryBuffer, which implements a memory-based file-like object, similar to Python's own StringIO.


    Sign

    The following code demonstrates how to generate an S/MIME-signed message. randpool.dat contains random data which is used to seed OpenSSL's pseudo-random number generator via M2Crypto.

        from M2Crypto import BIO, Rand, SMIME
    
        def makebuf(text):
            return BIO.MemoryBuffer(text)
    
        # Make a MemoryBuffer of the message.
        buf = makebuf('a sign of our times')
    
        # Seed the PRNG.
        Rand.load_file('randpool.dat', -1)
    
        # Instantiate an SMIME object; set it up; sign the buffer.
        s = SMIME.SMIME()
        s.load_key('signer_key.pem', 'signer.pem')
        p7 = s.sign(buf, SMIME.PKCS7_DETACHED)
        

    p7 now contains a PKCS #7 signature blob wrapped in an M2Crypto.SMIME.PKCS7 object. Note that buf has been consumed by sign() and has to be recreated if it is to be used again.

    We may now send the signed message via SMTP. In these examples, we shall not do so; instead, we'll render the S/MIME output in mail-friendly format, and pretend that our messages are sent and received correctly.

        # Recreate buf.
        buf = makebuf('a sign of our times')
    
        # Output p7 in mail-friendly format.
        out = BIO.MemoryBuffer()
        out.write('From: sender@example.dom\n')
        out.write('To: recipient@example.dom\n')
        out.write('Subject: M2Crypto S/MIME testing\n')
        s.write(out, p7, buf)
    
        print out.read()
    
        # Save the PRNG's state.
        Rand.save_file('randpool.dat')
        

    Here's the output:

        From: sender@example.dom
        To: recipient@example.dom
        Subject: M2Crypto S/MIME testing
        MIME-Version: 1.0
        Content-Type: multipart/signed ; protocol="application/x-pkcs7-signature" ; micalg=sha1 ; boundary="----3C93156FC7B4EBF49FE9C7DB7F503087"
        
        This is an S/MIME signed message
        
        ------3C93156FC7B4EBF49FE9C7DB7F503087
        a sign of our times
        ------3C93156FC7B4EBF49FE9C7DB7F503087
        Content-Type: application/x-pkcs7-signature; name="smime.p7s"
        Content-Transfer-Encoding: base64
        Content-Disposition: attachment; filename="smime.p7s"
        
        MIIE8AYJKoZIhvcNAQcCoIIE4TCCBN0CAQExCzAJBgUrDgMCGgUAMCIGCSqGSIb3
        DQEHAaAVBBNhIHNpZ24gb2Ygb3VyIHRpbWVzoIIC5zCCAuMwggJMoAMCAQICAQAw
        DQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRv
        MRYwFAYDVQQDEw1TL01JTUUgU2VuZGVyMSEwHwYJKoZIhvcNAQkBFhJzZW5kZXJA
        ZXhhbXBsZS5kb20wHhcNMDEwMzMxMTE0MDMzWhcNMDIwMzMxMTE0MDMzWjBbMQsw
        CQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBT
        ZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbTCBnzANBgkq
        hkiG9w0BAQEFAAOBjQAwgYkCgYEA5c5Tj1CHTSOxa1q2q0FYiwMWYHptJpJcvtZm
        UwrgU5sHrA8OnCM0cDXEj0KPf3cfNjHffB8HWMzI4UEgNmFXQNsxoGZ+iqwxLlNj
        y9Mh7eFW/Bjq5hNXbouSlQ0rWBRkoxV64y+t6lQehb32WfYXQbKFxFJSXzSxOx3R
        8YhSPd0CAwEAAaOBtjCBszAdBgNVHQ4EFgQUXOyolL1t4jaBwZFRM7MS8nBLzUow
        gYMGA1UdIwR8MHqAFFzsqJS9beI2gcGRUTOzEvJwS81KoV+kXTBbMQswCQYDVQQG
        EwJTRzERMA8GA1UEChMITTJDcnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIx
        ITAfBgkqhkiG9w0BCQEWEnNlbmRlckBleGFtcGxlLmRvbYIBADAMBgNVHRMEBTAD
        AQH/MA0GCSqGSIb3DQEBBAUAA4GBAHo3DrCHR86fSTVAvfiXdSswWqKtCEhUHRdC
        TLFGl4hDk2GyZxaFuqZwiURz/H7nMicymI2wkz8H/wyHFg8G3BIehURpj2v/ZWXY
        eovbgS7EZALVVkDj4hNl/IIHWd6Gtv1UODf7URbxtl3hQ9/eTWITrefT1heuPnar
        8czydsOLMYIBujCCAbYCAQEwYDBbMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJD
        cnlwdG8xFjAUBgNVBAMTDVMvTUlNRSBTZW5kZXIxITAfBgkqhkiG9w0BCQEWEnNl
        bmRlckBleGFtcGxlLmRvbQIBADAJBgUrDgMCGgUAoIGxMBgGCSqGSIb3DQEJAzEL
        BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAxMDMzMTExNDUwMlowIwYJKoZI
        hvcNAQkEMRYEFOoeRUd8ExIYXfQq8BTFuKWrSP3iMFIGCSqGSIb3DQEJDzFFMEMw
        CgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsO
        AwIHMA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIGAQpU8hFUtLCF6hO2t
        ec9EYJ/Imqqiiw+BxWxkUUVT81Vbjwdn9JST6+sztM5JRP2ZW+b4txEjZriYC8f3
        kv95YMTGbIsuWkJ93GrbvqoJ/CxO23r9WWRnZEm/1EZN9ZmlrYqzBTxnNRmP3Dhj
        cW8kzZwH+2/2zz2G7x1HxRWH95A=
        
        ------3C93156FC7B4EBF49FE9C7DB7F503087--
        

    Verify

    Assume the above output has been saved into sign.p7. Let's now verify the signature:

        from M2Crypto import SMIME, X509
        
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load the signer's cert.
        x509 = X509.load_cert('signer.pem')
        sk = X509.X509_Stack()
        sk.push(x509)
        s.set_x509_stack(sk)
        
        # Load the signer's CA cert. In this case, because the signer's
        # cert is self-signed, it is the signer's cert itself.
        st = X509.X509_Store()
        st.load_info('signer.pem')
        s.set_x509_store(st)
        
        # Load the data, verify it.
        p7, data = SMIME.smime_load_pkcs7('sign.p7')
        v = s.verify(p7, data)
        print v
        print data
        print data.read()
        

    Here's the output of the above program:

        a sign of our times
        <M2Crypto.BIO.BIO instance at 0x822012c>
        a sign of our times
        

    Suppose, instead of loading signer.pem above, we load recipient.pem. That is, we do a global substitution of recipient.pem for signer.pem in the above program. Here's the modified program's output:

        Traceback (most recent call last):
          File "./verify.py", line 22, in ?
            v = s.verify(p7)
          File "/usr/local/home/ngps/prog/m2/M2Crypto/SMIME.py", line 205, in verify
            raise SMIME_Error, Err.get_error()
        M2Crypto.SMIME.SMIME_Error: 312:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:pk7_smime.c:213:Verify error:self signed certificate
        

    As displayed, the error is generated by line 213 of OpenSSL's pk7_smime.c (as of OpenSSL 0.9.6); if you are a C programmer, you may wish to look up the C source to explore OpenSSL's S/MIME implementation and understand why the error message is worded thus.


    Encrypt

    We now demonstrate how to generate an S/MIME-encrypted message:

        from M2Crypto import BIO, Rand, SMIME, X509
        
        def makebuf(text):
            return BIO.MemoryBuffer(text)
        
        # Make a MemoryBuffer of the message.
        buf = makebuf('a sign of our times')
        
        # Seed the PRNG.
        Rand.load_file('randpool.dat', -1)
    
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load target cert to encrypt to.
        x509 = X509.load_cert('recipient.pem')
        sk = X509.X509_Stack()
        sk.push(x509)
        s.set_x509_stack(sk)
        
        # Set cipher: 3-key triple-DES in CBC mode.
        s.set_cipher(SMIME.Cipher('des_ede3_cbc'))
        
        # Encrypt the buffer.
        p7 = s.encrypt(buf)
            
        # Output p7 in mail-friendly format.
        out = BIO.MemoryBuffer()
        out.write('From: sender@example.dom\n')
        out.write('To: recipient@example.dom\n')
        out.write('Subject: M2Crypto S/MIME testing\n')
        s.write(out, p7)
        
        print out.read()
    
        # Save the PRNG's state.
        Rand.save_file('randpool.dat')
        

    Here's the output of the above program:

        From: sender@example.dom
        To: recipient@example.dom
        Subject: M2Crypto S/MIME testing
        MIME-Version: 1.0
        Content-Disposition: attachment; filename="smime.p7m"
        Content-Type: application/x-pkcs7-mime; name="smime.p7m"
        Content-Transfer-Encoding: base64
        
        MIIBVwYJKoZIhvcNAQcDoIIBSDCCAUQCAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE
        BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp
        ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ
        KoZIhvcNAQEBBQAEgYCBaXZ+qjpBEZwdP7gjfzfAtQitESyMwo3i+LBOw6sSDir6
        FlNDPCnkrTvqDX3Rt6X6vBtTCYOm+qiN7ujPkOU61cN7h8dvHR8YW9+0IPY80/W0
        lZ/HihSRgwTNd7LnxUUcPx8YV1id0dlmP0Hz+Lg+mHf6rqaR//JcYhX9vW4XvjA7
        BgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECMN+qya6ADywgBgHr9Jkhwn5Gsdu7BwX
        nIQfYTYcdL9I5Sk=
        

    Decrypt

    Assume the above output has been saved into encrypt.p7. Decrypt the message thusly:

        from M2Crypto import BIO, SMIME, X509
        
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load private key and cert.
        s.load_key('recipient_key.pem', 'recipient.pem')
        
        # Load the encrypted data.
        p7, data = SMIME.smime_load_pkcs7('encrypt.p7')
        
        # Decrypt p7.
        out = s.decrypt(p7)
            
        print out
        

    Here's the output:

        a sign of our times
        

    Sign and Encrypt

    Here's how to generate an S/MIME-signed/encrypted message:

        from M2Crypto import BIO, Rand, SMIME, X509
        
        def makebuf(text):
            return BIO.MemoryBuffer(text)
        
        # Make a MemoryBuffer of the message.
        buf = makebuf('a sign of our times')
        
        # Seed the PRNG.
        Rand.load_file('randpool.dat', -1)
        
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load signer's key and cert. Sign the buffer.
        s.load_key('signer_key.pem', 'signer.pem')
        p7 = s.sign(buf)
        
        # Load target cert to encrypt the signed message to.
        x509 = X509.load_cert('recipient.pem')
        sk = X509.X509_Stack()
        sk.push(x509)
        s.set_x509_stack(sk)
        
        # Set cipher: 3-key triple-DES in CBC mode.
        s.set_cipher(SMIME.Cipher('des_ede3_cbc'))
        
        # Create a temporary buffer.
        tmp = BIO.MemoryBuffer()
        
        # Write the signed message into the temporary buffer.
        s.write(tmp, p7)
        
        # Encrypt the temporary buffer.
        p7 = s.encrypt(tmp)
            
        # Output p7 in mail-friendly format.
        out = BIO.MemoryBuffer()
        out.write('From: sender@example.dom\n')
        out.write('To: recipient@example.dom\n')
        out.write('Subject: M2Crypto S/MIME testing\n')
        s.write(out, p7)
        
        print out.read()
        
        # Save the PRNG's state.
        Rand.save_file('randpool.dat')
        

    Here's the output of the above program:

        From: sender@example.dom
        To: recipient@example.dom
        Subject: M2Crypto S/MIME testing
        MIME-Version: 1.0
        Content-Disposition: attachment; filename="smime.p7m"
        Content-Type: application/x-pkcs7-mime; name="smime.p7m"
        Content-Transfer-Encoding: base64
        
        MIIIwwYJKoZIhvcNAQcDoIIItDCCCLACAQAxggEAMIH9AgEAMGYwYTELMAkGA1UE
        BhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRkwFwYDVQQDExBTL01JTUUgUmVjaXBp
        ZW50MSQwIgYJKoZIhvcNAQkBFhVyZWNpcGllbnRAZXhhbXBsZS5kb20CAQAwDQYJ
        KoZIhvcNAQEBBQAEgYBlZlGupFphwhsGtIAPvDExN61qisz3oem88xoXkUW0SzoR
        B9zJFFAuQTWzdNJgrKKYikhWjDojaAc/PFl1K5dYxRgtZLB36ULJD/v/yWmxnjz8
        TvtK+Wbal2P/MH2pZ4LVERXa/snTElhCawUlwtiFz/JvY5CiF/dcwd+AwFQq4jCC
        B6UGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIRF525UfwszaAggeA85RmX6AXQMxb
        eBDz/LJeCgc3RqU1UwIsbKMquIs1S46Ebbm5nP75izPnujOkJ2hv+LNzqOWADmOl
        +CnGEq1qxTyduIgUDA2nBgCL/gVyVy+/XC9dtImUUTxtxLgYtB0ujkBNsOaENOlM
        fv4SGM3jkR+K/xlYG6HHzZGbfYyNGj2Y7yMZ1rL1m8SnRNmkCysKGTrudeNf6wT9
        J6wO9DzLTioz3ZnVr3LjsSKIb4tIp4ugqNJaLuW7m3FtZ3MAgxN68hBbJs8TZ8tL
        V/0jwUqS+grcgZEb9ymfcedxahtDUfHjRkpDpsxZzVVGkSBNcbQu92oByQVnRQ8m
        wrYLp3/eawM5AvuV7HNpTT5ZR+1t8luishHN9899IMP2Vyg0Ub67FqFypYmM2cm2
        sjAI4KpfvT00XFNvgLuYwYEKs9syGTO7hiHNQKcF44F5LYv6nTFwmFQB11dAtY9V
        ull4D2CLDx9OvyNyKwdEZB5dyV0r/uKIdkhST60V2Q9KegpzgFpoZtSKM/HPYSVH
        1Bc9f3Q/GqZCvNZZCMx8UvRjQR8dRWDSmPJ0VXG1+wJ+fCmSPP3AuQ1/VsgPRqx2
        56VrpGPpGut40hV8xQFbWIZ2whwWLKPFAHj8B79ZtFUzUrU6Z2rNpvv8inHc/+S/
        b6GR5s8/gucRblvd7n3OFNX5UJmPmcw9zWbu/1Dr9DY8l0nAQh21y5FGSS8B1wdE
        oD2M3Lp7JbwjQbRtnDhImqul2S4yu+m+wDD1aR2K4k3GAI7KKgOBWT0+BDClcn8A
        4Ju6/YUbj33YlMPJgnGijLnolFy0hNW7TmWqR+8tSI3wO5eNKg4qwBnarqc3vgCV
        quVxINAXyGQCO9lzdw6hudk8/+BlweGdqhONaIWbK5z1L/SfQo6LC9MTsj7FJydq
        bc+kEbfZS8aSq7uc9axW6Ti0eAPJ8EVHtwhSBgZQRweKFBXs6HbbhMIdc4N0M7Oq
        UiFXaF6s4n2uihVP6TqXtHEjTpZoC7pC+HCYiuKXUJtaqtXBOh+y3KLvHk09YL6D
        XmTDg+UTiFsh4jKKm/BhdelbR5JbpJcj5AId76Mfr8+F/1g9ePOvsWHpQr/oIQTo
        xEkaxCmzEgP0b6caMWfMUQrbVGxBBNcqKc/ir9fGGOPHATzzq/xLcQYvK1tZhd/D
        ah/gpMPndsyvVCEuFPluWyDiM0VkwHgC2/3pJIYFHaxK64IutmPsy393rHMEB4kN
        AHau6kWK+yL9qEVH1pP2zvswQ12P7gjt3T/G3bGsmvlXkEfztfjkXo6XnjcBNf5y
        G+974AKLcjnk1gzIgarz+lAMY57Gkw4oNDMrTqVQ2OJQlvOSbllPXzH+aAiavB8W
        ZPECLLwHxD4B1AuaiAArgKl935u/TOB+yQOR8JgGsUzROyJqHJ/SC51HkebgCkL1
        aggtjgPlIBEXLZAlhpWLZ9lAQyrQpvCVJYwaOvfMmvRav4NAFNoZ2/Q7S4Tn1z+U
        XX+f+GD58P4MPMhU5IKnz4yH4nlHnAiTEvcs85TZUAXze9g/uBOwZITeGtyLi52S
        aETIr4v7SgXMepX7ThQ1Pv/jddsK/u4j2F34u0XktwCP+UrbfkE2mocdXvdzxbmd
        tZSznK2qwgVSsPOs9MhUaepbnjmNBFFBrULhrUtSglM/VX/rWNiyh0aw4XYyHhIt
        9ZNlfEjKjJ67VEMBxBJ/ieUCouRGCxPYD1j65VT7oB3ZiyPu2F2nlUIcYNqPg1Sd
        QBCrdaOXdJ0uLwyTAUeVE+wMbgscLvWsfZcCCJHAvw9NHFMUcnrdWxAYMVETNUOn
        uryVAK7VfOldaz6z3NOSOi6nonNeHpR/sipBa4ik5xCRLT9e0S2QJgRvO9GyfAqz
        3DIzHtxIGePFzTiUYUTxS3i2gnMX2PEe3ChTLlYWD3jNeAKz0iOzpDphIF2xHLLQ
        1tCAqBmq/vUzALyDFFdFuTIqQZys4z/u4Dmyq9uXs421eN3v2hkVHvDy8uT2Ot29
        lg4Q5YezR1EjaW//9guL1BXbcKrTEdtxeNqtem7SpZOMTSwD2lhB8z65GrX90Cyt
        EMmaRSGYEdf5h1afL1SmKOMskbqxe1D2jG/vsXC7XX7xO/ioy0BdiJcYN1JiMOHJ
        EOzFol5I20YkiV6j+cenfQFwc/NkaSxEkR8AUHJSbvUmRQRl6r0nnsFpZdR1w7pv
        wkaT+eOpZynO4mY/ZtF6MpXJsixi6L4ZYXEbS6yHf+XGFfB0okILylmwv2bf6+Mq
        nqXlmGj3Jwq7X9/+2BDqvfpFFX5lSmItKZAobLdssjFR6roJxOqRsGia2aZ+0+U5
        VhgdITtnElgtHBaeZU5rHDswgdeLVBP+rGWnKxpJ+pLtNNi25sPYRcWFL6Erd25u
        eXiY8GEIr+u7rqBWpc9HR34sAPRs3ubbCUleT748keCbx247ImBtiDctZxcc1O86
        +0QjHP6HUT7FSo/FmT7a120S3Gd2jixGh06l/9ij5Z6mJa7Rm7TTbSjup/XISnOT
        MKWcbI1nfVOhCv3xDq2eLae+s0oVoc041ceRazqFM2TL/Z6UXRME
        

    Decrypt and Verify

    Suppose the above output has been saved into se.p7. The following demonstrates how to decrypt and verify it:

        from M2Crypto import BIO, SMIME, X509
        
        # Instantiate an SMIME object.
        s = SMIME.SMIME()
        
        # Load private key and cert.
        s.load_key('recipient_key.pem', 'recipient.pem')
        
        # Load the signed/encrypted data.
        p7, data = SMIME.smime_load_pkcs7('se.p7')
        
        # After the above step, 'data' == None.  
        # Decrypt p7. 'out' now contains a PKCS #7 signed blob.
        out = s.decrypt(p7)
        
        # Load the signer's cert.
        x509 = X509.load_cert('signer.pem')
        sk = X509.X509_Stack()
        sk.push(x509)
        s.set_x509_stack(sk)
        
        # Load the signer's CA cert. In this case, because the signer's
        # cert is self-signed, it is the signer's cert itself.
        st = X509.X509_Store()
        st.load_info('signer.pem')
        s.set_x509_store(st)
        
        # Recall 'out' contains a PKCS #7 blob.
        # Transform 'out'; verify the resulting PKCS #7 blob.
        p7_bio = BIO.MemoryBuffer(out)
        p7, data = SMIME.smime_load_pkcs7_bio(p7_bio)
        v = s.verify(p7)
        
        print v
        

    The output is as follows:

        a sign of our times
        

    Sending S/MIME messages via SMTP

    In the above examples, we've assumed that our S/MIME messages are sent and received automagically. The following is a Python function that generates S/MIME-signed/encrypted messages and sends them via SMTP:

        from M2Crypto import BIO, SMIME, X509
        import smtplib, string, sys
        
        def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'):
        
            msg_bio = BIO.MemoryBuffer(msg)
            sign = from_key
            encrypt = to_certs
        
            s = SMIME.SMIME()
            if sign:
                s.load_key(from_key, from_cert)
                if encrypt:
                    p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT)
                else:
                    p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT|SMIME.PKCS7_DETACHED)
                msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it.
        
            if encrypt:
                sk = X509.X509_Stack()
                for x in to_certs:
                    sk.push(X509.load_cert(x))
                s.set_x509_stack(sk)
                s.set_cipher(SMIME.Cipher('des_ede3_cbc'))
                tmp_bio = BIO.MemoryBuffer()
                if sign:
                    s.write(tmp_bio, p7)
                else:
                    tmp_bio.write(msg)
                p7 = s.encrypt(tmp_bio)
        
            out = BIO.MemoryBuffer()
            out.write('From: %s\r\n' % from_addr)
            out.write('To: %s\r\n' % string.join(to_addrs, ", "))
            out.write('Subject: %s\r\n' % subject) 
            if encrypt:
                s.write(out, p7)
            else:
                if sign:
                    s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT)
                else:
                    out.write('\r\n')
                    out.write(msg)
            out.close()
        
            smtp = smtplib.SMTP()
            smtp.connect(smtpd)
            smtp.sendmail(from_addr, to_addrs, out.read())
            smtp.quit()
        

    This function sends plain, S/MIME-signed, S/MIME-encrypted, and S/MIME-signed/encrypted messages, depending on the parameters from_key and to_certs. The function's output interoperates with Netscape Messenger.


    Verifying origin of S/MIME messages

    In our examples above that decrypt or verify messages, we skipped a step: verifying that the from address of the message matches the email address attribute in the sender's certificate.

    The premise of current X.509 certification practice is that the CA is supposed to verify your identity, and to issue a certificate with email address that matches your actual mail address. (Verisign's March 2001 failure in identity verification resulting in Microsoft certificates being issued to spoofers notwithstanding.)

    If you run your own CA, your certification practice is up to you, of course, and it would probably be part of your security policy.

    Whether your S/MIME messaging application needs to verify the from addresses of S/MIME messages depends on your security policy and your system's threat model, as always.


    Interoperating with Netscape Messenger

    Suppose S/MIME Recipient uses Netscape Messenger. To enable Messenger to handle S/MIME messages from S/MIME Sender, S/MIME Recipient needs to configure Messenger with his private key and certificate, as well as S/MIME Sender's certificate.

    Note: Configuring Messenger's POP or IMAP settings so that it retrieves mail correctly is beyond the scope of this HOWTO.

    The following steps demonstrate how to import S/MIME Recipient's private key and certificate for Messenger:

    1. Transform S/MIME Recipient's private key and certificate into PKCS #12 format.

          openssl pkcs12 -export -in recipient.pem -inkey recipient_key.pem -name "S/MIME Recipient" -out recipient.p12
          
          Enter Export Password:<enter>
          Verifying password - Enter Export Password:<enter>
          
    2. Start Messenger.

    3. Click on the (open) "lock" icon at the bottom left corner of Messenger's window. This brings up the "Security Info" dialog box.

    4. Click on "Yours" under "Certificates".

    5. Select "Import a certificate", then pick recipient.p12 from the ensuing file selection dialog box.

    Next, you need to import signer.pem as a CA certificate, so that Messenger will mark messages signed by S/MIME Sender as "trusted":

    1. Create a DER encoding of signer.pem.

          openssl x509 -inform pem -outform der -in signer.pem -out signer.der
          
          
    2. Install signer.der into Messenger as MIME type application/x-x509-ca-cert. You do this by downloading signer.der via Navigator from a HTTP or HTTPS server, with the correct MIME type mapping. (You may use demo/ssl/https_srv.py, bundled with M2Crypto, for this purpose.) Follow the series of dialog boxes to accept signer.der as a CA for certifying email users.

    S/MIME Recipient is now able to decrypt and read S/MIME Sender's messages with Messenger. Messenger will indicate that S/MIME Sender's messages are signed, encrypted, or encrypted and signed, as the case may be, via the "stamp" icon on the message window's top right corner.

    Clicking on the "stamp" icon brings you to the Security Info dialog box. Messenger informs you that the message is, say, encrypted with 168-bit DES-EDE3-CBC and that it is digitally signed by the private key corresponding to the public key contained in the certificate signer.pem.


    Interoperating with Microsoft Outlook

    I do not know how to do this, as I do not use Outlook. (Nor do I use Netscape Messenger, actually. I use Mutt, top dog of MUAs. ;-) Information on how to configure Outlook with keys and certificates so that it handles S/MIME mail is gratefully accepted.


    ZSmime

    ZSmime is a Zope product that enables Zope to generate S/MIME-signed/encrypted messages. ZSmime demonstrates how to invoke M2Crypto in a web application server extension.

    ZSmime has its own HOWTO explaining its usage. (That HOWTO has some overlap in content with this document.)


    Resources


    $Id:howto.smime.html 583 2007-10-01 19:23:12Z heikki $

    M2Crypto-0.22.6rc4/doc/howto.ssl.html0000664000175000017500000001455012212052026017505 0ustar matejmatej00000000000000HOWTO: Programming SSL in Python with M2Crypto

    HOWTO: Programming SSL in Python with M2Crypto

    Ng Pheng Siong (ngps@netmemetic.com) and Heikki Toivonen (heikki@osafoundation.org)

    Introduction

    M2Crypto is a Python interface to OpenSSL. It makes available to the Python programmer SSL functionality to implement clients and servers, S/MIME v2, RSA, DSA, DH, symmetric ciphers, message digests and HMACs.

    This document demonstrates programming HTTPS with M2Crypto.

    A bit of history

    M2Crypto was created during the time of Python 1.5, which features a module httplib providing client-side HTTP functionality. M2Crypto sports a httpslib based on httplib.

    Beginning with version 2.0, Python's socket module provided (rudimentary) SSL support. Also in the same version, httplib was enhanced with class HTTPConnection, which is more sophisticated than the old class HTTP, and HTTPSConnection, which does HTTPS.

    Subsequently, M2Crypto.httpslib grew a compatible (but not identical) class HTTPSConnection.

    The primary interface difference between the two HTTPSConnection classes is that M2Crypto's version accepts an M2Crypto.SSL.Context instance as a parameter, whereas Python 2.x's SSL support does not permit Pythonic control of the SSL context.

    Within the implementations, Python's HTTPSConnection employs a FakeSocket object, which collects all input from the SSL connection before returning it to the application as a StringIO buffer, whereas M2Crypto's HTTPSConnection uses a buffering M2Crypto.BIO.IOBuffer object that works over the underlying M2Crypto.SSL.Connection directly.

    Since then M2Crypto has gained a Twisted wrapper that allows securing Twisted SSL connections with M2Crypto.

    Secure SSL

    It is recommended that you read the book Network Security with OpenSSL by John Viega, Matt Messier and Pravir Chandra, ISBN 059600270X.

    Using M2Crypto does not automatically make an SSL connection secure. There are various steps that need to be made before we can make that claim. Let's see how a simple client can establish a secure connection:

    ctx = SSL.Context()
    ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9)
    if ctx.load_verify_locations('ca.pem') != 1: raise Exception('No CA certs')
    s = SSL.Connection(ctx)
    s.connect(server_address)
    # Normal protocol (for example HTTP) commands follow
    

    The first line creates an SSL context. The defaults allow any SSL version (except SSL version 2 which has known weaknesses) and sets the allowed ciphers to secure ones.

    The second line tells M2Crypto to perform certificate validation. The flags shown above are typical for clients, and requires the server to send a certificate. The depth parameter tells how long certificate chains are allowed - 9 is pretty common default, although probably too long in practice.

    The third line loads the allowed root (certificate authority or CA) certificates. Most Linux distributions come with CA certificates in suitable format. You could also download the certdata.txt file from the NSS project and convert it with the little M2Crypto utility script demo/x509/certdata2pem.py.

    The fourth line creates an SSL connection object with the secure context.

    The fifth line connects to the server. During this time we perform the last security step: just after connection, but before exchanging any data, we compare the commonName (or subjectAltName DNS field) field in the certificate the server returned to the server address we tried to connect to. This happens automatically with SSL.Connection and the Twisted wrapper class, and anything that uses those. In all other cases you must do the check manually. It is recommended you call the SSL.Checker to do the actual check.

    SSL servers are different in that they typically do not require the client to send a certificate, so there is usually no certificate checking. Also, it is typically useless to perform host name checking.

    Code Samples

    The best samples of how to use the various SSL objects are in the tests directory, and the test_ssl.py file specifically. There are additional samples in the demo directory, but they are not quaranteed to be up to date.

    NOTE: The tests and demos may not be secure as is. Use the information above on how to make them secure.

    ssldump

    ssldump "is an SSLv3/TLS network protocol analyser. It identifies TCP connections on the chosen network interface and attempts to interpret them as SSLv3/TLS traffic. When it identifies SSLv3/TLS traffic, it decodes the records and displays them in a textual form to stdout. If provided with the appropriate keying material, it will also decrypt the connections and display the application data traffic.

    If linked with OpenSSL, ssldump can display certificates in decoded form and decrypt traffic (provided that it has the appropriate keying material)."

    ssldump is written by Eric Rescorla.

    M2Crypto-0.22.6rc4/tests/0000775000175000017500000000000012613362233015260 5ustar matejmatej00000000000000M2Crypto-0.22.6rc4/tests/README0000664000175000017500000000276512605255257016162 0ustar matejmatej00000000000000This directory contains unit tests for M2Crypto. To run all tests, make sure you have installed setuptools and then issue the following command from the M2Crypto root directory: python setup.py test To run tests in a single file, for example test_ssl.py, do this: python setup.py test --test-suite=tests.test_ssl Look also in the demo directory for other samples. To create new test certificates: mkdir certs cd certs Making the CA. You may want to use a locally edited openssl.cnf to make sure that X509v3 Basic Constraints CA:TRUE gets set (by default it may be false). By default duration may only be just one year; should set this for at least 3 years. CA.sh -newca cp demoCA/cacert.pem ../ca.pem Making the server certificate and private key. make sure commonName field is localhost. CA.sh -newreq CA.sh -signreq cp newcert.pem ../server.pem openssl rsa >../server.pem Making the x509 certificate and key. CA.sh -newreq CA.sh -signreq cp newcert.pem ../x509.pem openssl rsa >../x509.pem openssl x509 -in ../x509.pem -out ../x509.der -outform DER Making the signer certificate. Make sure the email address is signer@example.com. CA.sh -newreq CA.sh -signreq cp newcert.pem ../signer.pem openssl rsa ../signer_key.pem Making the recipient certificate. Make sure the email address is recipient@example.com. CA.sh -newreq CA.sh -signreq cp newcert.pem ../recipient.pem openssl rsa ../recipient_key.pem Finally run the tests and edit for new values. M2Crypto-0.22.6rc4/tests/__init__.py0000664000175000017500000000000012605232411017352 0ustar matejmatej00000000000000M2Crypto-0.22.6rc4/tests/alltests.py0000664000175000017500000000533312607370517017500 0ustar matejmatej00000000000000#!/usr/bin/env python def suite(): from M2Crypto import m2 import os import unittest def my_import(name): # See http://docs.python.org/lib/built-in-funcs.html#l2h-6 components = name.split('.') try: # python setup.py test mod = __import__(name) for comp in components[1:]: mod = getattr(mod, comp) except ImportError: # python tests/alltests.py mod = __import__(components[1]) return mod modules_to_test = [ 'tests.test_asn1', 'tests.test_bio', 'tests.test_bio_membuf', 'tests.test_bio_file', 'tests.test_bio_iobuf', 'tests.test_bio_ssl', 'tests.test_bn', 'tests.test_authcookie', 'tests.test_dh', 'tests.test_dsa', 'tests.test_engine', 'tests.test_evp', 'tests.test_obj', 'tests.test_pgp', 'tests.test_rand', 'tests.test_rc4', 'tests.test_rsa', 'tests.test_smime', 'tests.test_ssl_offline', 'tests.test_threading', 'tests.test_x509'] if os.name == 'posix': modules_to_test.append('tests.test_ssl') elif os.name == 'nt': modules_to_test.append('tests.test_ssl_win') if m2.OPENSSL_VERSION_NUMBER >= 0x90800F and m2.OPENSSL_NO_EC == 0: modules_to_test.append('tests.test_ecdh') modules_to_test.append('tests.test_ecdsa') modules_to_test.append('tests.test_ec_curves') alltests = unittest.TestSuite() for module in map(my_import, modules_to_test): alltests.addTest(module.suite()) return alltests def dump_garbage(): import gc print '\nGarbage:' gc.collect() if len(gc.garbage): print '\nLeaked objects:' for x in gc.garbage: s = str(x) if len(s) > 77: s = s[:73]+'...' print type(x), '\n ', s print 'There were %d leaks.' % len(gc.garbage) else: print 'Python garbage collector did not detect any leaks.' print 'However, it is still possible there are leaks in the C code.' def runall(report_leaks=0): report_leaks = report_leaks if report_leaks: import gc gc.enable() gc.set_debug(gc.DEBUG_LEAK & ~gc.DEBUG_SAVEALL) import os, unittest from M2Crypto import Rand try: Rand.load_file('tests/randpool.dat', -1) unittest.TextTestRunner(verbosity=2).run(suite()) Rand.save_file('tests/randpool.dat') finally: if os.name == 'posix': from test_ssl import zap_servers zap_servers() if report_leaks: dump_garbage() if __name__ == '__main__': runall(0) M2Crypto-0.22.6rc4/tests/ca.pem0000664000175000017500000000554012611255457016361 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: b4:7e:b2:de:87:00:03:0b Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Validity Not Before: Nov 21 15:31:30 2012 GMT Not After : Nov 21 15:31:30 2015 GMT Subject: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00:d2:2f:57:58:be:05:6d:45:14:d0:70:90:56:10: 80:f6:e3:e6:8a:ff:1e:0b:58:fa:a1:e6:95:a1:23: 8d:01:c6:48:85:99:ab:f9:1b:e0:9a:15:6a:d1:50: 73:fb:8f:7c:d2:73:4e:4a:c0:88:f9:54:f9:86:d9: 01:86:4e:02:68:bc:d0:1c:8d:d2:2e:ce:7e:54:ac: 45:a5:b7:39:c6:e9:f4:e0:70:2c:57:e6:21:24:f6: 52:f8:fa:0b:b3:63:53:ea:eb:11:ca:ef:90:32:9f: 15:08:6b:2d:0e:3d:61:69:22:f2:0f:dc:08:65:45: 34:a2:29:8e:66:5e:45:95:91 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 X509v3 Authority Key Identifier: keyid:80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha1WithRSAEncryption b0:37:88:ab:56:c5:19:e7:1b:d2:d3:c0:00:98:ff:f0:0a:35: 89:ff:a0:a8:14:bd:fc:84:b6:ee:6b:05:92:20:87:58:38:69: b2:16:b8:89:f3:4f:3c:9d:0f:da:b6:ea:35:9f:cf:e9:4f:05: 19:8b:6a:06:68:51:96:1c:0f:60:23:80:19:ff:cd:3e:2b:4b: 0c:1a:ff:bd:f6:0d:6b:11:25:0f:ba:87:2c:46:47:c0:32:e8: 8a:14:4c:30:26:35:2b:58:9c:6b:c6:0e:d1:e3:c8:6a:b0:c0: e0:82:98:77:07:2e:67:ba:0c:e5:a5:04:0d:81:ca:54:92:b5: 27:fa -----BEGIN CERTIFICATE----- MIICbDCCAdWgAwIBAgIJALR+st6HAAMLMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0bzEY MBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4XDTEyMTEyMTE1MzEzMFoXDTE1MTEy MTE1MzEzMFowTzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAP BgNVBAoMCE0yQ3J5cHRvMRgwFgYDVQQDDA9IZWlra2kgVG9pdm9uZW4wgZ8wDQYJ KoZIhvcNAQEBBQADgY0AMIGJAoGBANIvV1i+BW1FFNBwkFYQgPbj5or/HgtY+qHm laEjjQHGSIWZq/kb4JoVatFQc/uPfNJzTkrAiPlU+YbZAYZOAmi80ByN0i7OflSs RaW3Ocbp9OBwLFfmIST2Uvj6C7NjU+rrEcrvkDKfFQhrLQ49YWki8g/cCGVFNKIp jmZeRZWRAgMBAAGjUDBOMB0GA1UdDgQWBBSA2WoeFf6LYVFiYE2zzJVEeC2J5jAf BgNVHSMEGDAWgBSA2WoeFf6LYVFiYE2zzJVEeC2J5jAMBgNVHRMEBTADAQH/MA0G CSqGSIb3DQEBBQUAA4GBALA3iKtWxRnnG9LTwACY//AKNYn/oKgUvfyEtu5rBZIg h1g4abIWuInzTzydD9q26jWfz+lPBRmLagZoUZYcD2AjgBn/zT4rSwwa/732DWsR JQ+6hyxGR8Ay6IoUTDAmNStYnGvGDtHjyGqwwOCCmHcHLme6DOWlBA2BylSStSf6 -----END CERTIFICATE----- M2Crypto-0.22.6rc4/tests/der_encoded_seq.b640000664000175000017500000000243012605232411020672 0ustar matejmatej00000000000000MIIDwTCCA70wggKloAMCAQICAg5QMA0GCSqGSIb3DQEBBQUAMGkxEzARBgoJkiaJk/IsZAEZFgNv cmcxGDAWBgoJkiaJk/IsZAEZFghET0VHcmlkczEgMB4GA1UECxMXQ2VydGlmaWNhdGUgQXV0aG9y aXRpZXMxFjAUBgNVBAMTDURPRUdyaWRzIENBIDEwHhcNMDUwMTEyMDA1MTAyWhcNMDYwMTEyMDA1 MTAyWjBhMRMwEQYKCZImiZPyLGQBGRMDb3JnMRgwFgYKCZImiZPyLGQBGRMIZG9lZ3JpZHMxETAP BgNVBAsTCFNlcnZpY2VzMR0wGwYDVQQDExRob3N0L2Jvc3Nob2cubGJsLmdvdjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAJ+M2ICaiIkr1YcPzXlOSA/DTzduZPq+ALwbmU+nHatL8wXr 8SmwMq/aIG9egGnJzsTlofkSA5D7HAX3nLKkU0A+k0Eig2QzZ5iPjrtAr2m9/b/EsF2I58yOcEDT EZuHQWCg19YE29n3UwqXB6pgpuMcFfFqLz6NydN9i0T7Md8OGwYpNzK6TsOCtyF+nin5mZleDyXF BtkXeIDHmq8sYmsELv1fbAwYzpAZqvz3k0umXSMwnyq+z6WpawybNuLrhRzqMrMZYzq0Db/hS4xr TeXOFuRQ/IcgWt0rLmOIRYKrVfLujFcAQnaPDW8llK2kgi6OrPlTo8e8JVEcz5d7bKUCAwEAAaN3 MHUwEQYJYIZIAYb4QgEBBAQDAgbAMA4GA1UdDwEB/wQEAwIE8DAfBgNVHSMEGDAWgBTKGR0Sjm6k OF1C1DEOCNvZjRcNXTAvBgNVHREEKDAmgg9ib3NzaG9nLmxibC5nb3aBE01LUm9kcmlndWV6QGxi bC5nb3YwDQYJKoZIhvcNAQEFBQADggEBAKZkj+amwHCSdcMC05NBv1Vck46tGEsAEf9WiNvf3B1N O+B0d+egcbXME+LgrxWvOIf4k2DKvORt/oz5BavEbmD1+/NUseBEA01bzjXXgmWwW48CK5cb6Qam wq1uMa/asUgyLfpVkgA9ThwHIr2/g4HEIqUZLaqotLS5+EzZKhOuWh9OJh+AR6WCxOjTQw1xCJd0 T/sSlHdtlH47xBkDL5DKe0pn9CgGY+ihehcRpzXMB8tKgxzsE8NuB49IUrVC+wIgzEXEeaSPFenL XdWxAKaFWRXyPHrsrtsenxnRkM6y8qxWN6UV5UqpvdE/cy+5QORbzWtfVPYqtNVZoO+N3rc=M2Crypto-0.22.6rc4/tests/dhparams.pem0000664000175000017500000000036512605232411017561 0ustar matejmatej00000000000000-----BEGIN DH PARAMETERS----- MIGHAoGBAIgAcu3gpJeO8aS6N+sTMa655BMzBNlK66q62VH9RqmHwFJSjjCs3ZsF aVsTkO3Mt0gULn1drXsK6Lc6pA8s0eQN8ggyEPVr6ND0jN2jr2qc1XlqD7jxzdxe igB66pLvrWvAulrGxg4QMsQjqcpwZZ2ndRpYSmErIi4M1r19nTgjAgEC -----END DH PARAMETERS----- M2Crypto-0.22.6rc4/tests/dsa.param.pem0000664000175000017500000000070712605232411017630 0ustar matejmatej00000000000000-----BEGIN DSA PARAMETERS----- MIIBHgKBgQDqYu3smvs8KHBx4XX8otDHQUdtCyWKIRC52eQUSYeWejvdaqm11rIq QMFBJDnvicM4avyOIU2d/ZOfLzN7aXFw3Ep67amsLpj82N+n4lASUJwKdOJyzyLG 9IS41RRek8B3lRAs/zqk1U6P5EaE/uIG4+avYmkSDpB4kmnRGhTYeQIVALKQpdTy uat9aoq9mFm8dVA2VxAhAoGAausAkdN4Hj6S5nfPMjJTnwV4u7hVY6b6eAZTJmxs ykr3XlKqM3PS0hKhjatp7f+mRNFxYvGrWPLAwnPOIp/iNn7lM7U41ceUj1O3KrD/ Cg4LQ/bADvY48eytdjMLZDpL3Jwootfs4i8WIb0RnIxg8nClhkY2K2/+4voft+Xi DlA= -----END DSA PARAMETERS----- M2Crypto-0.22.6rc4/tests/dsa.priv.pem0000664000175000017500000000077512605232411017515 0ustar matejmatej00000000000000-----BEGIN PRIVATE KEY----- MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOpi7eya+zwocHHhdfyi0MdBR20L JYohELnZ5BRJh5Z6O91qqbXWsipAwUEkOe+Jwzhq/I4hTZ39k58vM3tpcXDcSnrt qawumPzY36fiUBJQnAp04nLPIsb0hLjVFF6TwHeVECz/OqTVTo/kRoT+4gbj5q9i aRIOkHiSadEaFNh5AhUAspCl1PK5q31qir2YWbx1UDZXECECgYBq6wCR03gePpLm d88yMlOfBXi7uFVjpvp4BlMmbGzKSvdeUqozc9LSEqGNq2nt/6ZE0XFi8atY8sDC c84in+I2fuUztTjVx5SPU7cqsP8KDgtD9sAO9jjx7K12MwtkOkvcnCii1+ziLxYh vRGcjGDycKWGRjYrb/7i+h+35eIOUAQWAhQ/vK8oLKHdEu7W77fbZ3+jQvvt6Q== -----END PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/dsa.pub.pem0000664000175000017500000000121612605232411017312 0ustar matejmatej00000000000000-----BEGIN PUBLIC KEY----- MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOpi7eya+zwocHHhdfyi0MdBR20LJYoh ELnZ5BRJh5Z6O91qqbXWsipAwUEkOe+Jwzhq/I4hTZ39k58vM3tpcXDcSnrtqawu mPzY36fiUBJQnAp04nLPIsb0hLjVFF6TwHeVECz/OqTVTo/kRoT+4gbj5q9iaRIO kHiSadEaFNh5AhUAspCl1PK5q31qir2YWbx1UDZXECECgYBq6wCR03gePpLmd88y MlOfBXi7uFVjpvp4BlMmbGzKSvdeUqozc9LSEqGNq2nt/6ZE0XFi8atY8sDCc84i n+I2fuUztTjVx5SPU7cqsP8KDgtD9sAO9jjx7K12MwtkOkvcnCii1+ziLxYhvRGc jGDycKWGRjYrb/7i+h+35eIOUAOBhQACgYEAmYO4Qss7pYq3vAEj5qj35A1gsOeC rGxvu8w9Dj8jACuz0IHOTq+vFbnB6p30rdloMU7Ci4NHPWqOVmWCFcXxkFgJMJld sBbkdbGnhPI80sWJGouUYofHFG4pK0QoMeDZKgg7OgwH8EnmQM+W9KDZYJRSuU4+ 6F6hQkmkwAKAXkU= -----END PUBLIC KEY----- M2Crypto-0.22.6rc4/tests/ec.priv.pem0000664000175000017500000000032312613361242017326 0ustar matejmatej00000000000000-----BEGIN EC PRIVATE KEY----- MG0CAQEEHXXhxMbflWHSfCjfxsqHTsIR+BVbREI6JFYGaUs0oAcGBSuBBAAaoUAD PgAEAdJXSN/xnRiDqc4wSiYbWB7LGabs71Y9zzIE1ZbzAcvb7uxtoyUxrmRQC8xD EO2qZX16mtpmgoNz3EeT -----END EC PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/ec.pub.pem0000664000175000017500000000024612613361242017140 0ustar matejmatej00000000000000-----BEGIN PUBLIC KEY----- MFIwEAYHKoZIzj0CAQYFK4EEABoDPgAEAdJXSN/xnRiDqc4wSiYbWB7LGabs71Y9 zzIE1ZbzAcvb7uxtoyUxrmRQC8xDEO2qZX16mtpmgoNz3EeT -----END PUBLIC KEY----- M2Crypto-0.22.6rc4/tests/fips.py0000664000175000017500000000024412607370517016602 0ustar matejmatej00000000000000try: f = open('/proc/sys/crypto/fips_enabled') try: fips_mode = int(f.read()) finally: f.close() except Exception, e: fips_mode = 0 M2Crypto-0.22.6rc4/tests/long_serial_cert.pem0000664000175000017500000000174112605232411021274 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIICsDCCAhmgAwIBAgIJAPR7mEmILgX6MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQwHhcNMDkwNjE5MTkzNjIyWhcNMDkwNzE5MTkzNjIyWjBF MQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB gQDRb/jlXLidgXQGsOLoFbh4JAvC+BgufR7jn93KPybI0oo8VXFUqr2eFuLDcPiE gpWIMrLwq9f0US/M/yXQdsH08L2xe+aaiNl+j+o4VsPhXfnvFvAtFRs+JqCR3VfI vVePwov31+/28PmF1kOxr9SmSzvSPnN3SqSC0GDAmhWNYwIDAQABo4GnMIGkMB0G A1UdDgQWBBR3SQBG5X/vH18obsb2aaBxhU/+HjB1BgNVHSMEbjBsgBR3SQBG5X/v H18obsb2aaBxhU/+HqFJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAPR7mEmI LgX6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAoyvUPgjkwPAgiqiU 4cD1tZdcxIzkk22U02cTjJtAPnIYwqwwDpFltApvRbp8MNiPqXbBt0tchj/Ovu4D JiDTMaizVOZ+XmiC68uNTZ4nvEwHvVdKmudNVTZDdFr/a6BErAeTknlMCihN3v6M POx8a1iz8Y/wJ8YA74vMPORKlKc= -----END CERTIFICATE----- M2Crypto-0.22.6rc4/tests/pubring.pgp0000664000175000017500000000210012605255257017437 0ustar matejmatej0000000000000028iPH6Nړ[21Ka=b)57X0f9QV!SuEůUN3S5GUv@#dF_H9D~[NY76hoCNV$XFdaft 223a5- d 7x yUTtԔ;JDAMN}> +7VGP=?2WM[) -h{ `5DʤDf:9 fa9>\@# Billy boyL2W salYcomCXyp$gKc,Mկ1v RtN%02zX(͂S٫usilly test this is=2NF0;1H*ۮ!e=zW6Uu+X*\h!Gary Howland L2 sRP M9'B{r<-NF 7Vs+j5S`|W[name=2xѡ^V?B|f_͂ `GOL2 ۽riR 3v# O6H 6[8f|2.'Qsilly test this isL2 _r_W,I$+bI\uCz~h5y&Qb !c8+silly test this is2t펝jwgkf7 4f-KvMķ$V3}q#Rl m٧/=}]N~kEȐ;m/ŕx+]_]@8͑CIڬDWK2qB}@ឫ@x|Iq"Nh{FpDJu /jv—??F sGBc+i w ˁe5Rlo <,A7~)j';}zgԎdE]ڟ5),@Dh04+st~ ĹCgC3rXZ]̂~fE.+*8(65j'P7$/=՜h0)ΈWo\!1 B_hMⵁ1>M+AſԁQ2 &0PBnVF|rbWfأM5T՜IÇb{+r7Hun(۰dl?(H=*Svش`(񀻲O:L_0ɒǿ O*B恳sFΝŐρ MCĝz =PbjĞ⻺`XhA'kE>(lO¹"05QIO H#VW\@PDx9{Qc7YX1PW,s eDJUjej'0cWYž8{no |#[֡ay.;g_;}6EvL~'ϩfӨ qd!Ή{ L#{J4@U`>hmҙM^rՇtNM2Crypto-0.22.6rc4/tests/recipient.pem0000664000175000017500000000606112611255457017757 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: b4:7e:b2:de:87:00:03:0f Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Validity Not Before: Nov 21 15:39:34 2012 GMT Not After : Jan 8 15:39:34 2023 GMT Subject: C=US, ST=California, O=M2Crypto, CN=Recipient/emailAddress=recipient@example.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00:ac:b6:2e:f0:34:34:7d:d4:e6:63:79:60:53:b9: fe:91:a5:bf:49:ec:99:4c:33:2f:85:96:55:e8:09: dc:18:47:1a:72:49:04:a2:e8:78:73:57:c7:bb:e9: c7:aa:c5:07:84:14:b6:01:1c:e3:8a:fd:f3:19:01: 11:9d:48:bc:24:8a:0f:c6:40:ed:d7:30:b1:92:ab: c2:61:8c:5d:ea:08:c6:c4:d6:a5:22:00:d9:aa:da: 57:5d:cc:2f:1a:35:1b:31:de:dc:c7:3b:83:91:38: d9:07:e1:c7:a7:54:bd:94:95:10:c6:2d:dc:00:e1: 28:99:b5:3b:28:95:aa:4e:d5 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: CD:26:EB:42:79:6D:04:7F:95:23:46:1E:03:C9:40:2D:D2:00:AE:71 X509v3 Authority Key Identifier: keyid:80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 Signature Algorithm: sha1WithRSAEncryption a9:5e:b2:4c:24:15:dd:49:d1:4d:e3:dd:e3:da:6b:23:99:45: 2d:a1:84:f2:9b:6e:48:3c:e9:ce:f8:7f:f3:1f:d3:85:99:94: 7e:19:8c:ca:be:3a:ca:97:b9:de:c8:4f:08:28:fc:7f:24:37: 95:e1:d5:60:97:07:2b:be:62:f4:02:1d:27:8f:9e:0d:36:1a: d5:45:6f:27:c3:34:21:13:1b:28:93:9d:cb:a6:30:0d:8f:4a: 5f:4c:4a:97:7b:fe:ed:ce:18:84:5a:ec:4f:f8:84:2e:cb:72: 28:90:cb:e3:5a:f4:83:16:bd:a8:ef:f0:f5:12:6c:26:3e:af: c7:a8 -----BEGIN CERTIFICATE----- MIICtzCCAiCgAwIBAgIJALR+st6HAAMPMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0bzEY MBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4XDTEyMTEyMTE1MzkzNFoXDTIzMDEw ODE1MzkzNFowbzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAP BgNVBAoMCE0yQ3J5cHRvMRIwEAYDVQQDDAlSZWNpcGllbnQxJDAiBgkqhkiG9w0B CQEWFXJlY2lwaWVudEBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw gYkCgYEArLYu8DQ0fdTmY3lgU7n+kaW/SeyZTDMvhZZV6AncGEcackkEouh4c1fH u+nHqsUHhBS2ARzjiv3zGQERnUi8JIoPxkDt1zCxkqvCYYxd6gjGxNalIgDZqtpX XcwvGjUbMd7cxzuDkTjZB+HHp1S9lJUQxi3cAOEombU7KJWqTtUCAwEAAaN7MHkw CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy dGlmaWNhdGUwHQYDVR0OBBYEFM0m60J5bQR/lSNGHgPJQC3SAK5xMB8GA1UdIwQY MBaAFIDZah4V/othUWJgTbPMlUR4LYnmMA0GCSqGSIb3DQEBBQUAA4GBAKleskwk Fd1J0U3j3ePaayOZRS2hhPKbbkg86c74f/Mf04WZlH4ZjMq+OsqXud7ITwgo/H8k N5Xh1WCXByu+YvQCHSePng02GtVFbyfDNCETGyiTncumMA2PSl9MSpd7/u3OGIRa 7E/4hC7LciiQy+Na9IMWvajv8PUSbCY+r8eo -----END CERTIFICATE----- M2Crypto-0.22.6rc4/tests/recipient_key.pem0000664000175000017500000000156712611255457020635 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCsti7wNDR91OZjeWBTuf6Rpb9J7JlMMy+FllXoCdwYRxpySQSi 6HhzV8e76ceqxQeEFLYBHOOK/fMZARGdSLwkig/GQO3XMLGSq8JhjF3qCMbE1qUi ANmq2lddzC8aNRsx3tzHO4ORONkH4cenVL2UlRDGLdwA4SiZtTsolapO1QIDAQAB AoGAXMxCqiOStK2I4Jfdzv7XrlA9WK38rDmwZfmhzNxHWvARYKilChcYaPkYQ3pY IwRchnZOWIi6JftO+/dcDIOBOsqlIRPcy7T1rMrNoouNy5IglzL5nAUfkGiPzm7Q xW5/jl7t5OA2YO8ID4jDvFjZ8Lo+mwQRD0Pd8eXyZZ/E1Z0CQQDarp9wz2HBnBQJ FY8yASX6CcLN6brrateC/gy+E8Sy82t4TOwWpLC3d8LEgYD7AZtu41VB50mUCg5e EbrGkZrjAkEAyi9J1TOf/LzrFEYOnskYiTkKLgHG1uJuDdcF4NtGn+tEc85X7R9A jAQdZGFeN26fgDqmHJlm4W0473H8sXQE5wJAJpK2vQdXjvcg8ZlD8OYS9M/T9M5N kkj+SrTVOpHyGD6nrkijPDtAkJwnVtIhFiVqbVzcJQvPBrXfYuhtsajtUQJAHS50 FpyL49uUhmmSJKLbsrqT2I4TF+K4hbDaPVkIuX4odBp9IFFZbJwPbfSLt650wPo2 DXyql7C+/fhSw33+UwJAea5E2ZMIXMwPwVH/oOaeiUqwEcJ0hQ97Y3DkiI9USPBz U3W9Nu/6eTEuFmadfPpT6SlwAbOTjEICpuOP3oPShg== -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/rsa.priv.pem0000664000175000017500000000162412605232411017525 0ustar matejmatej00000000000000-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM1lIRXaaLVgzlvW F2S6OMFJsfG+coZLx9qzmNb2gK6qjyGa71HeaLvFmQFv60dPjpuaGPs2uhL88hcN JAChGiD8LxNpVW0EEw+RRH6/CBlDGuKjkSaPz8zzpEhSZq/yGb0F4zaau1HINnwo rYPyRXWyRUzfpEB/7mx8/FUD24knAgMBAAECgYAaInsSP8dBBP9c+iHh5DwihBEL VJNX+T6F2oJhH96B2xv5R7CZ9zXWZq8wWqBSY5IexH3XQUBt+BeJzVc+aUFcpKLM D1O3OZ8NwC9HGIY0sLeX+uawYdFAPJfF8BZ8x3LMxWA8jdJM+4/P3C3jh2EvyzLT HQ1rXBPrLkH45xJQSQJBAPPfSiObRvbeJvkgE0z5SqdbQjTGxeAX5qt1e2LtTwdU gAxpYnYPz9CFCcIpa0j9UejlGninXasQvhpdwytBLk0CQQDXm/2kKh9BuWzemIu/ QcLSgc7VrGgZnGQ27fp3bXDSOV3Bev9VywLQ5VDBJcRSkMTC0V/+iHZbMl9EpwHN 8ZdDAkBJHtAZ8PrMFjvVQnrG/5AUsdYeAONfl4sAKc9/D+w8JGfoUMjG4WLMALe2 UbjrP5kJnXfcaUI6gmCdgzN7iqWZAkAvJbpKOrfJDH4lEuCEOyIaHC6ZhPDioNM9 O77ofLMOFWNOGtJY9WKxQWPuSI7sqyGLpHNEWpzfBl3UylxXp3u3AkEAzCzGUMfM 0qw/TFlVLzCHhrkP13SrJohdD693w9nuhYM2u27R32qJlF1OvN9NxEV7ZoOSGJxi CGTjWcXUGgYQgQ== -----END PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/rsa.priv2.pem0000664000175000017500000000202112605232411017577 0ustar matejmatej00000000000000-----BEGIN ENCRYPTED PRIVATE KEY----- MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIq+j6kBSOkTkCAggA MBQGCCqGSIb3DQMHBAin1qbPaI3dAQSCAoAwb9BTWY6+o9GAZk9ZUJHAHL0Yb7C/ Hkm8Kh+YBqIEHbTzzSzIO3pFFnLrLLSVbWuYX3bBJRDSUfmV9JaZu0YYJ/TzBtb5 epgD+sZ83E11NM0L3rJTI9GOUm8b9U15N94X+gnQj0JSK8Ex0dJpJ3rwHPd1zAOe 0SjXViOCCuHeu4Mnz3P9B42FR5C/53GLkqtSZCsznSBsbPGZ/mb6eEGjgYtxFm15 17Px7ezDjjr5knBozYua3OehCfI6lN1W+yyTvHGF4lpWkm7Pj24uHHh6yagFQuvB RgE8eFLLPLBBa3kHWTn6hAPL4pfPIaPiDtX69IshSv2LVcbUPp6pTkji7mo3EFpN Jigd3msMCf6w5Wh4I2k8Hb6eSkfsModIru05xq0fuTYi1nTh2l/M3FEGeOuBmpbD AYzpT6J1+373rshkdqmv1C/REsnnrACGwbM7JN6K3sKnJZesI3iiHY5tnumypyv3 f7wMaRcIq0QOi/WUIKzU0B4f9WxgjDuFwWyYlEBl2IYZ8wxD0P2s968puc7RRwrc 11Tn0a993122gBAHaa24iAW2ig2hGktLtxY1EvY6Sfd/migu2iVA6bwdVz68kKBj tYfJQEoMGJhR+NqSDYvgJYgoNljOIf6Wq++L9/zqgtYkiL7xRLqSvths2NWaxGmc RvjWFeq2sTiVXFn36jzO9YfJ4BFqgt5UoBRSw8jYQwm+W5TUhgWGQxQTTrCUs/36 5oQXOwpRol+ivO/VtMdDShg6sKHEjQ/FhHqNpPccVLg/g81HbJyfmEmeqYu6rtOd xBe9lVFW+86wObsYl1WCHYUQuBUlPv+uEDLqC92/6zLdCtDYYRYvdLF8 -----END ENCRYPTED PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/rsa.pub.pem0000664000175000017500000000042012605232411017324 0ustar matejmatej00000000000000-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNZSEV2mi1YM5b1hdkujjBSbHx vnKGS8fas5jW9oCuqo8hmu9R3mi7xZkBb+tHT46bmhj7NroS/PIXDSQAoRog/C8T aVVtBBMPkUR+vwgZQxrio5Emj8/M86RIUmav8hm9BeM2mrtRyDZ8KK2D8kV1skVM 36RAf+5sfPxVA9uJJwIDAQAB -----END PUBLIC KEY----- M2Crypto-0.22.6rc4/tests/server.pem0000664000175000017500000000752412611255457017310 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: b4:7e:b2:de:87:00:03:0c Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Validity Not Before: Nov 21 15:33:54 2012 GMT Not After : Jan 8 15:33:54 2023 GMT Subject: C=US, ST=California, O=M2Crypto, CN=localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00:dd:9d:eb:7f:82:43:ed:f2:06:1c:1d:b3:fa:e1: 41:8a:4b:bd:b4:1d:82:04:ee:63:b3:22:af:cf:94: 88:36:52:18:3e:01:b6:37:15:59:93:7f:cc:88:5a: 56:ea:02:c1:a2:bd:9f:c2:87:a4:f6:0e:cb:ca:e9: b8:c6:50:3c:87:30:15:7e:e0:4b:1d:b9:5f:8e:4f: 2b:af:64:9b:24:14:01:a7:6a:47:ab:72:f5:26:66: a5:73:33:11:bf:81:28:4f:88:14:76:49:e1:7b:ce: b8:11:fd:3c:ad:83:95:8f:be:30:ec:78:ab:d7:68: b9:70:f5:87:7a:96:f7:35:dd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 14:E4:DE:06:C8:F0:45:E8:3B:FD:48:7A:6C:9C:AC:14:1F:D5:DB:E0 X509v3 Authority Key Identifier: keyid:80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 Signature Algorithm: sha1WithRSAEncryption 74:b4:9d:87:61:b0:e5:8e:7b:38:11:1b:26:18:ba:f6:03:38: 1b:84:3f:be:95:70:eb:d6:1d:2c:d7:1e:d8:b7:26:62:84:db: cb:f4:40:6b:af:97:0e:76:5f:fb:da:d7:2b:bb:c8:bd:38:a3: 02:c1:f2:60:f4:ec:11:d8:81:54:b6:7a:a4:5b:66:72:40:cb: 72:ff:12:a3:8f:e7:6a:76:73:b3:9f:72:4e:68:40:0c:11:bd: bd:4d:93:2e:33:27:7d:8d:0a:93:c2:71:de:4f:a2:58:0c:8e: f0:ad:d2:28:05:bc:04:72:30:6d:5b:d1:4e:73:48:f1:1d:83: 65:a6 -----BEGIN CERTIFICATE----- MIICkTCCAfqgAwIBAgIJALR+st6HAAMMMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0bzEY MBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4XDTEyMTEyMTE1MzM1NFoXDTIzMDEw ODE1MzM1NFowSTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAP BgNVBAoMCE0yQ3J5cHRvMRIwEAYDVQQDDAlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcN AQEBBQADgY0AMIGJAoGBAN2d63+CQ+3yBhwds/rhQYpLvbQdggTuY7Mir8+UiDZS GD4BtjcVWZN/zIhaVuoCwaK9n8KHpPYOy8rpuMZQPIcwFX7gSx25X45PK69kmyQU AadqR6ty9SZmpXMzEb+BKE+IFHZJ4XvOuBH9PK2DlY++MOx4q9douXD1h3qW9zXd AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2Vu ZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQU5N4GyPBF6Dv9SHpsnKwUH9Xb 4DAfBgNVHSMEGDAWgBSA2WoeFf6LYVFiYE2zzJVEeC2J5jANBgkqhkiG9w0BAQUF AAOBgQB0tJ2HYbDljns4ERsmGLr2AzgbhD++lXDr1h0s1x7YtyZihNvL9EBrr5cO dl/72tcru8i9OKMCwfJg9OwR2IFUtnqkW2ZyQMty/xKjj+dqdnOzn3JOaEAMEb29 TZMuMyd9jQqTwnHeT6JYDI7wrdIoBbwEcjBtW9FOc0jxHYNlpg== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDdnet/gkPt8gYcHbP64UGKS720HYIE7mOzIq/PlIg2Uhg+AbY3 FVmTf8yIWlbqAsGivZ/Ch6T2DsvK6bjGUDyHMBV+4EsduV+OTyuvZJskFAGnaker cvUmZqVzMxG/gShPiBR2SeF7zrgR/Tytg5WPvjDseKvXaLlw9Yd6lvc13QIDAQAB AoGAIZzWHxzO2MQgkRsgNSj9G9CpESx4j+7oSD82kzFgB30kGCOCU5B1aZ20k+m/ zPZmEBzaolKYfol392rDj7CTvVT5VQh5QzkVeU28iLOBVqUJ1fwh5gBvIy5iEXzo O58M8y2IDyJ2W84UUtIav8LD3xGKDxD7k14FW5TIwXfCE4ECQQD8gAI7RHfViv0M 9qSsZ7MapR4wwJKolapfHJda8hM+uEaSanJ/2RwAe5mfn92VUubmAG+Xcoe9HR9x dJQ5hAllAkEA4LBSq3T8+5wNUBE7V9OUP4Eh8ytbEviurNizfM4sBTrsXBVyDoBU +ji9BCcDtbaB+GewnpsrXeqSJ/eKxMnvGQJALInH2vxwxtIFYMwAsAh6pzCI6sCN Hf+IVc6NRBV/H4kRqbHtEHATaGJk7qscQsKkx9070dL57nm8mh6eJqcLoQJBALM0 LltNrVBIQF3xwHDl8UFNDvTRSYwyB68YDt+l2Ho7arRu7k8ej6gahLbBHzZY4ARt PvLhM49uPS/fQTB/FlECQHaIJA/MFMtpFpv2h0Vsq5Rq0kayzFy/1Cf7k+E9wVUg gqcUvnEaT990We8Ffri/HlBtIuiuC7lVtv7zKu//VHU= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/sig.p70000664000175000017500000000330012613276453016316 0ustar matejmatej00000000000000-----BEGIN PKCS7----- MIIE1wYJKoZIhvcNAQcCoIIEyDCCBMQCAQExCzAJBgUrDgMCGgUAMBgGCSqGSIb3 DQEHAaALBAlzb21lIHRleHSgggK1MIICsTCCAhqgAwIBAgIJALR+st6HAAMOMA0G CSqGSIb3DQEBBQUAME8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh MREwDwYDVQQKDAhNMkNyeXB0bzEYMBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4X DTEyMTEyMTE1Mzc1NVoXDTIzMDEwODE1Mzc1NVowaTELMAkGA1UEBhMCVVMxEzAR BgNVBAgMCkNhbGlmb3JuaWExETAPBgNVBAoMCE0yQ3J5cHRvMQ8wDQYDVQQDDAZT aWduZXIxITAfBgkqhkiG9w0BCQEWEnNpZ25lckBleGFtcGxlLmNvbTCBnzANBgkq hkiG9w0BAQEFAAOBjQAwgYkCgYEAofPAS4QDVMTb3ZV1S9LjS2Ne++loMjp5Ols8 8a48ZRGhoobZRSDBqDzpZMZcmljurtNOrweVgF9M/mS9Za4skfz6v9yqX9o2TAp3 Yeak9qNUkr85EoRE2asS2nhDILZQbJ2HOieGlRSnnPLYNin7HiRkYRNItd4XYUls KmHaA7ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFAd9E8Cv9eRjzXxkaP/S Z/wnRtwEMB8GA1UdIwQYMBaAFIDZah4V/othUWJgTbPMlUR4LYnmMA0GCSqGSIb3 DQEBBQUAA4GBAABkvL5LQnJUyn4CKIeQB8jLrawY+om7HqggwRo50uO6ttkctr+7 x9xGO5msgROZ94ifsq4Z/9c3woOqysjSAx/OALiGKrAtgOiDwIM0it2fdcXfYf/M wYur4OETAv9jSx1YC106pOmjtToZL9ykwkq0Rl4M+llOxTFfohiqyKSSMYIB3TCC AdkCAQEwXDBPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTERMA8G A1UECgwITTJDcnlwdG8xGDAWBgNVBAMMD0hlaWtraSBUb2l2b25lbgIJALR+st6H AAMOMAkGBSsOAwIaBQCggdgwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq hkiG9w0BCQUxDxcNMTUxMDI2MDEwODU5WjAjBgkqhkiG9w0BCQQxFgQUN6pjx3OY 2VRHMmLhoAV8HmMu2ncweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI hvcNAQEBBQAEgYCCwjie6VA+ujzNsemm6eyhgbGfynpaLSAHV5GrAmndZW8ILAS/ tkW28JLRNo5575r4YHYHTyBPRbkj2EU0lszBqSKdemAJ/jTKOjT1bqk/zsQaFvmd hjm6qu3PqgpeGYRor/QBFVGXp5NW8DfJCqDVie4AillzvTki9gICm1mpAQ== -----END PKCS7----- M2Crypto-0.22.6rc4/tests/sig.p7s0000664000175000017500000000413212613276453016505 0ustar matejmatej00000000000000MIME-Version: 1.0 Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha1"; boundary="----7A9933A5721BEA867FC99CE1F09978F1" This is an S/MIME signed message ------7A9933A5721BEA867FC99CE1F09978F1 some text ------7A9933A5721BEA867FC99CE1F09978F1 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" MIIEygYJKoZIhvcNAQcCoIIEuzCCBLcCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3 DQEHAaCCArUwggKxMIICGqADAgECAgkAtH6y3ocAAw4wDQYJKoZIhvcNAQEFBQAw TzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAPBgNVBAoMCE0y Q3J5cHRvMRgwFgYDVQQDDA9IZWlra2kgVG9pdm9uZW4wHhcNMTIxMTIxMTUzNzU1 WhcNMjMwMTA4MTUzNzU1WjBpMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZv cm5pYTERMA8GA1UECgwITTJDcnlwdG8xDzANBgNVBAMMBlNpZ25lcjEhMB8GCSqG SIb3DQEJARYSc2lnbmVyQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN ADCBiQKBgQCh88BLhANUxNvdlXVL0uNLY1776WgyOnk6WzzxrjxlEaGihtlFIMGo POlkxlyaWO6u006vB5WAX0z+ZL1lriyR/Pq/3Kpf2jZMCndh5qT2o1SSvzkShETZ qxLaeEMgtlBsnYc6J4aVFKec8tg2KfseJGRhE0i13hdhSWwqYdoDsQIDAQABo3sw eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUB30TwK/15GPNfGRo/9Jn/CdG3AQwHwYDVR0j BBgwFoAUgNlqHhX+i2FRYmBNs8yVRHgtieYwDQYJKoZIhvcNAQEFBQADgYEAAGS8 vktCclTKfgIoh5AHyMutrBj6ibseqCDBGjnS47q22Ry2v7vH3EY7mayBE5n3iJ+y rhn/1zfCg6rKyNIDH84AuIYqsC2A6IPAgzSK3Z91xd9h/8zBi6vg4RMC/2NLHVgL XTqk6aO1Ohkv3KTCSrRGXgz6WU7FMV+iGKrIpJIxggHdMIIB2QIBATBcME8xCzAJ BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0 bzEYMBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuAgkAtH6y3ocAAw4wCQYFKw4DAhoF AKCB2DAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0x NTEwMjYwMTA4NTlaMCMGCSqGSIb3DQEJBDEWBBQ3qmPHc5jZVEcyYuGgBXweYy7a dzB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASBgILC OJ7pUD66PM2x6abp7KGBsZ/KelotIAdXkasCad1lbwgsBL+2RbbwktE2jnnvmvhg dgdPIE9FuSPYRTSWzMGpIp16YAn+NMo6NPVuqT/OxBoW+Z2GObqq7c+qCl4ZhGiv 9AEVUZenk1bwN8kKoNWJ7gCKWXO9OSL2AgKbWakB ------7A9933A5721BEA867FC99CE1F09978F1-- M2Crypto-0.22.6rc4/tests/signer.pem0000664000175000017500000000604312611255457017264 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: b4:7e:b2:de:87:00:03:0e Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Validity Not Before: Nov 21 15:37:55 2012 GMT Not After : Jan 8 15:37:55 2023 GMT Subject: C=US, ST=California, O=M2Crypto, CN=Signer/emailAddress=signer@example.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00:a1:f3:c0:4b:84:03:54:c4:db:dd:95:75:4b:d2: e3:4b:63:5e:fb:e9:68:32:3a:79:3a:5b:3c:f1:ae: 3c:65:11:a1:a2:86:d9:45:20:c1:a8:3c:e9:64:c6: 5c:9a:58:ee:ae:d3:4e:af:07:95:80:5f:4c:fe:64: bd:65:ae:2c:91:fc:fa:bf:dc:aa:5f:da:36:4c:0a: 77:61:e6:a4:f6:a3:54:92:bf:39:12:84:44:d9:ab: 12:da:78:43:20:b6:50:6c:9d:87:3a:27:86:95:14: a7:9c:f2:d8:36:29:fb:1e:24:64:61:13:48:b5:de: 17:61:49:6c:2a:61:da:03:b1 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 07:7D:13:C0:AF:F5:E4:63:CD:7C:64:68:FF:D2:67:FC:27:46:DC:04 X509v3 Authority Key Identifier: keyid:80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 Signature Algorithm: sha1WithRSAEncryption 00:64:bc:be:4b:42:72:54:ca:7e:02:28:87:90:07:c8:cb:ad: ac:18:fa:89:bb:1e:a8:20:c1:1a:39:d2:e3:ba:b6:d9:1c:b6: bf:bb:c7:dc:46:3b:99:ac:81:13:99:f7:88:9f:b2:ae:19:ff: d7:37:c2:83:aa:ca:c8:d2:03:1f:ce:00:b8:86:2a:b0:2d:80: e8:83:c0:83:34:8a:dd:9f:75:c5:df:61:ff:cc:c1:8b:ab:e0: e1:13:02:ff:63:4b:1d:58:0b:5d:3a:a4:e9:a3:b5:3a:19:2f: dc:a4:c2:4a:b4:46:5e:0c:fa:59:4e:c5:31:5f:a2:18:aa:c8: a4:92 -----BEGIN CERTIFICATE----- MIICsTCCAhqgAwIBAgIJALR+st6HAAMOMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0bzEY MBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4XDTEyMTEyMTE1Mzc1NVoXDTIzMDEw ODE1Mzc1NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAP BgNVBAoMCE0yQ3J5cHRvMQ8wDQYDVQQDDAZTaWduZXIxITAfBgkqhkiG9w0BCQEW EnNpZ25lckBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA ofPAS4QDVMTb3ZV1S9LjS2Ne++loMjp5Ols88a48ZRGhoobZRSDBqDzpZMZcmlju rtNOrweVgF9M/mS9Za4skfz6v9yqX9o2TAp3Yeak9qNUkr85EoRE2asS2nhDILZQ bJ2HOieGlRSnnPLYNin7HiRkYRNItd4XYUlsKmHaA7ECAwEAAaN7MHkwCQYDVR0T BAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh dGUwHQYDVR0OBBYEFAd9E8Cv9eRjzXxkaP/SZ/wnRtwEMB8GA1UdIwQYMBaAFIDZ ah4V/othUWJgTbPMlUR4LYnmMA0GCSqGSIb3DQEBBQUAA4GBAABkvL5LQnJUyn4C KIeQB8jLrawY+om7HqggwRo50uO6ttkctr+7x9xGO5msgROZ94ifsq4Z/9c3woOq ysjSAx/OALiGKrAtgOiDwIM0it2fdcXfYf/MwYur4OETAv9jSx1YC106pOmjtToZ L9ykwkq0Rl4M+llOxTFfohiqyKSS -----END CERTIFICATE----- M2Crypto-0.22.6rc4/tests/signer_key.pem0000664000175000017500000000156712611255457020142 0ustar matejmatej00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCh88BLhANUxNvdlXVL0uNLY1776WgyOnk6WzzxrjxlEaGihtlF IMGoPOlkxlyaWO6u006vB5WAX0z+ZL1lriyR/Pq/3Kpf2jZMCndh5qT2o1SSvzkS hETZqxLaeEMgtlBsnYc6J4aVFKec8tg2KfseJGRhE0i13hdhSWwqYdoDsQIDAQAB AoGAOAsY1UkWugPxrellkNqmq1T07qnj09XmU6p1GZFY9wS18X9GuqROP8DsZ2I5 c3QpDLi09t7h/m18QGBuJjyy0Tk3iFsLZ1+F1nNCFOZTeRybWA2MS91P9bpYri63 tarTxHaDe/RsMsaXe2HBp2rjw/jxT3y5DYwwWPQWjEIgf/0CQQDT7yeEtdj5LN1O NW9Coj3MzAodjyz5Jz1bCRGvhXpnralaM8Oyl1Dix99wGM64VuHvE5Lg0gY1ySg2 YJeYfuo/AkEAw6AmUTUrG8+axMkKX+rXz7LvaOR6Ad39uXO3S2lhbACQAy1Tn4W+ gJ2x0zJY+lY8oRQpXqZi1wzdLI/JGL82DwJAQvZmcx0N8DUHu6VQgSpIAoRZkdti J1sJnNDxwJaZBVcukiyW4b/Ds9PZOk7sSfxRqLtzhgt2INptFTlRzMIU+wJBALYc 1s7uoi0HvVrIlUHpy/Js73dEi1hForgMQ2yOs8TpWSe8AIcW6Nuu8iZcTnzt3w9N R533Yzgzn4qmaF0DVH0CQGHvjKMwb63YsnyjiUHtjG/zlN7FZWAIr3wEPNoMl2dd s33jU+euC2oKygr1tSUf1lSM+yLCvDTetzg+1uBNfmg= -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/tests/test_asn1.py0000664000175000017500000000557112611255457017552 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.ASN1. Copyright (c) 2005 Open Source Applications Foundation. All rights reserved.""" import time, datetime try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import ASN1, m2 class ASN1TestCase(unittest.TestCase): def test_Integer(self): pass # XXX Dunno how to test def test_BitSTring(self): pass # XXX Dunno how to test def test_String(self): asn1ptr = m2.asn1_string_new() text = 'hello there' # In RFC2253 format: # #040B68656C6C6F207468657265 # h e l l o t h e r e m2.asn1_string_set(asn1ptr, text) a = ASN1.ASN1_String(asn1ptr, 1) assert a.as_text() == 'hello there', a.as_text() assert a.as_text(flags=m2.ASN1_STRFLGS_RFC2253) == '#040B68656C6C6F207468657265', a.as_text(flags=m2.ASN1_STRFLGS_RFC2253) self.assertEqual(a.as_text(), str(a)) def test_Object(self): pass # XXX Dunno how to test def test_UTCTIME(self): asn1 = ASN1.ASN1_UTCTIME() assert str(asn1) == 'Bad time value' format = '%b %d %H:%M:%S %Y GMT' utcformat = '%y%m%d%H%M%SZ' s = '990807053011Z' asn1.set_string(s) #assert str(asn1) == 'Aug 7 05:30:11 1999 GMT' t1 = time.strptime(str(asn1), format) t2 = time.strptime(s, utcformat) self.assertEqual(t1, t2) asn1.set_time(500) #assert str(asn1) == 'Jan 1 00:08:20 1970 GMT' t1 = time.strftime(format, time.strptime(str(asn1), format)) t2 = time.strftime(format, time.gmtime(500)) self.assertEqual(t1, t2) t = long(time.time()) + time.timezone asn1.set_time(t) t1 = time.strftime(format, time.strptime(str(asn1), format)) t2 = time.strftime(format, time.gmtime(t)) self.assertEqual(t1, t2) def test_UTCTIME_datetime(self): asn1 = ASN1.ASN1_UTCTIME() # Test get_datetime and set_datetime t = time.time() dt = datetime.datetime.fromtimestamp(int(t)) udt = dt.replace(tzinfo=ASN1.LocalTimezone()).astimezone(ASN1.UTC) asn1.set_time(int(t)) t1 = str(asn1) asn1.set_datetime(dt) t2 = str(asn1) self.assertEqual(t1, t2) self.assertEqual(str(udt), str(asn1.get_datetime())) dt = dt.replace(tzinfo=ASN1.LocalTimezone()) asn1.set_datetime(dt) t2 = str(asn1) self.assertEqual(t1, t2) self.assertEqual(str(udt), str(asn1.get_datetime())) dt = dt.astimezone(ASN1.UTC) asn1.set_datetime(dt) t2 = str(asn1) self.assertEqual(t1, t2) self.assertEqual(str(udt), str(asn1.get_datetime())) def suite(): return unittest.makeSuite(ASN1TestCase) if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_authcookie.py0000664000175000017500000001171412611255457021037 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.AuthCookie. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" import Cookie, binascii, time, sys try: import unittest2 as unittest except ImportError: import unittest from M2Crypto.AuthCookie import AuthCookie, AuthCookieJar, mix, unmix, unmix3 from M2Crypto import Rand, EVP class AuthCookieTestCase(unittest.TestCase): _format = 'Set-Cookie: _M2AUTH_="exp=%s&data=%s&digest=%s"' if sys.version_info < (2,5): _format += ';' _token = '_M2AUTH_' def setUp(self): self.data = 'cogitoergosum' self.exp = time.time() + 3600 self.jar = AuthCookieJar() def tearDown(self): pass def test_mix_unmix(self): dough = mix(self.exp, self.data) exp, data = unmix(dough) self.assertEqual(data, self.data) self.assertEqual(exp, self.exp) def test_make_cookie(self): c = self.jar.makeCookie(self.exp, self.data) self.assertTrue(isinstance(c, AuthCookie)) self.assertEqual(c.expiry(), self.exp) self.assertEqual(c.data(), self.data) # Peek inside the cookie jar... key = self.jar._key mac = binascii.b2a_base64(EVP.hmac(key, mix(self.exp, self.data), 'sha1'))[:-1] self.assertEqual(c.mac(), mac) # Ok, stop peeking now. cookie_str = self._format % (repr(self.exp), self.data, mac) self.assertEqual(c.output(), cookie_str) def test_expired(self): t = self.exp - 7200 c = self.jar.makeCookie(t, self.data) self.assertTrue(c.isExpired()) def test_not_expired(self): c = self.jar.makeCookie(self.exp, self.data) self.assertFalse(c.isExpired()) def test_is_valid(self): c = self.jar.makeCookie(self.exp, self.data) self.assertTrue(self.jar.isGoodCookie(c)) def test_is_invalid_expired(self): t = self.exp - 7200 c = self.jar.makeCookie(t, self.data) self.assertFalse(self.jar.isGoodCookie(c)) def test_is_invalid_changed_exp(self): c = self.jar.makeCookie(self.exp, self.data) c._expiry = 'this is bad' self.assertFalse(self.jar.isGoodCookie(c)) def test_is_invalid_changed_data(self): c = self.jar.makeCookie(self.exp, self.data) c._data = 'this is bad' self.assertFalse(self.jar.isGoodCookie(c)) def test_is_invalid_changed_mac(self): c = self.jar.makeCookie(self.exp, self.data) c._mac = 'this is bad' self.assertFalse(self.jar.isGoodCookie(c)) def test_mix_unmix3(self): c = self.jar.makeCookie(self.exp, self.data) s = Cookie.SmartCookie() s.load(c.output()) exp, data, digest = unmix3(s[self._token].value) self.assertEqual(data, self.data) self.assertEqual(float(exp), self.exp) key = self.jar._key # Peeking... mac = binascii.b2a_base64(EVP.hmac(key, mix(self.exp, self.data), 'sha1'))[:-1] self.assertEqual(digest, mac) def test_cookie_str(self): c = self.jar.makeCookie(self.exp, self.data) self.assertTrue(self.jar.isGoodCookieString(c.output())) def test_cookie_str2(self): c = self.jar.makeCookie(self.exp, self.data) s = Cookie.SmartCookie() s.load(c.output()) self.assertTrue(self.jar.isGoodCookieString(s.output())) def test_cookie_str_expired(self): t = self.exp - 7200 c = self.jar.makeCookie(t, self.data) s = Cookie.SmartCookie() s.load(c.output()) self.assertFalse(self.jar.isGoodCookieString(s.output())) def test_cookie_str_arbitrary_change(self): c = self.jar.makeCookie(self.exp, self.data) cout = c.output() str = cout[:32] + 'this is bad' + cout[32:] s = Cookie.SmartCookie() s.load(str) self.assertFalse(self.jar.isGoodCookieString(s.output())) def test_cookie_str_changed_exp(self): c = self.jar.makeCookie(self.exp, self.data) cout = c.output() str = cout[:26] + chr(ord(cout[26])^1) + cout[27:] s = Cookie.SmartCookie() s.load(str) self.assertFalse(self.jar.isGoodCookieString(s.output())) def test_cookie_str_changed_data(self): c = self.jar.makeCookie(self.exp, self.data) cout = c.output() str = cout[:36] + chr(ord(cout[36])^1) + cout[37:] s = Cookie.SmartCookie() s.load(str) self.assertFalse(self.jar.isGoodCookieString(s.output())) def test_cookie_str_changed_mac(self): c = self.jar.makeCookie(self.exp, self.data) cout = c.output() str = cout[:76] + chr(ord(cout[76])^1) + cout[77:] s = Cookie.SmartCookie() s.load(str) self.assertFalse(self.jar.isGoodCookieString(s.output())) def suite(): return unittest.makeSuite(AuthCookieTestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_bio.py0000664000175000017500000000471612611255457017461 0ustar matejmatej00000000000000#!/usr/bin/env python """ Unit tests for M2Crypto.BIO. Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. Copyright (c) 2006 Open Source Applications Foundation Author: Heikki Toivonen """ try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import BIO, Rand from fips import fips_mode class CipherStreamTestCase(unittest.TestCase): def try_algo(self, algo): enc = 1 dec = 0 data = '123456789012345678901234' # Encrypt. mem = BIO.MemoryBuffer() cf = BIO.CipherStream(mem) cf.set_cipher(algo, 'key', 'iv', 1) cf.write(data) cf.flush() cf.write_close() cf.close() xxx = mem.read() # Decrypt. mem = BIO.MemoryBuffer(xxx) cf = BIO.CipherStream(mem) cf.set_cipher(algo, 'key', 'iv', 0) cf.write_close() data2 = cf.read() cf.close() assert not cf.readable() self.assertRaises(IOError, cf.read) self.assertRaises(IOError, cf.readline) self.assertRaises(IOError, cf.readlines) assert data == data2, '%s algorithm cipher test failed' % algo def test_ciphers(self): ciphers=[ 'des_ede_ecb', 'des_ede_cbc', 'des_ede_cfb', 'des_ede_ofb', 'des_ede3_ecb', 'des_ede3_cbc', 'des_ede3_cfb', 'des_ede3_ofb', 'aes_128_ecb', 'aes_128_cbc', 'aes_128_cfb', 'aes_128_ofb', 'aes_192_ecb', 'aes_192_cbc', 'aes_192_cfb', 'aes_192_ofb', 'aes_256_ecb', 'aes_256_cbc', 'aes_256_cfb', 'aes_256_ofb'] nonfips_ciphers=['bf_ecb', 'bf_cbc', 'bf_cfb', 'bf_ofb', #'idea_ecb', 'idea_cbc', 'idea_cfb', 'idea_ofb', 'cast5_ecb', 'cast5_cbc', 'cast5_cfb', 'cast5_ofb', #'rc5_ecb', 'rc5_cbc', 'rc5_cfb', 'rc5_ofb', 'des_ecb', 'des_cbc', 'des_cfb', 'des_ofb', 'rc4', 'rc2_40_cbc'] if not fips_mode: # Forbidden ciphers ciphers += nonfips_ciphers for i in ciphers: self.try_algo(i) self.assertRaises(ValueError, self.try_algo, 'nosuchalgo4567') def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(CipherStreamTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_bio_file.py0000664000175000017500000000404612611255457020454 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.BIO.File. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" import os, sys try: import unittest2 as unittest except ImportError: import unittest import M2Crypto from M2Crypto.BIO import File, openfile class FileTestCase(unittest.TestCase): def setUp(self): self.data = 'abcdef' * 64 if sys.platform != 'win32': self.fname = os.tmpnam() else: import tempfile self.fname = tempfile.mktemp() def tearDown(self): try: os.unlink(self.fname) except OSError: pass def test_openfile_rb(self): # First create the file using Python's open(). f = open(self.fname, 'wb') f.write(self.data) f.close() # Now open the file using M2Crypto.BIO.openfile(). f = openfile(self.fname, 'rb') data = f.read(len(self.data)) assert data == self.data def test_openfile_wb(self): # First create the file using M2Crypto.BIO.openfile(). f = openfile(self.fname, 'wb') f.write(self.data) f.close() # Now open the file using Python's open(). f = open(self.fname, 'rb') data = f.read(len(self.data)) assert data == self.data def test_closed(self): f = openfile(self.fname, 'wb') f.write(self.data) f.close() self.assertRaises(IOError, f.write, self.data) def test_use_pyfile(self): # First create the file. f = open(self.fname, 'wb') f2 = File(f) f2.write(self.data) f2.close() # Now read the file. f = open(self.fname, 'rb') data = f.read(len(self.data)) assert data == self.data def suite(): # Python 2.2 warns that os.tmpnam() is unsafe. try: import warnings warnings.filterwarnings('ignore') except ImportError: pass return unittest.makeSuite(FileTestCase) if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_bio_iobuf.py0000664000175000017500000000445112611255457020641 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.BIO.IOBuffer. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" from cStringIO import StringIO try: import unittest2 as unittest except ImportError: import unittest import M2Crypto from M2Crypto.BIO import IOBuffer, MemoryBuffer class IOBufferTestCase(unittest.TestCase): def setUp(self): self._data = 'abcdef\n' self.data = self._data * 1024 def tearDown(self): pass def test_init_empty(self): mb = MemoryBuffer() io = IOBuffer(mb) out = io.read() assert out == '' def test_init_something(self): mb = MemoryBuffer(self.data) io = IOBuffer(mb) out = io.read(len(self.data)) assert out == self.data def test_read_less_than(self): chunk = len(self.data) - 7 mb = MemoryBuffer(self.data) io = IOBuffer(mb) out = io.read(chunk) assert out == self.data[:chunk] def test_read_more_than(self): chunk = len(self.data) + 8 mb = MemoryBuffer(self.data) io = IOBuffer(mb) out = io.read(chunk) assert out == self.data def test_readline(self): buf = StringIO() mb = MemoryBuffer(self.data) io = IOBuffer(mb) while 1: out = io.readline() if not out: break buf.write(out) assert out == self._data assert buf.getvalue() == self.data def test_readlines(self): buf = StringIO() mb = MemoryBuffer(self.data) io = IOBuffer(mb) lines = io.readlines() for line in lines: assert line == self._data buf.write(line) assert buf.getvalue() == self.data def test_closed(self): mb = MemoryBuffer(self.data) io = IOBuffer(mb) io.close() self.assertRaises(IOError, io.write, self.data) assert not io.readable() and not io.writeable() def test_read_only(self): mb = MemoryBuffer(self.data) io = IOBuffer(mb, mode='r') self.assertRaises(IOError, io.write, self.data) assert not io.writeable() def suite(): return unittest.makeSuite(IOBufferTestCase) if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_bio_membuf.py0000664000175000017500000000325012611255457021004 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.BIO.MemoryBuffer. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" try: import unittest2 as unittest except ImportError: import unittest import M2Crypto from M2Crypto.BIO import MemoryBuffer class MemoryBufferTestCase(unittest.TestCase): def setUp(self): self.data = 'abcdef' * 64 def tearDown(self): pass def test_init_empty(self): mb = MemoryBuffer() assert len(mb) == 0 out = mb.read() assert out is None def test_init_something(self): mb = MemoryBuffer(self.data) assert len(mb) == len(self.data) out = mb.read() assert out == self.data def test_read_less_than(self): chunk = len(self.data) - 7 mb = MemoryBuffer(self.data) out = mb.read(chunk) assert out == self.data[:chunk] and len(mb) == (len(self.data) - chunk) def test_read_more_than(self): chunk = len(self.data) + 8 mb = MemoryBuffer(self.data) out = mb.read(chunk) assert out == self.data and len(mb) == 0 def test_write_close(self): mb = MemoryBuffer(self.data) assert mb.writeable() mb.write_close() assert mb.readable() self.assertRaises(IOError, mb.write, self.data) assert not mb.writeable() def test_closed(self): mb = MemoryBuffer(self.data) mb.close() self.assertRaises(IOError, mb.write, self.data) assert mb.readable() and not mb.writeable() def suite(): return unittest.makeSuite(MemoryBufferTestCase) if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_bio_ssl.py0000664000175000017500000001144712611255457020341 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.BIO.File. Copyright (c) 1999-2002 Ng Pheng Siong. All rights reserved.""" import threading, sys, socket try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import BIO from M2Crypto import SSL from M2Crypto import Err from M2Crypto import Rand from M2Crypto import threading as m2threading from test_ssl import srv_host, allocate_srv_port class HandshakeClient(threading.Thread): def __init__(self, host, port): threading.Thread.__init__(self) self.host = host self.port = port def run(self): ctx = SSL.Context() ctx.load_cert_chain("tests/server.pem") conn = SSL.Connection(ctx) cipher_list = conn.get_cipher_list() sslbio = BIO.SSLBio() readbio = BIO.MemoryBuffer() writebio = BIO.MemoryBuffer() sslbio.set_ssl(conn) conn.set_bio(readbio, writebio) conn.set_connect_state() sock = socket.socket() sock.connect((self.host, self.port)) handshake_complete = False while not handshake_complete: ret = sslbio.do_handshake() if ret <= 0: if not sslbio.should_retry() or not sslbio.should_read(): err_string = Err.get_error() print err_string sys.exit("unrecoverable error in handshake - client") else: output_token = writebio.read() if output_token is not None: sock.sendall(output_token) else: input_token = sock.recv(1024) readbio.write(input_token) else: handshake_complete = True sock.close() class SSLTestCase(unittest.TestCase): def setUp(self): self.sslbio = BIO.SSLBio() def test_pass(self): # XXX leaks 64/24 bytes pass def test_set_ssl(self): # XXX leaks 64/1312 bytes ctx = SSL.Context() conn = SSL.Connection(ctx) self.sslbio.set_ssl(conn) def test_do_handshake_fail(self): # XXX leaks 64/42066 bytes ctx = SSL.Context() conn = SSL.Connection(ctx) conn.set_connect_state() self.sslbio.set_ssl(conn) ret = self.sslbio.do_handshake() assert ret == 0 def test_should_retry_fail(self): # XXX leaks 64/1312 bytes ctx = SSL.Context() conn = SSL.Connection(ctx) self.sslbio.set_ssl(conn) ret = self.sslbio.do_handshake() assert ret == -1 ret = self.sslbio.should_retry() assert ret == 0 def test_should_write_fail(self): # XXX leaks 64/1312 bytes ctx = SSL.Context() conn = SSL.Connection(ctx) self.sslbio.set_ssl(conn) ret = self.sslbio.do_handshake() assert ret == -1 ret = self.sslbio.should_write() assert ret == 0 def test_should_read_fail(self): # XXX leaks 64/1312 bytes ctx = SSL.Context() conn = SSL.Connection(ctx) self.sslbio.set_ssl(conn) ret = self.sslbio.do_handshake() assert ret == -1 ret = self.sslbio.should_read() assert ret == 0 def test_do_handshake_succeed(self): # XXX leaks 196/26586 bytes ctx = SSL.Context() ctx.load_cert_chain("tests/server.pem") conn = SSL.Connection(ctx) self.sslbio.set_ssl(conn) readbio = BIO.MemoryBuffer() writebio = BIO.MemoryBuffer() conn.set_bio(readbio, writebio) conn.set_accept_state() handshake_complete = False srv_port = allocate_srv_port() sock = socket.socket() sock.bind((srv_host, srv_port)) sock.listen(5) handshake_client = HandshakeClient(srv_host, srv_port) handshake_client.start() new_sock, addr = sock.accept() while not handshake_complete: input_token = new_sock.recv(1024) readbio.write(input_token) ret = self.sslbio.do_handshake() if ret <= 0: if not self.sslbio.should_retry() or not self.sslbio.should_read(): sys.exit("unrecoverable error in handshake - server") else: handshake_complete = True output_token = writebio.read() if output_token is not None: new_sock.sendall(output_token) handshake_client.join() sock.close() new_sock.close() def suite(): return unittest.makeSuite(SSLTestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) m2threading.init() unittest.TextTestRunner().run(suite()) m2threading.cleanup() Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_bn.py0000775000175000017500000000371212611255457017305 0ustar matejmatej00000000000000#!/usr/bin/env python """ Unit tests for M2Crypto.BN. Copyright (c) 2005 Open Source Applications Foundation. All rights reserved. """ import re try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import BN, Rand loops = 16 class BNTestCase(unittest.TestCase): def test_rand(self): # defaults for x in range(loops): r8 = BN.rand(8) # top for x in range(loops): r8 = BN.rand(8, top=0) assert r8 & 128 for x in range(loops): r8 = BN.rand(8, top=1) assert r8 & 192 # bottom for x in range(loops): r8 = BN.rand(8, bottom=1) assert r8 % 2 == 1 # make sure we can get big numbers and work with them for x in range(loops): r8 = BN.rand(8, top=0) r16 = BN.rand(16, top=0) r32 = BN.rand(32, top=0) r64 = BN.rand(64, top=0) r128 = BN.rand(128, top=0) r256 = BN.rand(256, top=0) r512 = BN.rand(512, top=0) assert r8 < r16 < r32 < r64 < r128 < r256 < r512 < (r512 + 1) def test_rand_range(self): # small range for x in range(loops): r = BN.rand_range(1) assert r == 0 for x in range(loops): r = BN.rand_range(4) assert 0 <= r < 4 # large range r512 = BN.rand(512, top=0) for x in range(loops): r = BN.rand_range(r512) assert 0 <= r < r512 def test_randfname(self): m = re.compile('^[a-zA-Z0-9]{8}$') for x in range(loops): r = BN.randfname(8) assert m.match(r) def suite(): return unittest.makeSuite(BNTestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_dh.py0000664000175000017500000000333612611255457017300 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.DH. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import DH, BIO, Rand, m2 class DHTestCase(unittest.TestCase): params = 'tests/dhparam.pem' def genparam_callback(self, *args): pass def genparam_callback2(self): pass def test_init_junk(self): self.assertRaises(TypeError, DH.DH, 'junk') def test_gen_params(self): a = DH.gen_params(1024, 2, self.genparam_callback) assert a.check_params() == 0 def test_gen_params_bad_cb(self): a = DH.gen_params(1024, 2, self.genparam_callback2) assert a.check_params() == 0 def test_print_params(self): a = DH.gen_params(1024, 2, self.genparam_callback) bio = BIO.MemoryBuffer() a.print_params(bio) params = bio.read() assert params.find('(1024 bit)') assert params.find('generator: 2 (0x2)') def test_load_params(self): a = DH.load_params('tests/dhparams.pem') assert a.check_params() == 0 def test_compute_key(self): a = DH.load_params('tests/dhparams.pem') b = DH.set_params(a.p, a.g) a.gen_key() b.gen_key() ak = a.compute_key(b.pub) bk = b.compute_key(a.pub) assert ak == bk self.assertEqual(len(a), 128) self.assertRaises(DH.DHError, setattr, a, 'p', 1) self.assertRaises(DH.DHError, setattr, a, 'priv', 1) def suite(): return unittest.makeSuite(DHTestCase) if __name__=='__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_dsa.py0000664000175000017500000000602112613276364017450 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.DSA. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" import hashlib try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import DSA, Rand class DSATestCase(unittest.TestCase): errkey = 'tests/rsa.priv.pem' privkey = 'tests/dsa.priv.pem' pubkey = 'tests/dsa.pub.pem' param = 'tests/dsa.param.pem' data = hashlib.sha1('Can you spell subliminal channel?').digest() different_data = hashlib.sha1('I can spell.').digest() def callback(self, *args): pass def test_loadkey_junk(self): self.assertRaises(DSA.DSAError, DSA.load_key, self.errkey) def test_loadkey(self): dsa = DSA.load_key(self.privkey) assert len(dsa) == 1024 self.assertRaises(AttributeError, getattr, dsa, 'foobar') for k in ('p', 'q', 'g', 'priv', 'pub'): self.assertRaises(DSA.DSAError, setattr, dsa, k, 1) def test_loadparam(self): self.assertRaises(DSA.DSAError, DSA.load_key, self.param) dsa = DSA.load_params(self.param) assert not dsa.check_key() assert len(dsa) == 1024 def test_sign(self): dsa = DSA.load_key(self.privkey) assert dsa.check_key() r, s = dsa.sign(self.data) assert dsa.verify(self.data, r, s) assert not dsa.verify(self.data, s, r) def test_sign_asn1(self): dsa = DSA.load_key(self.privkey) blob = dsa.sign_asn1(self.data) assert dsa.verify_asn1(self.data, blob) def test_sign_with_params_only(self): dsa = DSA.load_params(self.param) self.assertRaises(AssertionError, dsa.sign, self.data) self.assertRaises(AssertionError, dsa.sign_asn1, self.data) def test_pub_verify(self): dsa = DSA.load_key(self.privkey) r, s = dsa.sign(self.data) dsapub = DSA.load_pub_key(self.pubkey) assert dsapub.check_key() assert dsapub.verify(self.data, r, s) self.assertRaises(DSA.DSAError, dsapub.sign) def test_verify_fail(self): dsa = DSA.load_key(self.privkey) r, s = dsa.sign(self.data) assert not dsa.verify(self.different_data, r, s) def test_verify_fail2(self): dsa = DSA.load_key(self.privkey) r, s = dsa.sign(self.data) dsa2 = DSA.load_params(self.param) assert not dsa2.check_key() self.assertRaises(AssertionError, dsa2.verify, self.data, r, s) def test_genparam_setparam_genkey(self): dsa = DSA.gen_params(1024, self.callback) assert len(dsa) == 1024 p = dsa.p q = dsa.q g = dsa.g dsa2 = DSA.set_params(p, q, g) assert not dsa2.check_key() dsa2.gen_key() assert dsa2.check_key() r, s = dsa2.sign(self.data) assert dsa2.verify(self.data, r, s) def suite(): return unittest.makeSuite(DSATestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_ec_curves.py0000664000175000017500000001157412613361242020656 0ustar matejmatej00000000000000#!/usr/bin/env python # XXX memory leaks """ Unit tests for M2Crypto.EC, the curves There are several ways one could unittest elliptical curves but we are going to only validate that we are using the OpenSSL curve and that it works with ECDSA. We will assume OpenSSL has validated the curves themselves. Also, some curves are shorter than a SHA-1 digest of 160 bits. To keep the testing simple, we will take advantage of ECDSA's ability to sign any digest length and create a digset string of only 48 bits. Remember we are testing our ability to access the curve, not ECDSA itself. Copyright (c) 2006 Larry Bugbee. All rights reserved. """ #import sha try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import EC, Rand from test_ecdsa import ECDSATestCase as ECDSATest curves = [ ('secp112r1', 112), ('secp112r2', 112), ('secp128r1', 128), ('secp128r2', 128), ('secp160k1', 160), ('secp160r1', 160), ('secp160r2', 160), ('secp192k1', 192), ('secp224k1', 224), ('secp224r1', 224), ('secp256k1', 256), ('secp384r1', 384), ('secp521r1', 521), ('sect113r1', 113), ('sect113r2', 113), ('sect131r1', 131), ('sect131r2', 131), ('sect163k1', 163), ('sect163r1', 163), ('sect163r2', 163), ('sect193r1', 193), ('sect193r2', 193), ('sect233k1', 233), ('sect233r1', 233), ('sect239k1', 239), ('sect283k1', 283), ('sect283r1', 283), ('sect409k1', 409), ('sect409r1', 409), ('sect571k1', 571), ('sect571r1', 571), ('X9_62_prime192v1', 192), ('X9_62_prime192v2', 192), ('X9_62_prime192v3', 192), ('X9_62_prime239v1', 239), ('X9_62_prime239v2', 239), ('X9_62_prime239v3', 239), ('X9_62_prime256v1', 256), ('X9_62_c2pnb163v1', 163), ('X9_62_c2pnb163v2', 163), ('X9_62_c2pnb163v3', 163), ('X9_62_c2pnb176v1', 176), ('X9_62_c2tnb191v1', 191), ('X9_62_c2tnb191v2', 191), ('X9_62_c2tnb191v3', 191), ('X9_62_c2pnb208w1', 208), ('X9_62_c2tnb239v1', 239), ('X9_62_c2tnb239v2', 239), ('X9_62_c2tnb239v3', 239), ('X9_62_c2pnb272w1', 272), ('X9_62_c2pnb304w1', 304), ('X9_62_c2tnb359v1', 359), ('X9_62_c2pnb368w1', 368), ('X9_62_c2tnb431r1', 431), ('wap_wsg_idm_ecid_wtls1', 113), ('wap_wsg_idm_ecid_wtls3', 163), ('wap_wsg_idm_ecid_wtls4', 113), ('wap_wsg_idm_ecid_wtls5', 163), ('wap_wsg_idm_ecid_wtls6', 112), ('wap_wsg_idm_ecid_wtls7', 160), ('wap_wsg_idm_ecid_wtls8', 112), ('wap_wsg_idm_ecid_wtls9', 160), ('wap_wsg_idm_ecid_wtls10', 233), ('wap_wsg_idm_ecid_wtls11', 233), ('wap_wsg_idm_ecid_wtls12', 224), ] # The following two curves, according to OpenSSL, have a # "Questionable extension field!" and are not supported by # the OpenSSL inverse function. ECError: no inverse. # As such they cannot be used for signing. They might, # however, be usable for encryption but that has not # been tested. Until thir usefulness can be established, # they are not supported at this time. #curves2 = [ # ('ipsec3', 155), # ('ipsec4', 185), #] class ECCurveTests(unittest.TestCase): #data = sha.sha('Kilroy was here!').digest() # 160 bits data = "digest" # keep short (48 bits) so lesser curves # will work... ECDSA requires curve be # equal or longer than digest def genkey(self, curveName, curveLen): curve = getattr(EC, 'NID_'+curveName) ec = EC.gen_params(curve) assert len(ec) == curveLen ec.gen_key() assert ec.check_key(), 'check_key() failure for "%s"' % curveName return ec # def check_ec_curves_genkey(self): # for curveName, curveLen in curves2: # self.genkey(curveName, curveLen) # # self.assertRaises(AttributeError, self.genkey, # 'nosuchcurve', 1) def sign_verify_ecdsa(self, curveName, curveLen): ec = self.genkey(curveName, curveLen) r, s = ec.sign_dsa(self.data) assert ec.verify_dsa(self.data, r, s) assert not ec.verify_dsa(self.data, s, r) def test_ec_curves_ECDSA(self): for curveName, curveLen in curves: self.sign_verify_ecdsa(curveName, curveLen) self.assertRaises(AttributeError, self.sign_verify_ecdsa, 'nosuchcurve', 1) # for curveName, curveLen in curves2: # self.assertRaises(EC.ECError, self.sign_verify_ecdsa, # curveName, curveLen) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ECCurveTests)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_ecdh.py0000664000175000017500000000241112613361242017571 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.EC, ECDH part. Copyright (c) 2000 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved. """ import sys try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import EC, BIO, Rand, m2 class ECDHTestCase(unittest.TestCase): privkey = 'tests/ec.priv.pem' def test_init_junk(self): self.assertRaises(TypeError, EC.EC, 'junk') def test_compute_key(self): a = EC.load_key(self.privkey) b = EC.gen_params(EC.NID_sect233k1) b.gen_key() ak = a.compute_dh_key(b.pub()) bk = b.compute_dh_key(a.pub()) assert ak == bk def test_pubkey_from_der(self): a = EC.gen_params(EC.NID_sect233k1) a.gen_key() b = EC.gen_params(EC.NID_sect233k1) b.gen_key() a_pub_der = a.pub().get_der() a_pub = EC.pub_key_from_der(a_pub_der) ak = a.compute_dh_key(b.pub()) bk = b.compute_dh_key(a_pub) assert ak == bk def suite(): return unittest.makeSuite(ECDHTestCase) if __name__=='__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_ecdsa.py0000664000175000017500000000422012613361242017745 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.EC, ECDSA part. Copyright (c) 2000 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved. """ import hashlib try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import EC, BIO, Rand, m2 class ECDSATestCase(unittest.TestCase): errkey = 'tests/rsa.priv.pem' privkey = 'tests/ec.priv.pem' pubkey = 'tests/ec.pub.pem' data = hashlib.sha1('Can you spell subliminal channel?').digest() def callback(self, *args): pass def callback2(self): pass def test_loadkey_junk(self): self.assertRaises(ValueError, EC.load_key, self.errkey) def test_loadkey(self): ec = EC.load_key(self.privkey) assert len(ec) == 233 def test_loadpubkey(self): # XXX more work needed ec = EC.load_pub_key(self.pubkey) assert len(ec) == 233 self.assertRaises(EC.ECError, EC.load_pub_key, self.errkey) def _test_sign_dsa(self): ec = EC.gen_params(EC.NID_sect233k1) # ec.gen_key() self.assertRaises(EC.ECError, ec.sign_dsa, self.data) ec = EC.load_key(self.privkey) r, s = ec.sign_dsa(self.data) assert ec.verify_dsa(self.data, r, s) assert not ec.verify_dsa(self.data, s, r) def test_sign_dsa_asn1(self): ec = EC.load_key(self.privkey) blob = ec.sign_dsa_asn1(self.data) assert ec.verify_dsa_asn1(self.data, blob) self.assertRaises(EC.ECError, ec.verify_dsa_asn1, blob, self.data) def test_verify_dsa(self): ec = EC.load_key(self.privkey) r, s = ec.sign_dsa(self.data) ec2 = EC.load_pub_key(self.pubkey) assert ec2.verify_dsa(self.data, r, s) assert not ec2.verify_dsa(self.data, s, r) def test_genparam(self): ec = EC.gen_params(EC.NID_sect233k1) assert len(ec) == 233 def suite(): return unittest.makeSuite(ECDSATestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_engine.py0000664000175000017500000000245112611255457020147 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.Engine.""" try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import Engine, m2 class EngineTestCase(unittest.TestCase): privkey = 'tests/rsa.priv.pem' bad_id = '1bea1edfeb97' def tearDown(self): Engine.cleanup() def test_by_id_junk(self): self.assertRaises(ValueError, Engine.Engine, self.bad_id) self.assertRaises(ValueError, Engine.Engine) def test_by_id_openssl(self): Engine.load_openssl() e = Engine.Engine('openssl') self.assertEqual(e.get_name(), 'Software engine support') self.assertEqual(e.get_id(), 'openssl') def test_by_id_dynamic(self): Engine.load_dynamic() Engine.Engine('dynamic') def test_load_private(self): Engine.load_openssl() e = Engine.Engine('openssl') e.set_default() e.load_private_key(self.privkey) def test_load_certificate(self): Engine.load_openssl() e = Engine.Engine('openssl') e.set_default() self.assertRaises(Engine.EngineError, e.load_certificate, '/dev/null') def suite(): return unittest.makeSuite(EngineTestCase) if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_evp.py0000664000175000017500000004427612611255457017507 0ustar matejmatej00000000000000#!/usr/bin/env python """ Unit tests for M2Crypto.EVP. Copyright (c) 2004-2007 Open Source Applications Foundation Author: Heikki Toivonen """ import cStringIO, sha from binascii import hexlify, unhexlify try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import EVP, RSA, util, Rand, m2, BIO from M2Crypto.util import h2b from fips import fips_mode class EVPTestCase(unittest.TestCase): def _gen_callback(self, *args): pass def _pass_callback(self, *args): return 'foobar' def _assign_rsa(self): rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey = EVP.PKey() pkey.assign_rsa(rsa, capture=0) # capture=1 should cause crash return rsa def test_assign(self): rsa = self._assign_rsa() rsa.check_key() def test_pem(self): rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey = EVP.PKey() pkey.assign_rsa(rsa) assert pkey.as_pem(callback=self._pass_callback) != pkey.as_pem(cipher=None) self.assertRaises(ValueError, pkey.as_pem, cipher='noXX$$%%suchcipher', callback=self._pass_callback) def test_as_der(self): """ Test DER encoding the PKey instance after assigning a RSA key to it. """ rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey = EVP.PKey() pkey.assign_rsa(rsa) der_blob = pkey.as_der() #A quick but not thorough sanity check assert len(der_blob) == 160 def test_MessageDigest(self): self.assertRaises(ValueError, EVP.MessageDigest, 'sha513') md = EVP.MessageDigest('sha1') assert md.update('Hello') == 1 assert util.octx_to_num(md.final()) == 1415821221623963719413415453263690387336440359920 def test_as_der_capture_key(self): """ Test DER encoding the PKey instance after assigning a RSA key to it. Have the PKey instance capture the RSA key. """ rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey = EVP.PKey() pkey.assign_rsa(rsa, 1) der_blob = pkey.as_der() #A quick but not thorough sanity check assert len(der_blob) == 160 def test_size(self): rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey = EVP.PKey() pkey.assign_rsa(rsa) size = pkey.size() assert size == 128 def test_hmac(self): assert util.octx_to_num(EVP.hmac('key', 'data')) == 92800611269186718152770431077867383126636491933, util.octx_to_num(EVP.hmac('key', 'data')) if not fips_mode: # Disabled algorithms assert util.octx_to_num(EVP.hmac('key', 'data', algo='md5')) == 209168838103121722341657216703105225176, util.octx_to_num(EVP.hmac('key', 'data', algo='md5')) assert util.octx_to_num(EVP.hmac('key', 'data', algo='ripemd160')) == 1176807136224664126629105846386432860355826868536, util.octx_to_num(EVP.hmac('key', 'data', algo='ripemd160')) if m2.OPENSSL_VERSION_NUMBER >= 0x90800F: assert util.octx_to_num(EVP.hmac('key', 'data', algo='sha224')) == 2660082265842109788381286338540662430962855478412025487066970872635, util.octx_to_num(EVP.hmac('key', 'data', algo='sha224')) assert util.octx_to_num(EVP.hmac('key', 'data', algo='sha256')) == 36273358097036101702192658888336808701031275731906771612800928188662823394256, util.octx_to_num(EVP.hmac('key', 'data', algo='sha256')) assert util.octx_to_num(EVP.hmac('key', 'data', algo='sha384')) == 30471069101236165765942696708481556386452105164815350204559050657318908408184002707969468421951222432574647369766282, util.octx_to_num(EVP.hmac('key', 'data', algo='sha384')) assert util.octx_to_num(EVP.hmac('key', 'data', algo='sha512')) == 3160730054100700080556942280820129108466291087966635156623014063982211353635774277148932854680195471287740489442390820077884317620321797003323909388868696, util.octx_to_num(EVP.hmac('key', 'data', algo='sha512')) self.assertRaises(ValueError, EVP.hmac, 'key', 'data', algo='sha513') def test_get_rsa(self): """ Testing retrieving the RSA key from the PKey instance. """ rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) assert isinstance(rsa, RSA.RSA) pkey = EVP.PKey() pkey.assign_rsa(rsa) rsa2 = pkey.get_rsa() assert isinstance(rsa2, RSA.RSA_pub) assert rsa.e == rsa2.e assert rsa.n == rsa2.n pem = rsa.as_pem(callback=self._pass_callback) pem2 = rsa2.as_pem() assert pem assert pem2 assert pem != pem2 message = "This is the message string" digest = sha.sha(message).digest() assert rsa.sign(digest) == rsa2.sign(digest) rsa3 = RSA.gen_key(1024, 3, callback=self._gen_callback) assert rsa.sign(digest) != rsa3.sign(digest) def test_get_rsa_fail(self): """ Testing trying to retrieve the RSA key from the PKey instance when it is not holding a RSA Key. Should raise a ValueError. """ pkey = EVP.PKey() self.assertRaises(ValueError, pkey.get_rsa) def test_get_modulus(self): pkey = EVP.PKey() self.assertRaises(ValueError, pkey.get_modulus) rsa = RSA.gen_key(1024, 3, callback=self._gen_callback) pkey.assign_rsa(rsa) mod = pkey.get_modulus() assert len(mod) > 0, mod assert len(mod.strip('0123456789ABCDEF')) == 0 def test_verify_final(self): from M2Crypto import X509 pkey = EVP.load_key('tests/signer_key.pem') pkey.sign_init() pkey.sign_update('test message') sig = pkey.sign_final() # OK x509 = X509.load_cert('tests/signer.pem') pubkey = x509.get_pubkey() pubkey.verify_init() pubkey.verify_update('test message') assert pubkey.verify_final(sig) == 1 # wrong cert x509 = X509.load_cert('tests/x509.pem') pubkey = x509.get_pubkey() pubkey.verify_init() pubkey.verify_update('test message') assert pubkey.verify_final(sig) == 0 # wrong message x509 = X509.load_cert('tests/signer.pem') pubkey = x509.get_pubkey() pubkey.verify_init() pubkey.verify_update('test message not') assert pubkey.verify_final(sig) == 0 def test_load_bad(self): self.assertRaises(BIO.BIOError, EVP.load_key, 'thisdoesnotexist-dfgh56789') self.assertRaises(EVP.EVPError, EVP.load_key, 'tests/signer.pem') # not a key self.assertRaises(EVP.EVPError, EVP.load_key_bio, BIO.MemoryBuffer('no a key')) def test_pad(self): self.assertEqual(util.pkcs5_pad('Hello World'), 'Hello World\x05\x05\x05\x05\x05') self.assertEqual(util.pkcs7_pad('Hello World', 15), 'Hello World\x04\x04\x04\x04') self.assertRaises(ValueError, util.pkcs7_pad, 'Hello', 256) class CipherTestCase(unittest.TestCase): def cipher_filter(self, cipher, inf, outf): while 1: buf=inf.read() if not buf: break outf.write(cipher.update(buf)) outf.write(cipher.final()) return outf.getvalue() def try_algo(self, algo): enc = 1 dec = 0 otxt='against stupidity the gods themselves contend in vain' k=EVP.Cipher(algo, 'goethe','12345678', enc, 1, 'sha1', 'saltsalt', 5) pbuf=cStringIO.StringIO(otxt) cbuf=cStringIO.StringIO() ctxt=self.cipher_filter(k, pbuf, cbuf) pbuf.close() cbuf.close() j=EVP.Cipher(algo, 'goethe','12345678', dec, 1, 'sha1', 'saltsalt', 5) pbuf=cStringIO.StringIO() cbuf=cStringIO.StringIO(ctxt) ptxt=self.cipher_filter(j, cbuf, pbuf) pbuf.close() cbuf.close() assert otxt == ptxt, '%s algorithm cipher test failed' % algo def test_ciphers(self): ciphers=[ 'des_ede_ecb', 'des_ede_cbc', 'des_ede_cfb', 'des_ede_ofb', 'des_ede3_ecb', 'des_ede3_cbc', 'des_ede3_cfb', 'des_ede3_ofb', 'aes_128_ecb', 'aes_128_cbc', 'aes_128_cfb', 'aes_128_ofb', 'aes_192_ecb', 'aes_192_cbc', 'aes_192_cfb', 'aes_192_ofb', 'aes_256_ecb', 'aes_256_cbc', 'aes_256_cfb', 'aes_256_ofb'] nonfips_ciphers=['bf_ecb', 'bf_cbc', 'bf_cfb', 'bf_ofb', #'idea_ecb', 'idea_cbc', 'idea_cfb', 'idea_ofb', 'cast5_ecb', 'cast5_cbc', 'cast5_cfb', 'cast5_ofb', #'rc5_ecb', 'rc5_cbc', 'rc5_cfb', 'rc5_ofb', 'des_ecb', 'des_cbc', 'des_cfb', 'des_ofb', 'rc4', 'rc2_40_cbc'] if not fips_mode: # Disabled algorithms ciphers += nonfips_ciphers for i in ciphers: self.try_algo(i) # idea might not be compiled in ciphers=['idea_ecb', 'idea_cbc', 'idea_cfb', 'idea_ofb'] try: for i in ciphers: self.try_algo(i) except ValueError, e: if str(e) != "('unknown cipher', 'idea_ecb')": raise # rc5 might not be compiled in ciphers=['rc5_ecb', 'rc5_cbc', 'rc5_cfb', 'rc5_ofb'] try: for i in ciphers: self.try_algo(i) except ValueError, e: if str(e) != "('unknown cipher', 'rc5_ecb')": raise self.assertRaises(ValueError, self.try_algo, 'nosuchalgo4567') def test_AES(self): enc = 1 dec = 0 tests = [ # test vectors from rfc 3602 #Case #1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key { 'KEY': '06a9214036b8a15b512e03d534120006', 'IV': '3dafba429d9eb430b422da802c9fac41', 'PT': 'Single block msg', 'CT': 'e353779c1079aeb82708942dbe77181a', }, #Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key { 'KEY': 'c286696d887c9aa0611bbb3e2025a45a', 'IV': '562e17996d093d28ddb3ba695a2e6f58', 'PT': unhexlify('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'), 'CT': 'd296cd94c2cccf8a3a863028b5e1dc0a7586602d253cfff91b8266bea6d61ab1', }, #Case #3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key { 'KEY': '6c3ea0477630ce21a2ce334aa746c2cd', 'IV': 'c782dc4c098c66cbd9cd27d825682c81', 'PT': 'This is a 48-byte message (exactly 3 AES blocks)', 'CT': 'd0a02b3836451753d493665d33f0e8862dea54cdb293abc7506939276772f8d5021c19216bad525c8579695d83ba2684', }, ] # Test with padding for test in tests: # encrypt k=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=enc) pbuf=cStringIO.StringIO(test['PT']) cbuf=cStringIO.StringIO() ciphertext = hexlify(self.cipher_filter(k, pbuf, cbuf)) cipherpadding = ciphertext[len(test['PT']) * 2:] ciphertext = ciphertext[:len(test['PT']) * 2] # Remove the padding from the end pbuf.close() cbuf.close() self.assertEqual(ciphertext, test['CT']) # decrypt j=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=dec) pbuf=cStringIO.StringIO() cbuf=cStringIO.StringIO(unhexlify(test['CT'] + cipherpadding)) plaintext=self.cipher_filter(j, cbuf, pbuf) pbuf.close() cbuf.close() self.assertEqual(plaintext, test['PT']) # Test without padding for test in tests: # encrypt k=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=enc, padding=False) pbuf=cStringIO.StringIO(test['PT']) cbuf=cStringIO.StringIO() ciphertext = hexlify(self.cipher_filter(k, pbuf, cbuf)) pbuf.close() cbuf.close() self.assertEqual(ciphertext, test['CT']) # decrypt j=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=dec, padding=False) pbuf=cStringIO.StringIO() cbuf=cStringIO.StringIO(unhexlify(test['CT'])) plaintext=self.cipher_filter(j, cbuf, pbuf) pbuf.close() cbuf.close() self.assertEqual(plaintext, test['PT']) def test_raises(self): def _cipherFilter(cipher, inf, outf): while 1: buf = inf.read() if not buf: break outf.write(cipher.update(buf)) outf.write(cipher.final()) return outf.getvalue() def decrypt(ciphertext, key, iv, alg='aes_256_cbc'): cipher = EVP.Cipher(alg=alg, key=key, iv=iv, op=0) pbuf = cStringIO.StringIO() cbuf = cStringIO.StringIO(ciphertext) plaintext = _cipherFilter(cipher, cbuf, pbuf) pbuf.close() cbuf.close() return plaintext self.assertRaises(EVP.EVPError, decrypt, unhexlify('941d3647a642fab26d9f99a195098b91252c652d07235b9db35758c401627711724637648e45cad0f1121751a1240a4134998cfdf3c4a95c72de2a2444de3f9e40d881d7f205630b0d8ce142fdaebd8d7fbab2aea3dc47f5f29a0e9b55aae59222671d8e2877e1fb5cd8ef1c427027e0'), unhexlify('5f2cc54067f779f74d3cf1f78c735aec404c8c3a4aaaa02eb1946f595ea4cddb'), unhexlify('0001efa4bd154ee415b9413a421cedf04359fff945a30e7c115465b1c780a85b65c0e45c')) self.assertRaises(EVP.EVPError, decrypt, unhexlify('a78a510416c1a6f1b48077cc9eeb4287dcf8c5d3179ef80136c18876d774570d'), unhexlify('5cd148eeaf680d4ff933aed83009cad4110162f53ef89fd44fad09611b0524d4'), unhexlify('')) class PBKDF2TestCase(unittest.TestCase): def test_rfc3211_test_vectors(self): from binascii import hexlify, unhexlify password = 'password' salt = unhexlify('12 34 56 78 78 56 34 12'.replace(' ', '')) iter = 5 keylen = 8 ret = EVP.pbkdf2(password, salt, iter, keylen) self.assertEqual(hexlify(ret), 'D1 DA A7 86 15 F2 87 E6'.replace(' ', '').lower()) password = 'All n-entities must communicate with other n-entities via n-1 entiteeheehees' salt = unhexlify('12 34 56 78 78 56 34 12'.replace(' ', '')) iter = 500 keylen = 16 ret = EVP.pbkdf2(password, salt, iter, keylen) self.assertEqual(hexlify(ret), '6A 89 70 BF 68 C9 2C AE A8 4A 8D F2 85 10 85 86'.replace(' ', '').lower()) class HMACTestCase(unittest.TestCase): data1=['', 'More text test vectors to stuff up EBCDIC machines :-)', \ h2b("b760e92d6662d351eb3801057695ac0346295356")] data2=[h2b('0b'*16), "Hi There", \ h2b("675b0b3a1b4ddf4e124872da6c2f632bfed957e9")] data3=['Jefe', "what do ya want for nothing?", \ h2b("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")] data4=[h2b('aa'*16), h2b('dd'*50), \ h2b("d730594d167e35d5956fd8003d0db3d3f46dc7bb")] data=[data1, data2, data3, data4] def test_simple(self): algo = 'sha1' for d in self.data: h = EVP.HMAC(d[0], algo) h.update(d[1]) ret = h.final() self.assertEqual(ret, d[2]) self.assertRaises(ValueError, EVP.HMAC, d[0], algo='nosuchalgo') def make_chain_HMAC(self, key, start, input, algo='sha1'): chain = [] hmac = EVP.HMAC(key, algo) hmac.update(`start`) digest = hmac.final() chain.append((digest, start)) for i in input: hmac.reset(digest) hmac.update(`i`) digest = hmac.final() chain.append((digest, i)) return chain def make_chain_hmac(self, key, start, input, algo='sha1'): from M2Crypto.EVP import hmac chain = [] digest = hmac(key, `start`, algo) chain.append((digest, start)) for i in input: digest = hmac(digest, `i`, algo) chain.append((digest, i)) return chain def verify_chain_hmac(self, key, start, chain, algo='sha1'): from M2Crypto.EVP import hmac digest = hmac(key, `start`, algo) c = chain[0] if c[0] != digest or c[1] != start: return 0 for d, v in chain[1:]: digest = hmac(digest, `v`, algo) if digest != d: return 0 return 1 def verify_chain_HMAC(self, key, start, chain, algo='sha1'): hmac = EVP.HMAC(key, algo) hmac.update(`start`) digest = hmac.final() c = chain[0] if c[0] != digest or c[1] != start: return 0 for d, v in chain[1:]: hmac.reset(digest) hmac.update(`v`) digest = hmac.final() if digest != d: return 0 return 1 def test_complicated(self): make_chain = self.make_chain_hmac verify_chain = self.verify_chain_hmac key = 'numero uno' start = 'zeroth item' input = ['first item', 'go go go', 'fly fly fly'] chain = make_chain(key, start, input) self.assertEquals(verify_chain('some key', start, chain), 0) self.assertEquals(verify_chain(key, start, chain), 1) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(EVPTestCase)) suite.addTest(unittest.makeSuite(CipherTestCase)) suite.addTest(unittest.makeSuite(PBKDF2TestCase)) suite.addTest(unittest.makeSuite(HMACTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_obj.py0000664000175000017500000000643012611255457017455 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.m2 obj_* functions. """ try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import X509, ASN1, BIO, Rand, m2 """ These functions must be cleaned up and moved to some python module Taken from CA managment code """ def x509_name2list(name): for i in range(0, name.entry_count()): yield X509.X509_Name_Entry(m2.x509_name_get_entry(name._ptr(), i), _pyfree = 0) def x509_name_entry2tuple(entry): bio = BIO.MemoryBuffer() m2.asn1_string_print(bio._ptr(), m2.x509_name_entry_get_data(entry._ptr())) return (m2.obj_obj2txt(m2.x509_name_entry_get_object(entry._ptr()), 0), bio.getvalue()) def tuple2x509_name_entry(tup): obj, data = tup _x509_ne = m2.x509_name_entry_create_by_txt(None, obj, ASN1.MBSTRING_ASC, data, len(data)) if not _x509_ne: raise ValueError("Invalid object indentifier: %s" % obj) return X509.X509_Name_Entry(_x509_ne, _pyfree = 1) # Prevent memory leaks class ObjectsTestCase(unittest.TestCase): def callback(self, *args): pass def test_obj2txt(self): assert m2.obj_obj2txt(m2.obj_txt2obj("commonName", 0), 1) == "2.5.4.3", "2.5.4.3" assert m2.obj_obj2txt(m2.obj_txt2obj("commonName", 0), 0) == "commonName", "commonName" def test_nid(self): assert m2.obj_ln2nid("commonName") == m2.obj_txt2nid("2.5.4.3"), "ln2nid and txt2nid mismatch" assert m2.obj_ln2nid("CN") == 0, "ln2nid on sn" assert m2.obj_sn2nid("CN") == m2.obj_ln2nid("commonName"), "ln2nid and sn2nid mismatch" assert m2.obj_sn2nid("CN") == m2.obj_obj2nid(m2.obj_txt2obj("CN", 0)), "obj2nid" assert m2.obj_txt2nid("__unknown") == 0, "__unknown" def test_tuple2tuple(self): tup = ("CN", "someCommonName") tup1 = x509_name_entry2tuple(tuple2x509_name_entry(tup)) assert tup1[1] == tup[1], tup1 # tup1[0] is 'commonName', not 'CN' assert x509_name_entry2tuple(tuple2x509_name_entry(tup1)) == tup1, tup1 def test_unknown(self): self.assertRaises(ValueError, tuple2x509_name_entry, ("__unknown", "_")) def test_x509_name(self): n = X509.X509_Name() n.C = 'US' # It seems this actually needs to be a real 2 letter country code n.SP = 'State or Province' n.L = 'locality name' n.O = 'orhanization name' n.OU = 'org unit' n.CN = 'common name' n.Email = 'bob@example.com' n.serialNumber = '1234' n.SN = 'surname' n.GN = 'given name' n.givenName = 'name given' assert len(n) == 11, len(n) tl = map(x509_name_entry2tuple, x509_name2list(n)) assert len(tl) == len(n), len(tl) x509_n = m2.x509_name_new() for o in map(tuple2x509_name_entry, tl): m2.x509_name_add_entry(x509_n, o._ptr(), -1, 0) o._pyfree = 0 # Take care of underlying object n1 = X509.X509_Name(x509_n) assert n.as_text() == n1.as_text(), n1.as_text() def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ObjectsTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_pgp.py0000664000175000017500000000200612611255457017464 0ustar matejmatej00000000000000#!/usr/bin/env python """PGP test program. Copyright (c) 1999 Ng Pheng Siong. All rights reserved.""" from cStringIO import StringIO try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import EVP, PGP class PGPTestCase(unittest.TestCase): def test_simple(self): pkr = PGP.load_pubring('tests/pubring.pgp') daft = pkr['daft'] daft_pkt = daft._pubkey_pkt.pack() s1 = EVP.MessageDigest('sha1') s1.update(daft_pkt) s1f = `s1.final()` buf = StringIO(daft_pkt) ps = PGP.packet_stream(buf) dift_pkt = ps.read() s2 = EVP.MessageDigest('sha1') s2.update(dift_pkt.pack()) s2f = `s2.final()` self.assertEqual(s1f, s2f) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(PGPTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_rand.py0000664000175000017500000000312412611255457017624 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.Rand. Copyright (C) 2006 Open Source Applications Foundation (OSAF). All Rights Reserved. """ import os, sys try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import Rand class RandTestCase(unittest.TestCase): def test_bytes(self): self.assertRaises(MemoryError, Rand.rand_bytes, -1) assert Rand.rand_bytes(0) == '' assert len(Rand.rand_bytes(1)) == 1 def test_pseudo_bytes(self): self.assertRaises(MemoryError, Rand.rand_pseudo_bytes, -1) assert Rand.rand_pseudo_bytes(0) == ('', 1) a, b = Rand.rand_pseudo_bytes(1) assert len(a) == 1 assert b == 1 def test_load_save(self): try: os.remove('tests/randpool.dat') except OSError: pass assert Rand.load_file('tests/randpool.dat', -1) == 0 assert Rand.save_file('tests/randpool.dat') == 1024 assert Rand.load_file('tests/randpool.dat', -1) == 1024 def test_seed_add(self): if sys.version_info >= (2, 4): assert Rand.rand_seed(os.urandom(1024)) is None # XXX Should there be limits on the entropy parameter? assert Rand.rand_add(os.urandom(2), 0.5) is None Rand.rand_add(os.urandom(2), -0.5) Rand.rand_add(os.urandom(2), 5000.0) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(RandTestCase)) return suite if __name__ == '__main__': unittest.TextTestRunner().run(suite()) M2Crypto-0.22.6rc4/tests/test_rc4.py0000664000175000017500000000252112613361242017360 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.RC4. Copyright (c) 2009 Heikki Toivonen. All rights reserved.""" try: import unittest2 as unittest except ImportError: import unittest from binascii import hexlify from M2Crypto import RC4 from fips import fips_mode class RC4TestCase(unittest.TestCase): @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") def test_vectors(self): """ Test with test vectors from Wikipedia: http://en.wikipedia.org/wiki/Rc4 """ vectors = (('Key', 'Plaintext', 'BBF316E8D940AF0AD3'), ('Wiki', 'pedia', '1021BF0420'), ('Secret', 'Attack at dawn', '45A01F645FC35B383552544B9BF5')) rc4 = RC4.RC4() for key, plaintext, ciphertext in vectors: rc4.set_key(key) self.assertEqual(hexlify(rc4.update(plaintext)).upper(), ciphertext) self.assertEqual(rc4.final(), '') @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") def test_bad(self): rc4 = RC4.RC4('foo') self.assertNotEqual(hexlify(rc4.update('bar')).upper(), '45678') def suite(): return unittest.makeSuite(RC4TestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_rsa.py0000664000175000017500000002630312613361405017462 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.RSA. Copyright (c) 2000 Ng Pheng Siong. All rights reserved.""" import hashlib import os import sys try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import BIO, RSA, Rand, X509, m2 from fips import fips_mode class RSATestCase(unittest.TestCase): errkey = 'tests/dsa.priv.pem' privkey = 'tests/rsa.priv.pem' privkey2 = 'tests/rsa.priv2.pem' pubkey = 'tests/rsa.pub.pem' data = hashlib.sha1('The magic words are squeamish ossifrage.').digest() e_padding_ok = ('pkcs1_padding', 'pkcs1_oaep_padding') s_padding_ok = ('pkcs1_padding',) s_padding_nok = ('no_padding', 'sslv23_padding', 'pkcs1_oaep_padding') def gen_callback(self, *args): pass def gen2_callback(self): pass def pp_callback(self, *args): # The passphrase for rsa.priv2.pem is 'qwerty'. return 'qwerty' def pp2_callback(self, *args): # Misbehaving passphrase callback. pass def test_loadkey_junk(self): self.assertRaises(RSA.RSAError, RSA.load_key, self.errkey) def test_loadkey_pp(self): rsa = RSA.load_key(self.privkey2, self.pp_callback) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 assert rsa.check_key() == 1 def test_loadkey_pp_bad_cb(self): with self.assertRaises(RSA.RSAError): RSA.load_key(self.privkey2, self.pp2_callback) def test_loadkey(self): rsa = RSA.load_key(self.privkey) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 self.assertEqual(rsa.n, "\x00\x00\x00\x81\x00\xcde!\x15\xdah\xb5`\xce[\xd6\x17d\xba8\xc1I\xb1\xf1\xber\x86K\xc7\xda\xb3\x98\xd6\xf6\x80\xae\xaa\x8f!\x9a\xefQ\xdeh\xbb\xc5\x99\x01o\xebGO\x8e\x9b\x9a\x18\xfb6\xba\x12\xfc\xf2\x17\r$\x00\xa1\x1a \xfc/\x13iUm\x04\x13\x0f\x91D~\xbf\x08\x19C\x1a\xe2\xa3\x91&\x8f\xcf\xcc\xf3\xa4HRf\xaf\xf2\x19\xbd\x05\xe36\x9a\xbbQ\xc86|(\xad\x83\xf2Eu\xb2EL\xdf\xa4@\x7f\xeel|\xfcU\x03\xdb\x89'") self.assertRaises(AttributeError, getattr, rsa, 'nosuchprop') assert rsa.check_key() == 1 def test_loadkey_bio(self): keybio = BIO.MemoryBuffer(open(self.privkey).read()) rsa = RSA.load_key_bio(keybio) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 assert rsa.check_key() == 1 def test_keygen(self): rsa = RSA.gen_key(1024, 65537, self.gen_callback) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 assert rsa.check_key() == 1 def test_keygen_bad_cb(self): rsa = RSA.gen_key(1024, 65537, self.gen2_callback) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 assert rsa.check_key() == 1 def test_private_encrypt(self): priv = RSA.load_key(self.privkey) # pkcs1_padding for padding in self.s_padding_ok: p = getattr(RSA, padding) ctxt = priv.private_encrypt(self.data, p) ptxt = priv.public_decrypt(ctxt, p) assert ptxt == self.data # The other paddings. for padding in self.s_padding_nok: p = getattr(RSA, padding) self.assertRaises(RSA.RSAError, priv.private_encrypt, self.data, p) # Type-check the data to be encrypted. with self.assertRaises(TypeError): priv.private_encrypt(self.gen_callback, RSA.pkcs1_padding) def test_public_encrypt(self): priv = RSA.load_key(self.privkey) # pkcs1_padding, pkcs1_oaep_padding for padding in self.e_padding_ok: p = getattr(RSA, padding) ctxt = priv.public_encrypt(self.data, p) ptxt = priv.private_decrypt(ctxt, p) self.assertEqual(ptxt, self.data) # sslv23_padding ctxt = priv.public_encrypt(self.data, RSA.sslv23_padding) with self.assertRaises(RSA.RSAError): priv.private_decrypt(ctxt, RSA.sslv23_padding) with self.assertRaises(RSA.RSAError): priv.private_decrypt(ctxt, RSA.sslv23_padding) # no_padding with self.assertRaises(RSA.RSAError): priv.public_encrypt(self.data, RSA.no_padding) # Type-check the data to be encrypted. with self.assertRaises(TypeError): priv.public_encrypt(self.gen_callback, RSA.pkcs1_padding) def test_x509_public_encrypt(self): x509 = X509.load_cert("tests/recipient.pem") rsa = x509.get_pubkey().get_rsa() rsa.public_encrypt("data", RSA.pkcs1_padding) def test_loadpub(self): rsa = RSA.load_pub_key(self.pubkey) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 self.assertRaises(RSA.RSAError, setattr, rsa, 'e', '\000\000\000\003\001\000\001') self.assertRaises(RSA.RSAError, rsa.private_encrypt, 1) self.assertRaises(RSA.RSAError, rsa.private_decrypt, 1) assert rsa.check_key() def test_loadpub_bad(self): self.assertRaises(RSA.RSAError, RSA.load_pub_key, self.errkey) def test_savepub(self): rsa = RSA.load_pub_key(self.pubkey) assert rsa.as_pem() # calls save_key_bio f = 'tests/rsa_test.pub' try: self.assertEquals(rsa.save_key(f), 1) finally: try: os.remove(f) except IOError: pass def test_set_bn(self): rsa = RSA.load_pub_key(self.pubkey) assert m2.rsa_set_e(rsa.rsa, '\000\000\000\003\001\000\001') is None with self.assertRaises(RSA.RSAError): m2.rsa_set_e(rsa.rsa, '\000\000\000\003\001') def test_newpub(self): old = RSA.load_pub_key(self.pubkey) new = RSA.new_pub_key(old.pub()) self.assertTrue(new.check_key()) self.assertEqual(len(new), 1024) # aka 65537 aka 0xf4 self.assertEqual(new.e, '\000\000\000\003\001\000\001') def test_sign_and_verify(self): """ Testing signing and verifying digests """ algos = {'sha1': '', 'ripemd160': '', 'md5': ''} if m2.OPENSSL_VERSION_NUMBER >= 0x90800F: algos['sha224'] = '' algos['sha256'] = '' algos['sha384'] = '' algos['sha512'] = '' message = "This is the message string" digest = hashlib.sha1(message).digest() rsa = RSA.load_key(self.privkey) rsa2 = RSA.load_pub_key(self.pubkey) for algo in algos.keys(): signature = rsa.sign(digest, algo) # assert signature == algos[algo], # 'mismatched signature with algorithm %s: # signature=%s' % (algo, signature) verify = rsa2.verify(digest, signature, algo) assert verify == 1, 'verification failed with algorithm %s' % algo if m2.OPENSSL_VERSION_NUMBER >= 0x90708F: def test_sign_and_verify_rsassa_pss(self): """ Testing signing and verifying using rsassa_pss The maximum size of the salt has to decrease as the size of the digest increases because of the size of our test key limits it. """ message = "This is the message string" if sys.version_info < (2, 5): algos = {'sha1': (43, hashlib.sha1(message).digest()), 'md5': (47, hashlib.md5(message).digest())} else: import hashlib algos = {'sha1': 43} if not fips_mode: algos['md5'] = 47 algos['ripemd160'] = 43 if m2.OPENSSL_VERSION_NUMBER >= 0x90800F: algos['sha224'] = 35 algos['sha256'] = 31 algos['sha384'] = 15 algos['sha512'] = 0 for algo, salt_max in algos.iteritems(): h = hashlib.new(algo) h.update(message) digest = h.digest() algos[algo] = (salt_max, digest) rsa = RSA.load_key(self.privkey) rsa2 = RSA.load_pub_key(self.pubkey) for algo, (salt_max, digest) in algos.iteritems(): for salt_length in range(0, salt_max): signature = rsa.sign_rsassa_pss(digest, algo, salt_length) verify = rsa2.verify_rsassa_pss(digest, signature, algo, salt_length) self.assertEqual(verify, 1, 'verification failed with algorithm ' '%s salt length %d' % (algo, salt_length)) def test_sign_bad_method(self): """ Testing calling sign with an unsupported message digest algorithm """ rsa = RSA.load_key(self.privkey) #message = "This is the message string" digest = 'a' * 16 with self.assertRaises(ValueError): rsa.sign(digest, 'bad_digest_method') def test_verify_bad_method(self): """ Testing calling verify with an unsupported message digest algorithm """ rsa = RSA.load_key(self.privkey) #message = "This is the message string" digest = 'a' * 16 signature = rsa.sign(digest, 'sha1') with self.assertRaises(ValueError): rsa.verify(digest, signature, 'bad_digest_method') def test_verify_mismatched_algo(self): """ Testing verify to make sure it fails when we use a different message digest algorithm """ rsa = RSA.load_key(self.privkey) message = "This is the message string" digest = hashlib.sha1(message).digest() signature = rsa.sign(digest, 'sha1') #rsa2 = RSA.load_pub_key(self.pubkey) with self.assertRaises(RSA.RSAError): rsa.verify(digest, signature, 'md5') def test_sign_fail(self): """ Testing sign to make sure it fails when I give it a bogus digest. Looking at the RSA sign method I discovered that with the digest methods we use it has to be longer than a certain length. """ rsa = RSA.load_key(self.privkey) digest = """This string should be long enough to warrant an error in RSA_sign""" * 2 self.assertRaises(RSA.RSAError, rsa.sign, digest) def test_verify_bad_signature(self): """ Testing verify to make sure it fails when we use a bad signature """ rsa = RSA.load_key(self.privkey) message = "This is the message string" digest = hashlib.sha1(message).digest() other_message = "Abracadabra" other_digest = hashlib.sha1(other_message).digest() other_signature = rsa.sign(other_digest) with self.assertRaises(RSA.RSAError): rsa.verify(digest, other_signature) def suite(): return unittest.makeSuite(RSATestCase) if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_smime.py0000664000175000017500000002071212611255457020014 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.SMIME. Copyright (C) 2006 Open Source Applications Foundation. All Rights Reserved. """ try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import SMIME, BIO, Rand, X509, EVP class SMIMETestCase(unittest.TestCase): cleartext = 'some text to manipulate' def setUp(self): # XXX Ugly, but not sure what would be better self.signed = self.test_sign() self.encrypted = self.test_encrypt() def test_load_bad(self): s = SMIME.SMIME() self.assertRaises(EVP.EVPError, s.load_key, 'tests/signer.pem', 'tests/signer.pem') self.assertRaises(BIO.BIOError, SMIME.load_pkcs7, 'nosuchfile-dfg456') self.assertRaises(SMIME.PKCS7_Error, SMIME.load_pkcs7, 'tests/signer.pem') self.assertRaises(SMIME.PKCS7_Error, SMIME.load_pkcs7_bio, BIO.MemoryBuffer('no pkcs7')) self.assertRaises(SMIME.SMIME_Error, SMIME.smime_load_pkcs7, 'tests/signer.pem') self.assertRaises(SMIME.SMIME_Error, SMIME.smime_load_pkcs7_bio, BIO.MemoryBuffer('no pkcs7')) def test_crlf(self): self.assertEqual(SMIME.text_crlf('foobar'), 'Content-Type: text/plain\r\n\r\nfoobar') self.assertEqual(SMIME.text_crlf_bio(BIO.MemoryBuffer('foobar')).read(), 'Content-Type: text/plain\r\n\r\nfoobar') def test_sign(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(buf, SMIME.PKCS7_DETACHED) assert len(buf) == 0 assert p7.type() == SMIME.PKCS7_SIGNED, p7.type() assert isinstance(p7, SMIME.PKCS7), p7 out = BIO.MemoryBuffer() p7.write(out) buf = out.read() assert buf[:len('-----BEGIN PKCS7-----')] == '-----BEGIN PKCS7-----' buf = buf.strip() assert buf[-len('-----END PKCS7-----'):] == '-----END PKCS7-----', buf[-len('-----END PKCS7-----'):] assert len(buf) > len('-----END PKCS7-----') + len('-----BEGIN PKCS7-----') s.write(out, p7, BIO.MemoryBuffer(self.cleartext)) return out def test_store_load_info(self): st = X509.X509_Store() self.assertRaises(X509.X509Error, st.load_info, 'tests/ca.pem-typoname') self.assertEqual(st.load_info('tests/ca.pem'), 1) def test_verify(self): s = SMIME.SMIME() x509 = X509.load_cert('tests/signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('tests/ca.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7_bio(self.signed) assert isinstance(p7, SMIME.PKCS7), p7 v = s.verify(p7, data) assert v == self.cleartext t = p7.get0_signers(sk) assert len(t) == 1 assert t[0].as_pem() == x509.as_pem(), t[0].as_text() def test_verifyBad(self): s = SMIME.SMIME() x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('tests/recipient.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7_bio(self.signed) assert isinstance(p7, SMIME.PKCS7), p7 self.assertRaises(SMIME.PKCS7_Error, s.verify, p7) # Bad signer def test_encrypt(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) self.assertRaises(ValueError, SMIME.Cipher, 'nosuchcipher') s.set_cipher(SMIME.Cipher('des_ede3_cbc')) p7 = s.encrypt(buf) assert len(buf) == 0 assert p7.type() == SMIME.PKCS7_ENVELOPED, p7.type() assert isinstance(p7, SMIME.PKCS7), p7 out = BIO.MemoryBuffer() p7.write(out) buf = out.read() assert buf[:len('-----BEGIN PKCS7-----')] == '-----BEGIN PKCS7-----' buf = buf.strip() assert buf[-len('-----END PKCS7-----'):] == '-----END PKCS7-----' assert len(buf) > len('-----END PKCS7-----') + len('-----BEGIN PKCS7-----') s.write(out, p7) return out def test_decrypt(self): s = SMIME.SMIME() s.load_key('tests/recipient_key.pem', 'tests/recipient.pem') p7, data = SMIME.smime_load_pkcs7_bio(self.encrypted) assert isinstance(p7, SMIME.PKCS7), p7 self.assertRaises(SMIME.SMIME_Error, s.verify, p7) # No signer out = s.decrypt(p7) assert out == self.cleartext def test_decryptBad(self): s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7, data = SMIME.smime_load_pkcs7_bio(self.encrypted) assert isinstance(p7, SMIME.PKCS7), p7 self.assertRaises(SMIME.SMIME_Error, s.verify, p7) # No signer # Cannot decrypt: no recipient matches certificate self.assertRaises(SMIME.PKCS7_Error, s.decrypt, p7) def test_signEncryptDecryptVerify(self): # sign buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(buf) # encrypt x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp = BIO.MemoryBuffer() s.write(tmp, p7) p7 = s.encrypt(tmp) signedEncrypted = BIO.MemoryBuffer() s.write(signedEncrypted, p7) # decrypt s = SMIME.SMIME() s.load_key('tests/recipient_key.pem', 'tests/recipient.pem') p7, data = SMIME.smime_load_pkcs7_bio(signedEncrypted) out = s.decrypt(p7) # verify x509 = X509.load_cert('tests/signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('tests/ca.pem') s.set_x509_store(st) p7_bio = BIO.MemoryBuffer(out) p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) v = s.verify(p7) assert v == self.cleartext class WriteLoadTestCase(unittest.TestCase): def setUp(self): s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(BIO.MemoryBuffer('some text')) self.filename = 'tests/sig.p7' f = BIO.openfile(self.filename, 'wb') assert p7.write(f) == 1 f.close() p7 = s.sign(BIO.MemoryBuffer('some text'), SMIME.PKCS7_DETACHED) self.filenameSmime = 'tests/sig.p7s' f = BIO.openfile(self.filenameSmime, 'wb') assert s.write(f, p7, BIO.MemoryBuffer('some text')) == 1 f.close() def test_write_pkcs7_der(self): buf = BIO.MemoryBuffer() assert SMIME.load_pkcs7(self.filename).write_der(buf) == 1 s = buf.read() assert len(s) in (1188, 1204, 1243, 1263), len(s) def test_load_pkcs7(self): assert SMIME.load_pkcs7(self.filename).type() == SMIME.PKCS7_SIGNED def test_load_pkcs7_bio(self): f = open(self.filename, 'rb') buf = BIO.MemoryBuffer(f.read()) f.close() assert SMIME.load_pkcs7_bio(buf).type() == SMIME.PKCS7_SIGNED def test_load_smime(self): a, b = SMIME.smime_load_pkcs7(self.filenameSmime) assert isinstance(a, SMIME.PKCS7), a assert isinstance(b, BIO.BIO), b assert a.type() == SMIME.PKCS7_SIGNED def test_load_smime_bio(self): f = open(self.filenameSmime, 'rb') buf = BIO.MemoryBuffer(f.read()) f.close() a, b = SMIME.smime_load_pkcs7_bio(buf) assert isinstance(a, SMIME.PKCS7), a assert isinstance(b, BIO.BIO), b assert a.type() == SMIME.PKCS7_SIGNED def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SMIMETestCase)) suite.addTest(unittest.makeSuite(WriteLoadTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_ssl.py0000664000175000017500000012030612613361242017473 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.SSL. Copyright (c) 2000-2004 Ng Pheng Siong. All rights reserved. Copyright (c) 2009-2010 Heikki Toivonen. All rights reserved. """ """ TODO Server tests: - ??? Others: - ssl_dispatcher - SSLServer - ForkingSSLServer - ThreadingSSLServer """ import os import signal import socket import sys import tempfile import time try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import Err, Rand, SSL, m2 from fips import fips_mode from platform import linux_distribution srv_host = 'localhost' distro_string = linux_distribution(supported_dists=('redhat', 'fedora', 'debian'), full_distribution_name=False)[0] plat_fedora = distro_string in ['redhat', 'fedora'] plat_debian = distro_string in ['debian'] def allocate_srv_port(): s = socket.socket() try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((srv_host, 0)) (host, port) = s.getsockname() finally: s.close() return port def verify_cb_new_function(ok, store): try: assert not ok err = store.get_error() assert err in [m2.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, m2.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, m2.X509_V_ERR_CERT_UNTRUSTED, m2.X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE] assert store.get_error_depth() == 0 app_data = m2.x509_store_ctx_get_app_data(store.ctx) assert app_data x509 = store.get_current_cert() assert x509 stack = store.get1_chain() assert len(stack) == 1 assert stack[0].as_pem() == x509.as_pem() except AssertionError: # If we let exceptions propagate from here the # caller may see strange errors. This is cleaner. return 0 return 1 class VerifyCB: def __call__(self, ok, store): return verify_cb_new_function(ok, store) sleepTime = float(os.getenv('M2CRYPTO_TEST_SSL_SLEEP', 1.5)) def find_openssl(): if os.name == 'nt' or sys.platform == 'cygwin': openssl = 'openssl.exe' else: openssl = 'openssl' plist = os.environ['PATH'].split(os.pathsep) for p in plist: try: dir = os.listdir(p) if openssl in dir: return True except: pass return False class BaseSSLClientTestCase(unittest.TestCase): openssl_in_path = find_openssl() def start_server(self, args): if not self.openssl_in_path: raise Exception('openssl command not in PATH') pid = os.fork() if pid == 0: # openssl must be started in the tests directory for it # to find the .pem files os.chdir('tests') try: os.execvp('openssl', args) finally: os.chdir('..') else: time.sleep(sleepTime) return pid def stop_server(self, pid): os.kill(pid, signal.SIGTERM) os.waitpid(pid, 0) def http_get(self, s): s.send('GET / HTTP/1.0\n\n') resp = '' while 1: try: r = s.recv(4096) if not r: break except SSL.SSLError: # s_server throws an 'unexpected eof'... break resp = resp + r return resp def setUp(self): self.srv_host = srv_host self.srv_port = allocate_srv_port() self.srv_addr = (srv_host, self.srv_port) self.srv_url = 'https://%s:%s/' % (srv_host, self.srv_port) self.args = ['s_server', '-quiet', '-www', #'-cert', 'server.pem', Implicitly using this '-accept', str(self.srv_port)] class PassSSLClientTestCase(BaseSSLClientTestCase): def test_pass(self): pass class HttpslibSSLClientTestCase(BaseSSLClientTestCase): def test_HTTPSConnection(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib c = httpslib.HTTPSConnection(srv_host, self.srv_port) c.request('GET', '/') data = c.getresponse().read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_HTTPSConnection_resume_session(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.load_verify_locations(cafile='tests/ca.pem') ctx.load_cert('tests/x509.pem') ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 1) ctx.set_session_cache_mode(m2.SSL_SESS_CACHE_CLIENT) c = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx) c.request('GET', '/') ses = c.get_session() t = ses.as_text() data = c.getresponse().read() # Appearently closing connection here screws session; Ali Polatel? # c.close() ctx2 = SSL.Context() ctx2.load_verify_locations(cafile='tests/ca.pem') ctx2.load_cert('tests/x509.pem') ctx2.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 1) ctx2.set_session_cache_mode(m2.SSL_SESS_CACHE_CLIENT) c2 = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx2) c2.set_session(ses) c2.request('GET', '/') ses2 = c2.get_session() t2 = ses2.as_text() data = c2.getresponse().read() c.close() c2.close() assert t == t2, "Sessions did not match" finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_HTTPSConnection_secure_context(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') c = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx) c.request('GET', '/') data = c.getresponse().read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_HTTPSConnection_secure_context_fail(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/server.pem') c = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx) self.assertRaises(SSL.SSLError, c.request, 'GET', '/') c.close() finally: self.stop_server(pid) def test_HTTPS(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib c = httpslib.HTTPS(srv_host, self.srv_port) c.putrequest('GET', '/') c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') c.endheaders() err, msg, headers = c.getreply() assert err == 200, err f = c.getfile() data = f.read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_HTTPS_secure_context(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') c = httpslib.HTTPS(srv_host, self.srv_port, ssl_context=ctx) c.putrequest('GET', '/') c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') c.endheaders() err, msg, headers = c.getreply() assert err == 200, err f = c.getfile() data = f.read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_HTTPS_secure_context_fail(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/server.pem') c = httpslib.HTTPS(srv_host, self.srv_port, ssl_context=ctx) c.putrequest('GET', '/') c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') self.assertRaises(SSL.SSLError, c.endheaders) c.close() finally: self.stop_server(pid) def test_HTTPSConnection_illegalkeywordarg(self): from M2Crypto import httpslib self.assertRaises(ValueError, httpslib.HTTPSConnection, 'example.org', badKeyword=True) class MiscSSLClientTestCase(BaseSSLClientTestCase): def test_no_connection(self): ctx = SSL.Context() SSL.Connection(ctx) def test_server_simple(self): pid = self.start_server(self.args) try: self.assertRaises(ValueError, SSL.Context, 'tlsv5') ctx = SSL.Context() s = SSL.Connection(ctx) s.connect(self.srv_addr) self.assertRaises(ValueError, s.read, 0) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_server_simple_secure_context(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') s = SSL.Connection(ctx) s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_server_simple_secure_context_fail(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/server.pem') s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_server_simple_timeouts(self): pid = self.start_server(self.args) try: self.assertRaises(ValueError, SSL.Context, 'tlsv5') ctx = SSL.Context() s = SSL.Connection(ctx) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() assert r.sec == 0, r.sec assert r.microsec == 0, r.microsec assert w.sec == 0, w.sec assert w.microsec == 0, w.microsec s.set_socket_read_timeout(SSL.timeout()) s.set_socket_write_timeout(SSL.timeout(909, 9)) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() assert r.sec == 600, r.sec assert r.microsec == 0, r.microsec assert w.sec == 909, w.sec #assert w.microsec == 9, w.microsec XXX 4000 s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) # TLS is required in FIPS mode @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") def test_tls1_nok(self): self.args.append('-no_tls1') pid = self.start_server(self.args) try: ctx = SSL.Context('tlsv1') s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: self.assertIn(e[0], ['wrong version number', 'unexpected eof']) s.close() finally: self.stop_server(pid) def test_tls1_ok(self): self.args.append('-tls1') pid = self.start_server(self.args) try: ctx = SSL.Context('tlsv1') s = SSL.Connection(ctx) s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) # TLS is required in FIPS mode @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") @unittest.skipIf(plat_debian, "Debian distros don't allow weak ciphers") def test_sslv23_weak_crypto(self): self.args = self.args + ['-ssl2'] pid = self.start_server(self.args) try: ctx = SSL.Context('sslv23', weak_crypto=1) s = SSL.Connection(ctx) # SSLv2 ciphers disabled by default in newer OpenSSL if plat_fedora and m2.OPENSSL_VERSION_NUMBER < 0x10000000: s.connect(self.srv_addr) self.assertEqual(s.get_version(), 'SSLv2') else: self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() except Exception as ex: print('Caught exception %s' % ex) raise finally: self.stop_server(pid) def test_cipher_mismatch(self): self.args = self.args + ['-cipher', 'AES256-SHA'] pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) s.set_cipher_list('AES128-SHA') try: s.connect(self.srv_addr) except SSL.SSLError, e: self.assertEqual(e[0], 'sslv3 alert handshake failure') s.close() finally: self.stop_server(pid) def test_no_such_cipher(self): self.args = self.args + ['-cipher', 'AES128-SHA'] pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) s.set_cipher_list('EXP-RC2-MD5') try: s.connect(self.srv_addr) except SSL.SSLError, e: self.assertEqual(e[0], 'no ciphers available') s.close() finally: self.stop_server(pid) # TLS is required in FIPS mode @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") def test_no_weak_cipher(self): self.args = self.args + ['-cipher', 'EXP'] pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) with self.assertRaisesRegexp(SSL.SSLError, 'sslv3 alert handshake failure'): s.connect(self.srv_addr) finally: s.close() self.stop_server(pid) # TLS is required in FIPS mode @unittest.skipIf(fips_mode, "Can't be run in FIPS mode") @unittest.skipIf(plat_debian, "Debian distros don't allow weak ciphers") def test_use_weak_cipher(self): self.args = self.args + ['-cipher', 'EXP'] pid = self.start_server(self.args) try: ctx = SSL.Context(weak_crypto=1) s = SSL.Connection(ctx) s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_cipher_ok(self): self.args = self.args + ['-cipher', 'AES128-SHA'] pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) s.set_cipher_list('AES128-SHA') s.connect(self.srv_addr) data = self.http_get(s) assert s.get_cipher().name() == 'AES128-SHA', s.get_cipher().name() cipher_stack = s.get_ciphers() assert cipher_stack[0].name() == 'AES128-SHA', \ cipher_stack[0].name() self.assertRaises(IndexError, cipher_stack.__getitem__, 2) # For some reason there are 2 entries in the stack #assert len(cipher_stack) == 1, len(cipher_stack) assert s.get_cipher_list() == 'AES128-SHA', s.get_cipher_list() # Test Cipher_Stack iterator i = 0 for cipher in cipher_stack: i += 1 assert cipher.name() == 'AES128-SHA', '"%s"' % cipher.name() self.assertEqual('AES128-SHA-128', str(cipher)) # For some reason there are 2 entries in the stack #assert i == 1, i self.assertEqual(i, len(cipher_stack)) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def verify_cb_new(self, ok, store): return verify_cb_new_function(ok, store) def test_verify_cb_new(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, self.verify_cb_new) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cb_new_class(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, VerifyCB()) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cb_new_function(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, verify_cb_new_function) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cb_lambda(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, lambda ok, store: 1) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def verify_cb_exception(self, ok, store): self.fail('We should fail verification') def test_verify_cb_exception(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, self.verify_cb_exception) s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_verify_cb_not_callable(self): ctx = SSL.Context() self.assertRaises(TypeError, ctx.set_verify, SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, 1) def test_verify_cb_wrong_callable(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, lambda _: '') s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def verify_cb_old(self, ctx_ptr, x509_ptr, err, depth, ok): try: from M2Crypto import X509 assert not ok assert err == m2.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT or \ err == m2.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY or \ err == m2.X509_V_ERR_CERT_UNTRUSTED or \ err == m2.X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE assert m2.ssl_ctx_get_cert_store(ctx_ptr) assert X509.X509(x509_ptr).as_pem() except AssertionError: # If we let exceptions propagate from here the # caller may see strange errors. This is cleaner. return 0 return 1 def test_verify_cb_old(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, self.verify_cb_old) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_allow_unknown_old(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, SSL.cb.ssl_verify_callback) ctx.set_allow_unknown_ca(1) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_allow_unknown_new(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, SSL.cb.ssl_verify_callback_allow_unknown_ca) s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cert(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cert_fail(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/server.pem') s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_verify_cert_mutual_auth(self): self.args.extend(['-Verify', '2', '-CAfile', 'ca.pem']) pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') ctx.load_cert('tests/x509.pem') s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cert_mutual_auth_servernbio(self): self.args.extend(['-Verify', '2', '-CAfile', 'ca.pem', '-nbio']) pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') ctx.load_cert('tests/x509.pem') s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_verify_cert_mutual_auth_fail(self): self.args.extend(['-Verify', '2', '-CAfile', 'ca.pem']) pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_verify_nocert_fail(self): self.args.extend(['-nocert']) pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') s = SSL.Connection(ctx) self.assertRaises(SSL.SSLError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_blocking0(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) s.setblocking(0) self.assertRaises(Exception, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_blocking1(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) s.setblocking(1) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_makefile(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e bio = s.makefile('rw') #s.close() # XXX bug 6628? bio.write('GET / HTTP/1.0\n\n') bio.flush() data = bio.read() bio.close() s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_makefile_err(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) try: s.connect(self.srv_addr) except SSL.SSLError, e: assert 0, e f = s.makefile() data = self.http_get(s) s.close() del f del s err_code = Err.peek_error_code() assert not err_code, 'Unexpected error: %s' % err_code err = Err.get_error() assert not err, 'Unexpected error: %s' % err finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_info_callback(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_info_callback() s = SSL.Connection(ctx) s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) class UrllibSSLClientTestCase(BaseSSLClientTestCase): def test_urllib(self): pid = self.start_server(self.args) try: from M2Crypto import m2urllib url = m2urllib.FancyURLopener() url.addheader('Connection', 'close') u = url.open('https://%s:%s/' % (srv_host, self.srv_port)) data = u.read() u.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) # XXX Don't actually know how to use m2urllib safely! #def test_urllib_secure_context(self): #def test_urllib_secure_context_fail(self): # XXX Don't actually know how to use m2urllib safely! #def test_urllib_safe_context(self): #def test_urllib_safe_context_fail(self): class Urllib2SSLClientTestCase(BaseSSLClientTestCase): if sys.version_info >= (2, 4): def test_urllib2(self): pid = self.start_server(self.args) try: from M2Crypto import m2urllib2 opener = m2urllib2.build_opener() opener.addheaders = [('Connection', 'close')] u = opener.open('https://%s:%s/' % (srv_host, self.srv_port)) data = u.read() u.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_urllib2_secure_context(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify( SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') from M2Crypto import m2urllib2 opener = m2urllib2.build_opener(ctx) opener.addheaders = [('Connection', 'close')] u = opener.open('https://%s:%s/' % (srv_host, self.srv_port)) data = u.read() u.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_urllib2_secure_context_fail(self): pid = self.start_server(self.args) try: ctx = SSL.Context() ctx.set_verify( SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/server.pem') from M2Crypto import m2urllib2 opener = m2urllib2.build_opener(ctx) opener.addheaders = [('Connection', 'close')] self.assertRaises(SSL.SSLError, opener.open, 'https://%s:%s/' % (srv_host, self.srv_port)) finally: self.stop_server(pid) def test_z_urllib2_opener(self): pid = self.start_server(self.args) try: ctx = SSL.Context() from M2Crypto import m2urllib2 opener = m2urllib2.build_opener( ctx, m2urllib2.HTTPBasicAuthHandler()) m2urllib2.install_opener(opener) req = m2urllib2.Request('https://%s:%s/' % (srv_host, self.srv_port)) u = m2urllib2.urlopen(req) data = u.read() u.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_urllib2_opener_handlers(self): ctx = SSL.Context() from M2Crypto import m2urllib2 m2urllib2.build_opener(ctx, m2urllib2.HTTPBasicAuthHandler()) def test_urllib2_leak(self): pid = self.start_server(self.args) try: import gc from M2Crypto import m2urllib2 o = m2urllib2.build_opener() r = o.open('https://%s:%s/' % (srv_host, self.srv_port)) s = [r.fp._sock.fp] r.close() self.assertEqual(len(gc.get_referrers(s[0])), 1) finally: self.stop_server(pid) class TwistedSSLClientTestCase(BaseSSLClientTestCase): def test_timeout(self): pid = self.start_server(self.args) try: ctx = SSL.Context() s = SSL.Connection(ctx) # Just a really small number so we can timeout s.settimeout(0.000000000000000000000000000001) self.assertRaises(SSL.SSLTimeoutError, s.connect, self.srv_addr) s.close() finally: self.stop_server(pid) def test_makefile_timeout(self): # httpslib uses makefile to read the response pid = self.start_server(self.args) try: from M2Crypto import httpslib c = httpslib.HTTPS(srv_host, self.srv_port) c.putrequest('GET', '/') c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') c.endheaders() c._conn.sock.settimeout(100) err, msg, headers = c.getreply() assert err == 200, err f = c.getfile() data = f.read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data) def test_makefile_timeout_fires(self): # This is convoluted because (openssl s_server -www) starts # writing the response as soon as it receives the first line of # the request, so it's possible for it to send the response # before the request is sent and there would be no timeout. So, # let the server spend time reading from an empty pipe FIFO_NAME = 'test_makefile_timeout_fires_fifo' # noqa os.mkfifo('tests/' + FIFO_NAME) pipe_pid = os.fork() try: if pipe_pid == 0: try: f = open('tests/' + FIFO_NAME, 'w') try: time.sleep(sleepTime + 1) f.write('Content\n') finally: f.close() finally: os._exit(0) self.args[self.args.index('-www')] = '-WWW' pid = self.start_server(self.args) try: from M2Crypto import httpslib c = httpslib.HTTPS(srv_host, self.srv_port) c.putrequest('GET', '/' + FIFO_NAME) c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') c.endheaders() c._conn.sock.settimeout(0.0000000001) self.assertRaises(socket.timeout, c.getreply) c.close() finally: self.stop_server(pid) finally: os.kill(pipe_pid, signal.SIGTERM) os.waitpid(pipe_pid, 0) os.unlink('tests/' + FIFO_NAME) def test_twisted_wrapper(self): # Test only when twisted and ZopeInterfaces are present try: from twisted.internet.protocol import ClientFactory from twisted.protocols.basic import LineReceiver from twisted.internet import reactor import M2Crypto.SSL.TwistedProtocolWrapper as wrapper except ImportError: import warnings warnings.warn( 'Skipping twisted wrapper test because twisted not found') return class EchoClient(LineReceiver): def connectionMade(self): self.sendLine('GET / HTTP/1.0\n\n') def lineReceived(self, line): global twisted_data twisted_data += line class EchoClientFactory(ClientFactory): protocol = EchoClient def clientConnectionFailed(self, connector, reason): reactor.stop() assert 0, reason def clientConnectionLost(self, connector, reason): reactor.stop() pid = self.start_server(self.args) class ContextFactory: def getContext(self): return SSL.Context() try: global twisted_data twisted_data = '' context_factory = ContextFactory() factory = EchoClientFactory() wrapper.connectSSL(srv_host, self.srv_port, factory, context_factory) # This will block until reactor.stop() is called reactor.run() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', twisted_data) twisted_data = '' class XmlRpcLibTestCase(unittest.TestCase): def test_lib(self): from M2Crypto import m2xmlrpclib m2xmlrpclib.SSL_Transport() # XXX need server to test against class FtpsLibTestCase(unittest.TestCase): def test_lib(self): from M2Crypto import ftpslib ftpslib.FTP_TLS() # XXX need server to test against class SessionTestCase(unittest.TestCase): def test_session_load_bad(self): self.assertRaises(SSL.SSLError, SSL.Session.load_session, 'tests/signer.pem') class FtpslibTestCase(unittest.TestCase): def test_26_compat(self): from M2Crypto import ftpslib f = ftpslib.FTP_TLS() # 2.6 used to raise AttributeError: self.assertRaises(socket.gaierror, f.connect, 'no-such-host-dfgHJK56789', 990) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SessionTestCase)) suite.addTest(unittest.makeSuite(XmlRpcLibTestCase)) suite.addTest(unittest.makeSuite(FtpsLibTestCase)) suite.addTest(unittest.makeSuite(PassSSLClientTestCase)) suite.addTest(unittest.makeSuite(HttpslibSSLClientTestCase)) suite.addTest(unittest.makeSuite(UrllibSSLClientTestCase)) suite.addTest(unittest.makeSuite(Urllib2SSLClientTestCase)) suite.addTest(unittest.makeSuite(MiscSSLClientTestCase)) suite.addTest(unittest.makeSuite(FtpslibTestCase)) try: import M2Crypto.SSL.TwistedProtocolWrapper as wrapper # noqa suite.addTest(unittest.makeSuite(TwistedSSLClientTestCase)) except ImportError: pass return suite def zap_servers(): s = 's_server' fn = tempfile.mktemp() cmd = 'ps | egrep %s > %s' % (s, fn) os.system(cmd) f = open(fn) while 1: ps = f.readline() if not ps: break chunk = ps.split() pid, cmd = chunk[0], chunk[4] if cmd == s: os.kill(int(pid), signal.SIGTERM) f.close() os.unlink(fn) if __name__ == '__main__': report_leaks = 0 if report_leaks: import gc gc.enable() gc.set_debug(gc.DEBUG_LEAK & ~gc.DEBUG_SAVEALL) try: Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') finally: zap_servers() if report_leaks: import alltests alltests.dump_garbage() M2Crypto-0.22.6rc4/tests/test_ssl_offline.py0000664000175000017500000000354012611255457021205 0ustar matejmatej00000000000000"""Unit tests for M2Crypto.SSL offline parts Copyright (C) 2006 Open Source Applications Foundation. All Rights Reserved. Copyright (C) 2009-2010 Heikki Toivonen. All Rights Reserved. """ import doctest try: import unittest2 as unittest except ImportError: import unittest from M2Crypto.SSL import Checker from M2Crypto import X509 from M2Crypto import SSL from test_ssl import srv_host class CheckerTestCase(unittest.TestCase): def test_checker(self): check = Checker.Checker(host=srv_host, peerCertHash='6D5C51BF6C90686A87E015A07731B252B7638D93') x509 = X509.load_cert('tests/server.pem') assert check(x509, srv_host) self.assertRaises(Checker.WrongHost, check, x509, 'example.com') doctest.testmod(Checker) class ContextTestCase(unittest.TestCase): def test_ctx_load_verify_locations(self): ctx = SSL.Context() self.assertRaises(ValueError, ctx.load_verify_locations, None, None) def test_map(self): from M2Crypto.SSL.Context import map, _ctxmap assert isinstance(map(), _ctxmap) ctx = SSL.Context() assert map() ctx.close() assert map() is _ctxmap.singleton def test_certstore(self): ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') ctx.load_cert('tests/x509.pem') store = ctx.get_cert_store() assert isinstance(store, X509.X509_Store) def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(CheckerTestCase)) suite.addTest(unittest.makeSuite(ContextTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_ssl_win.py0000664000175000017500000000401112611255457020352 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.SSL. Win32 version - requires Mark Hammond's Win32 extensions and openssl.exe on your PATH. Copyright (c) 2000-2001 Ng Pheng Siong. All rights reserved.""" import os, os.path, string, time try: import unittest2 as unittest except ImportError: import unittest try: import win32process except ImportError: win32process = None if win32process: from M2Crypto import Rand, SSL import test_ssl def find_openssl(): plist = os.environ['PATH'].split(';') for p in plist: try: dir = os.listdir(p) if 'openssl.exe' in dir: return os.path.join(p, 'openssl.exe') except WindowsError: pass return None srv_host = 'localhost' srv_port = 64000 class SSLWinClientTestCase(test_ssl.SSLClientTestCase): startupinfo = win32process.STARTUPINFO() openssl = find_openssl() def start_server(self, args): # openssl must be started in the tests directory for it # to find the .pem files os.chdir('tests') try: hproc, hthread, pid, tid = win32process.CreateProcess(self.openssl, string.join(args), None, None, 0, win32process.DETACHED_PROCESS, None, None, self.startupinfo) finally: os.chdir('..') time.sleep(0.3) return hproc def stop_server(self, hproc): win32process.TerminateProcess(hproc, 0) def suite(): return unittest.makeSuite(SSLWinClientTestCase) def zap_servers(): pass if __name__ == '__main__': try: if find_openssl() is not None: Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') finally: zap_servers() M2Crypto-0.22.6rc4/tests/test_threading.py0000664000175000017500000000165512611255457020654 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.threading. Copyright (C) 2007 Open Source Applications Foundation. All Rights Reserved. """ try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import threading as m2threading, Rand class ThreadingTestCase(unittest.TestCase): def setUp(self): m2threading.init() def tearDown(self): m2threading.cleanup() def test_pass(self): pass def test_multiInitCleanup(self): m2threading.init() m2threading.init() m2threading.cleanup() m2threading.cleanup() m2threading.init() m2threading.cleanup() def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ThreadingTestCase)) return suite if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/test_x509.py0000664000175000017500000006112012613276364017407 0ustar matejmatej00000000000000#!/usr/bin/env python """Unit tests for M2Crypto.X509. Contributed by Toby Allsopp under M2Crypto's license. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004-2005 OSAF. All Rights Reserved. Author: Heikki Toivonen """ import base64 import os import time try: import unittest2 as unittest except ImportError: import unittest from M2Crypto import ASN1, BIO, EVP, RSA, Rand, X509, m2 class X509TestCase(unittest.TestCase): def callback(self, *args): pass def mkreq(self, bits, ca=0): pk = EVP.PKey() x = X509.Request() rsa = RSA.gen_key(bits, 65537, self.callback) pk.assign_rsa(rsa) rsa = None # should not be freed here x.set_pubkey(pk) name = x.get_subject() name.C = "UK" name.CN = "OpenSSL Group" if not ca: ext1 = X509.new_extension('subjectAltName', 'DNS:foobar.example.com') ext2 = X509.new_extension('nsComment', 'Hello there') extstack = X509.X509_Extension_Stack() extstack.push(ext1) extstack.push(ext2) x.add_extensions(extstack) with self.assertRaises(ValueError): x.sign(pk, 'sha513') x.sign(pk, 'sha1') self.assertTrue(x.verify(pk)) pk2 = x.get_pubkey() self.assertTrue(x.verify(pk2)) return x, pk def test_ext(self): with self.assertRaises(ValueError): X509.new_extension('subjectKeyIdentifier', 'hash') ext = X509.new_extension('subjectAltName', 'DNS:foobar.example.com') self.assertEqual(ext.get_value(), 'DNS:foobar.example.com') self.assertEqual(ext.get_value(indent=2), ' DNS:foobar.example.com') self.assertEqual(ext.get_value(flag=m2.X509V3_EXT_PARSE_UNKNOWN), 'DNS:foobar.example.com') def test_extstack(self): # new ext1 = X509.new_extension('subjectAltName', 'DNS:foobar.example.com') ext2 = X509.new_extension('nsComment', 'Hello there') extstack = X509.X509_Extension_Stack() # push extstack.push(ext1) extstack.push(ext2) self.assertEqual(extstack[1].get_name(), 'nsComment') self.assertEqual(len(extstack), 2) # iterator i = 0 for e in extstack: i += 1 self.assertGreater(len(e.get_name()), 0) self.assertEqual(i, 2) # pop ext3 = extstack.pop() self.assertEqual(len(extstack), 1) self.assertEqual(extstack[0].get_name(), 'subjectAltName') extstack.push(ext3) self.assertEqual(len(extstack), 2) self.assertEqual(extstack[1].get_name(), 'nsComment') self.assertIsNotNone(extstack.pop()) self.assertIsNotNone(extstack.pop()) self.assertIsNone(extstack.pop()) def test_x509_name(self): n = X509.X509_Name() # It seems this actually needs to be a real 2 letter country code n.C = 'US' self.assertEqual(n.C, 'US') n.SP = 'State or Province' self.assertEqual(n.SP, 'State or Province') n.L = 'locality name' self.assertEqual(n.L, 'locality name') # Yes, 'orhanization' is a typo, I know it and you're smart. # However, fixing this typo would break later hashes. # I don't think it is worthy of troubles. n.O = 'orhanization name' self.assertEqual(n.O, 'orhanization name') n.OU = 'org unit' self.assertEqual(n.OU, 'org unit') n.CN = 'common name' self.assertEqual(n.CN, 'common name') n.Email = 'bob@example.com' self.assertEqual(n.Email, 'bob@example.com') n.serialNumber = '1234' self.assertEqual(n.serialNumber, '1234') n.SN = 'surname' self.assertEqual(n.SN, 'surname') n.GN = 'given name' self.assertEqual(n.GN, 'given name') self.assertEqual(n.as_text(), 'C=US, ST=State or Province, ' + 'L=locality name, O=orhanization name, ' + 'OU=org unit, CN=common ' + 'name/emailAddress=bob@example.com' + '/serialNumber=1234, ' + 'SN=surname, GN=given name') self.assertEqual(len(n), 10, 'X509_Name has inappropriate length %d ' % len(n)) n.givenName = 'name given' self.assertEqual(n.GN, 'given name') # Just gets the first self.assertEqual(n.as_text(), 'C=US, ST=State or Province, ' + 'L=locality name, O=orhanization name, ' + 'OU=org unit, ' + 'CN=common name/emailAddress=bob@example.com' + '/serialNumber=1234, ' + 'SN=surname, GN=given name, GN=name given') self.assertEqual(len(n), 11, 'After adding one more attribute X509_Name should ' + 'have 11 and not %d attributes.' % len(n)) n.add_entry_by_txt(field="CN", type=ASN1.MBSTRING_ASC, entry="Proxy", len=-1, loc=-1, set=0) self.assertEqual(len(n), 12, 'After adding one more attribute X509_Name should ' + 'have 12 and not %d attributes.' % len(n)) self.assertEqual(n.entry_count(), 12, n.entry_count()) self.assertEqual(n.as_text(), 'C=US, ST=State or Province, ' + 'L=locality name, O=orhanization name, ' + 'OU=org unit, ' + 'CN=common name/emailAddress=bob@example.com' + '/serialNumber=1234, ' + 'SN=surname, GN=given name, GN=name given, ' + 'CN=Proxy') self.assertRaises(AttributeError, n.__getattr__, 'foobar') n.foobar = 1 self.assertEqual(n.foobar, 1) # X509_Name_Entry tests l = 0 for entry in n: self.assertIsInstance(entry, X509.X509_Name_Entry) self.assertIsInstance(entry.get_object(), ASN1.ASN1_Object) self.assertIsInstance(entry.get_data(), ASN1.ASN1_String) l += 1 self.assertEqual(l, 12, l) l = 0 for cn in n.get_entries_by_nid(m2.NID_commonName): self.assertIsInstance(cn, X509.X509_Name_Entry) self.assertIsInstance(cn.get_object(), ASN1.ASN1_Object) data = cn.get_data() self.assertIsInstance(data, ASN1.ASN1_String) t = data.as_text() self.assertIn(t, ("common name", "Proxy",)) l += 1 self.assertEqual(l, 2, 'X509_Name has %d commonName entries instead ' 'of expected 2' % l) # The target list is not deleted when the loop is finished # https://docs.python.org/2.7/reference\ # /compound_stmts.html#the-for-statement # so this checks what are the attributes of the last value of # ``cn`` variable. cn.set_data("Hello There!") self.assertEqual(cn.get_data().as_text(), "Hello There!") # OpenSSL 1.0.1h switched from encoding strings as PRINTABLESTRING (the # first hash value) to UTF8STRING (the second one) self.assertIn(n.as_hash(), (1697185131, 1370641112), 'Unexpected value of the X509_Name hash %s' % n.as_hash()) self.assertRaises(IndexError, lambda: n[100]) self.assertIsNotNone(n[10]) def test_mkreq(self): (req, _) = self.mkreq(1024) req.save_pem('tests/tmp_request.pem') req2 = X509.load_request('tests/tmp_request.pem') os.remove('tests/tmp_request.pem') req.save('tests/tmp_request.pem') req3 = X509.load_request('tests/tmp_request.pem') os.remove('tests/tmp_request.pem') req.save('tests/tmp_request.der', format=X509.FORMAT_DER) req4 = X509.load_request('tests/tmp_request.der', format=X509.FORMAT_DER) os.remove('tests/tmp_request.der') self.assertEqual(req.as_pem(), req2.as_pem()) self.assertEqual(req.as_text(), req2.as_text()) self.assertEqual(req.as_der(), req2.as_der()) self.assertEqual(req.as_pem(), req3.as_pem()) self.assertEqual(req.as_text(), req3.as_text()) self.assertEqual(req.as_der(), req3.as_der()) self.assertEqual(req.as_pem(), req4.as_pem()) self.assertEqual(req.as_text(), req4.as_text()) self.assertEqual(req.as_der(), req4.as_der()) self.assertEqual(req.get_version(), 0) req.set_version(1) self.assertEqual(req.get_version(), 1) req.set_version(0) self.assertEqual(req.get_version(), 0) def test_mkcert(self): req, pk = self.mkreq(1024) pkey = req.get_pubkey() self.assertTrue(req.verify(pkey)) sub = req.get_subject() self.assertEqual(len(sub), 2, 'Subject should be long 2 items not %d' % len(sub)) cert = X509.X509() cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) t = long(time.time()) + time.timezone now = ASN1.ASN1_UTCTIME() now.set_time(t) now_plus_year = ASN1.ASN1_UTCTIME() now_plus_year.set_time(t + 60 * 60 * 24 * 365) cert.set_not_before(now) cert.set_not_after(now_plus_year) self.assertEqual(str(cert.get_not_before()), str(now)) self.assertEqual(str(cert.get_not_after()), str(now_plus_year)) issuer = X509.X509_Name() issuer.CN = 'The Issuer Monkey' issuer.O = 'The Organization Otherwise Known as My CA, Inc.' cert.set_issuer(issuer) cert.set_pubkey(pkey) cert.set_pubkey(cert.get_pubkey()) # Make sure get/set work ext = X509.new_extension('subjectAltName', 'DNS:foobar.example.com') ext.set_critical(0) self.assertEqual(ext.get_critical(), 0) cert.add_ext(ext) cert.sign(pk, 'sha1') with self.assertRaises(ValueError): cert.sign(pk, 'nosuchalgo') self.assertTrue(cert.get_ext('subjectAltName').get_name(), 'subjectAltName') self.assertTrue(cert.get_ext_at(0).get_name(), 'subjectAltName') self.assertTrue(cert.get_ext_at(0).get_value(), 'DNS:foobar.example.com') self.assertEqual(cert.get_ext_count(), 1, 'Certificate should have now 1 extension not %d' % cert.get_ext_count()) with self.assertRaises(IndexError): cert.get_ext_at(1) self.assertTrue(cert.verify()) self.assertTrue(cert.verify(pkey)) self.assertTrue(cert.verify(cert.get_pubkey())) self.assertEqual(cert.get_version(), 2) self.assertEqual(cert.get_serial_number(), 1) self.assertEqual(cert.get_issuer().CN, 'The Issuer Monkey') if m2.OPENSSL_VERSION_NUMBER >= 0x90800f: self.assertFalse(cert.check_ca()) self.assertFalse(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 1)) self.assertFalse(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER, 1)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 0)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER, 0)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_ANY, 0)) else: with self.assertRaises(AttributeError): cert.check_ca() def mkcacert(self): req, pk = self.mkreq(1024, ca=1) pkey = req.get_pubkey() sub = req.get_subject() cert = X509.X509() cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) t = long(time.time()) + time.timezone now = ASN1.ASN1_UTCTIME() now.set_time(t) now_plus_year = ASN1.ASN1_UTCTIME() now_plus_year.set_time(t + 60 * 60 * 24 * 365) cert.set_not_before(now) cert.set_not_after(now_plus_year) issuer = X509.X509_Name() issuer.C = "UK" issuer.CN = "OpenSSL Group" cert.set_issuer(issuer) cert.set_pubkey(pkey) ext = X509.new_extension('basicConstraints', 'CA:TRUE') cert.add_ext(ext) cert.sign(pk, 'sha1') if m2.OPENSSL_VERSION_NUMBER >= 0x0090800fL: self.assertTrue(cert.check_ca()) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 1)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER, 1)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_ANY, 1)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 0)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER, 0)) self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_ANY, 0)) else: with self.assertRaises(AttributeError): cert.check_ca() return cert, pk, pkey def test_mkcacert(self): cacert, _, pkey = self.mkcacert() self.assertTrue(cacert.verify(pkey)) def test_mkproxycert(self): cacert, pk1, _ = self.mkcacert() end_entity_cert_req, pk2 = self.mkreq(1024) end_entity_cert = self.make_eecert(cacert) end_entity_cert.set_subject(end_entity_cert_req.get_subject()) end_entity_cert.set_pubkey(end_entity_cert_req.get_pubkey()) end_entity_cert.sign(pk1, 'sha1') proxycert = self.make_proxycert(end_entity_cert) proxycert.sign(pk2, 'sha1') self.assertTrue(proxycert.verify(pk2)) self.assertEqual(proxycert.get_ext_at(0).get_name(), 'proxyCertInfo') self.assertEqual(proxycert.get_ext_at(0).get_value(), 'Path Length Constraint: infinite\n' + 'Policy Language: Inherit all\n') self.assertEqual(proxycert.get_ext_count(), 1, proxycert.get_ext_count()) self.assertEqual(proxycert.get_subject().as_text(), 'C=UK, CN=OpenSSL Group, CN=Proxy') self.assertEqual( proxycert.get_subject().as_text(indent=2, flags=m2.XN_FLAG_RFC2253), ' CN=Proxy,CN=OpenSSL Group,C=UK') def make_eecert(self, cacert): eecert = X509.X509() eecert.set_serial_number(2) eecert.set_version(2) t = long(time.time()) + time.timezone now = ASN1.ASN1_UTCTIME() now.set_time(t) now_plus_year = ASN1.ASN1_UTCTIME() now_plus_year.set_time(t + 60 * 60 * 24 * 365) eecert.set_not_before(now) eecert.set_not_after(now_plus_year) eecert.set_issuer(cacert.get_subject()) return eecert def make_proxycert(self, eecert): proxycert = X509.X509() pk2 = EVP.PKey() proxykey = RSA.gen_key(1024, 65537, self.callback) pk2.assign_rsa(proxykey) proxycert.set_pubkey(pk2) proxycert.set_version(2) not_before = ASN1.ASN1_UTCTIME() not_after = ASN1.ASN1_UTCTIME() not_before.set_time(int(time.time())) offset = 12 * 3600 not_after.set_time(int(time.time()) + offset) proxycert.set_not_before(not_before) proxycert.set_not_after(not_after) proxycert.set_issuer_name(eecert.get_subject()) proxycert.set_serial_number(12345678) issuer_name_string = eecert.get_subject().as_text() seq = issuer_name_string.split(",") subject_name = X509.X509_Name() for entry in seq: l = entry.split("=") subject_name.add_entry_by_txt(field=l[0].strip(), type=ASN1.MBSTRING_ASC, entry=l[1], len=-1, loc=-1, set=0) subject_name.add_entry_by_txt(field="CN", type=ASN1.MBSTRING_ASC, entry="Proxy", len=-1, loc=-1, set=0) proxycert.set_subject_name(subject_name) # XXX leaks 8 bytes pci_ext = X509.new_extension("proxyCertInfo", "critical,language:Inherit all", 1) proxycert.add_ext(pci_ext) return proxycert def test_fingerprint(self): x509 = X509.load_cert('tests/x509.pem') fp = x509.get_fingerprint('sha1') expected = 'B2522F9B4F6F2461475D0C6267911537E738494F' self.assertEqual(fp, expected) def test_load_der_string(self): f = open('tests/x509.der', 'rb') x509 = X509.load_cert_der_string(''.join(f.readlines())) fp = x509.get_fingerprint('sha1') expected = 'B2522F9B4F6F2461475D0C6267911537E738494F' self.assertEqual(fp, expected) def test_save_der_string(self): x509 = X509.load_cert('tests/x509.pem') s = x509.as_der() f = open('tests/x509.der', 'rb') s2 = f.read() f.close() self.assertEqual(s, s2) def test_load(self): x509 = X509.load_cert('tests/x509.pem') x5092 = X509.load_cert('tests/x509.der', format=X509.FORMAT_DER) self.assertEqual(x509.as_text(), x5092.as_text()) self.assertEqual(x509.as_pem(), x5092.as_pem()) self.assertEqual(x509.as_der(), x5092.as_der()) return def test_load_bio(self): bio = BIO.openfile('tests/x509.pem') bio2 = BIO.openfile('tests/x509.der') x509 = X509.load_cert_bio(bio) x5092 = X509.load_cert_bio(bio2, format=X509.FORMAT_DER) with self.assertRaises(ValueError): X509.load_cert_bio(bio2, format=45678) self.assertEqual(x509.as_text(), x5092.as_text()) self.assertEqual(x509.as_pem(), x5092.as_pem()) self.assertEqual(x509.as_der(), x5092.as_der()) def test_load_string(self): f = open('tests/x509.pem') s = f.read() f.close() f2 = open('tests/x509.der', 'rb') s2 = f2.read() f2.close() x509 = X509.load_cert_string(s) x5092 = X509.load_cert_string(s2, X509.FORMAT_DER) self.assertEqual(x509.as_text(), x5092.as_text()) self.assertEqual(x509.as_pem(), x5092.as_pem()) self.assertEqual(x509.as_der(), x5092.as_der()) def test_load_request_bio(self): (req, _) = self.mkreq(1024) r1 = X509.load_request_der_string(req.as_der()) r2 = X509.load_request_string(req.as_der(), X509.FORMAT_DER) r3 = X509.load_request_string(req.as_pem(), X509.FORMAT_PEM) r4 = X509.load_request_bio(BIO.MemoryBuffer(req.as_der()), X509.FORMAT_DER) r5 = X509.load_request_bio(BIO.MemoryBuffer(req.as_pem()), X509.FORMAT_PEM) for r in [r1, r2, r3, r4, r5]: self.assertEqual(req.as_der(), r.as_der()) with self.assertRaises(ValueError): X509.load_request_bio(BIO.MemoryBuffer(req.as_pem()), 345678) def test_save(self): x509 = X509.load_cert('tests/x509.pem') f = open('tests/x509.pem', 'r') l_tmp = f.readlines() # -----BEGIN CERTIFICATE----- : -----END CERTIFICATE----- x509_pem = ''.join(l_tmp[44:60]) f.close() f = open('tests/x509.der', 'rb') x509_der = f.read() f.close() x509.save('tests/tmpcert.pem') f = open('tests/tmpcert.pem') s = f.read() f.close() self.assertEquals(s, x509_pem) os.remove('tests/tmpcert.pem') x509.save('tests/tmpcert.der', format=X509.FORMAT_DER) f = open('tests/tmpcert.der', 'rb') s = f.read() f.close() self.assertEquals(s, x509_der) os.remove('tests/tmpcert.der') def test_malformed_data(self): with self.assertRaises(X509.X509Error): X509.load_cert_string('Hello') with self.assertRaises(X509.X509Error): X509.load_cert_der_string('Hello') with self.assertRaises(X509.X509Error): X509.new_stack_from_der('Hello') with self.assertRaises(X509.X509Error): X509.load_cert('tests/alltests.py') with self.assertRaises(X509.X509Error): X509.load_request('tests/alltests.py') with self.assertRaises(X509.X509Error): X509.load_request_string('Hello') with self.assertRaises(X509.X509Error): X509.load_request_der_string('Hello') with self.assertRaises(X509.X509Error): X509.load_crl('tests/alltests.py') def test_long_serial(self): cert = X509.load_cert('tests/long_serial_cert.pem') self.assertEquals(cert.get_serial_number(), 17616841808974579194) cert = X509.load_cert('tests/thawte.pem') self.assertEquals(cert.get_serial_number(), 127614157056681299805556476275995414779) class X509StackTestCase(unittest.TestCase): def test_make_stack_from_der(self): f = open("tests/der_encoded_seq.b64") b64 = f.read(1304) seq = base64.decodestring(b64) stack = X509.new_stack_from_der(seq) cert = stack.pop() self.assertIsNone(stack.pop()) cert.foobar = 1 self.assertEqual(cert.foobar, 1) subject = cert.get_subject() self.assertEqual( str(subject), "/DC=org/DC=doegrids/OU=Services/CN=host/bosshog.lbl.gov") def test_make_stack_check_num(self): f = open("tests/der_encoded_seq.b64") b64 = f.read(1304) seq = base64.decodestring(b64) stack = X509.new_stack_from_der(seq) num = len(stack) self.assertEqual(num, 1) cert = stack.pop() num = len(stack) self.assertEqual(num, 0) subject = cert.get_subject() self.assertEqual( str(subject), "/DC=org/DC=doegrids/OU=Services/CN=host/bosshog.lbl.gov") def test_make_stack(self): stack = X509.X509_Stack() cert = X509.load_cert("tests/x509.pem") issuer = X509.load_cert("tests/ca.pem") cert_subject1 = cert.get_subject() issuer_subject1 = issuer.get_subject() stack.push(cert) stack.push(issuer) # Test stack iterator i = 0 for c in stack: i += 1 self.assertGreater(len(c.get_subject().CN), 0) self.assertEqual(i, 2) stack.pop() cert_pop = stack.pop() cert_subject2 = cert_pop.get_subject() issuer_subject2 = issuer.get_subject() self.assertEqual(str(cert_subject1), str(cert_subject2)) self.assertEqual(str(issuer_subject1), str(issuer_subject2)) def test_as_der(self): stack = X509.X509_Stack() cert = X509.load_cert("tests/x509.pem") issuer = X509.load_cert("tests/ca.pem") cert_subject1 = cert.get_subject() issuer_subject1 = issuer.get_subject() stack.push(cert) stack.push(issuer) der_seq = stack.as_der() stack2 = X509.new_stack_from_der(der_seq) stack2.pop() cert_pop = stack2.pop() cert_subject2 = cert_pop.get_subject() issuer_subject2 = issuer.get_subject() self.assertEqual(str(cert_subject1), str(cert_subject2)) self.assertEqual(str(issuer_subject1), str(issuer_subject2)) class X509ExtTestCase(unittest.TestCase): def test_ext(self): if 0: # XXX # With this leaks 8 bytes: name = "proxyCertInfo" value = "critical,language:Inherit all" else: # With this there are no leaks: name = "nsComment" value = "Hello" lhash = m2.x509v3_lhash() ctx = m2.x509v3_set_conf_lhash(lhash) x509_ext_ptr = m2.x509v3_ext_conf(lhash, ctx, name, value) X509.X509_Extension(x509_ext_ptr, 1) class CRLTestCase(unittest.TestCase): def test_new(self): crl = X509.CRL() self.assertEqual(crl.as_text()[:34], 'Certificate Revocation List (CRL):') def suite(): st = unittest.TestSuite() st.addTest(unittest.makeSuite(X509TestCase)) st.addTest(unittest.makeSuite(X509StackTestCase)) st.addTest(unittest.makeSuite(X509ExtTestCase)) st.addTest(unittest.makeSuite(CRLTestCase)) return st if __name__ == '__main__': Rand.load_file('randpool.dat', -1) unittest.TextTestRunner().run(suite()) Rand.save_file('randpool.dat') M2Crypto-0.22.6rc4/tests/thawte.pem0000664000175000017500000000277212605232411017262 0ustar matejmatej00000000000000-----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA 2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu MdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- M2Crypto-0.22.6rc4/tests/x509.der0000664000175000017500000000122012611255457016463 0ustar matejmatej0000000000000000 ~އ 0  *H 0O1 0 UUS10U California10U M2Crypto10U Heikki Toivonen0 121121153524Z 230108153524Z0D1 0 UUS10U California10U M2Crypto1 0 U X50900  *H 0;!u:OxVh6oR 'xG5p3'1-JK)Ny :7g EB1txX .80# @?&[Cd]wO_^{0y0 U00, `HB OpenSSL Generated Certificate0Un`@eg&|3r0U#0jaQb`M̕Dx-0  *H W}2DD,iT (f7qo/Ka VPpeg$6SU\&V Pl;7dd+[xuOYFn;y ȑ],v>lӁlJM2Crypto-0.22.6rc4/tests/x509.pem0000664000175000017500000000751312611255457016505 0ustar matejmatej00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: b4:7e:b2:de:87:00:03:0d Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, ST=California, O=M2Crypto, CN=Heikki Toivonen Validity Not Before: Nov 21 15:35:24 2012 GMT Not After : Jan 8 15:35:24 2023 GMT Subject: C=US, ST=California, O=M2Crypto, CN=X509 Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00:ba:3b:21:75:3a:4f:78:99:14:56:ae:68:36:6f: 52:f3:01:a4:c4:0c:cc:27:eb:e2:c5:e1:78:19:ba: d4:47:05:35:df:d4:1c:10:8b:70:33:a2:f3:27:31: 9e:1d:b7:2d:f8:ff:01:4a:4b:90:a7:29:4e:79:09: ad:df:3a:85:96:fc:fd:cb:ea:8c:37:b6:e4:b2:67: ec:fd:20:e1:0c:45:98:42:31:80:74:0e:78:fa:58: 09:0d:2e:e5:82:38:8d:30:23:80:12:0c:40:c7:3f: 26:94:e9:5b:43:f1:64:e2:1e:5d:fc:77:92:93:b4: 4f:5f:8d:88:a0:03:b7:5e:a1 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: E8:C1:6E:60:19:13:82:40:65:B9:67:26:B7:8E:D6:7C:EE:33:8D:72 X509v3 Authority Key Identifier: keyid:80:D9:6A:1E:15:FE:8B:61:51:62:60:4D:B3:CC:95:44:78:2D:89:E6 Signature Algorithm: sha1WithRSAEncryption cf:57:f4:f6:7d:be:e0:32:d1:44:ba:15:f7:44:2c:69:df:54: a1:09:28:7f:7f:66:37:db:71:6f:2f:4b:b0:61:f5:96:09:56: 50:e4:14:87:81:70:93:bb:9d:1e:8a:65:06:e8:67:c5:fb:24: b1:17:b5:36:83:cb:53:88:0e:55:5c:91:80:26:56:f2:0b:50: 19:86:6c:3b:1b:37:64:e1:64:2b:18:c3:5b:aa:d3:78:84:75: 4f:59:c4:46:6e:9a:fb:a2:3b:86:79:87:09:a7:a6:e3:c8:91: 5d:ea:2c:76:d4:ff:a3:3e:ad:6c:bd:bb:e2:c1:1d:1e:d3:81: 6c:4a -----BEGIN CERTIFICATE----- MIICjDCCAfWgAwIBAgIJALR+st6HAAMNMA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQKDAhNMkNyeXB0bzEY MBYGA1UEAwwPSGVpa2tpIFRvaXZvbmVuMB4XDTEyMTEyMTE1MzUyNFoXDTIzMDEw ODE1MzUyNFowRDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExETAP BgNVBAoMCE0yQ3J5cHRvMQ0wCwYDVQQDDARYNTA5MIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQC6OyF1Ok94mRRWrmg2b1LzAaTEDMwn6+LF4XgZutRHBTXf1BwQ i3AzovMnMZ4dty34/wFKS5CnKU55Ca3fOoWW/P3L6ow3tuSyZ+z9IOEMRZhCMYB0 Dnj6WAkNLuWCOI0wI4ASDEDHPyaU6VtD8WTiHl38d5KTtE9fjYigA7deoQIDAQAB o3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU6MFuYBkTgkBluWcmt47WfO4zjXIwHwYD VR0jBBgwFoAUgNlqHhX+i2FRYmBNs8yVRHgtieYwDQYJKoZIhvcNAQEFBQADgYEA z1f09n2+4DLRRLoV90Qsad9UoQkof39mN9txby9LsGH1lglWUOQUh4Fwk7udHopl BuhnxfsksRe1NoPLU4gOVVyRgCZW8gtQGYZsOxs3ZOFkKxjDW6rTeIR1T1nERm6a +6I7hnmHCaem48iRXeosdtT/oz6tbL274sEdHtOBbEo= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQC6OyF1Ok94mRRWrmg2b1LzAaTEDMwn6+LF4XgZutRHBTXf1BwQ i3AzovMnMZ4dty34/wFKS5CnKU55Ca3fOoWW/P3L6ow3tuSyZ+z9IOEMRZhCMYB0 Dnj6WAkNLuWCOI0wI4ASDEDHPyaU6VtD8WTiHl38d5KTtE9fjYigA7deoQIDAQAB AoGBALdK8ZBGtuc0i28RM2K4SQUCDiAjlGCKa2Vll+aDGuFXwIGva3vhMaqw6+8c h8ope6cBnUx5eUL9hc3dd/Moz0dxM34p2zu/fZbiFD2yrKlkVSXHv6YobYhUagod htPwb+tQOrQqYpHZ/zPeVkAa/EfmM88RD603nlFHbCz5PpFBAkEA5HWMYUaXD+1M kX3YjXy3ESmKr3zPdbQkw6tDiQ6ijl1jUX+b4BKGSgINFYsmXlaFYM/GeJWJ0z64 BiPkSnhueQJBANCuYg0ykia6miTUWzXv3i8r8voVt593KmrAf23JwUM+jZnAd4yl xwSHkJSX5Ualp1cYDfKD9wzKj8vjq4mCx2kCQQCYlJFvHnAhqQDsYrpQtKynf7Eq RxdfqzKqpCV00htrLZ/5fFqkqnqZzwjiDI9RjkOCRwJs4qKsPUU2hJ4hxpExAkEA llzwfb3wnUNbiioRRr39hFPQke5QDvEYeS8XIo57WO6brSuHeKqCynq77LW+GLeH 6jOE6Te5LVhPYIQ9t6mp8QJAKPE2g1wc0kmlzaOkNrlj67PPcRKqRVqL1RWIaSz9 Dh3KWyvOnOQAKbShI9EbXqdINKM7JxJAhSL4LPBd3ejxSA== -----END RSA PRIVATE KEY----- M2Crypto-0.22.6rc4/CHANGES0000664000175000017500000005352312607370517015130 0ustar matejmatej000000000000000.21.1 - 2011-01-15 ------------------- - Distribution fix 0.21 - 2011-01-12 ----------------- - Support OpenSSL 1.0. Thanks to Miloslav Trmac for figuring out how to fix test_smime.py - Rename m2.engine_init to engine_init_error so that ENGINE_init and ENGINE_finish can be exposed, thanks to Erlo - 0.20 started releasing Python locks even around some operations that interacted with the Python runtime, potentially causing crashes and other weirdness, fix by Miloslav Trmac - Make httpslib.ProxyHTTPSConnection work with Python 2.3 0.20.2 - 2009-10-06 ------------------- - (Re)Enable configuration and use with OpenSSL 0.9.7g and older by disabling RSA PSS methods when using such old OpenSSL, thanks to Stef Walter 0.20.1 - 2009-08-27 ------------------- - Fix regression in httpslib.ProxyHTTPSConnection, by Miloslav Trmac 0.20 - 2009-08-10 ----------------- - Deprecated M2Crypto.PGP subpackage since nobody seems to be using it nor is it being maintained (if you do use it, please let me know) - Added fedora_setup.sh to help work around differences on Fedora Core -based distributions (RedHat, CentOS, ...); thanks to Miloslav Trmac - Added X509.load_request_bio and load_request_string, by Hartmut Goebel and Pavel Shramov - Added alias X509.Request.set_subject for set_subject_name to match X509.X509, by Pavel Shramov - OBJ_* wrappers did not work properly with OpenSSL 0.9.8a and earlier, fix by Pavel Shramov - Added ASN1_UTCTIME.get_datetime and set_datetime, by Pavel Shramov - Fixed obj_obj2txt, which returned nonsense, fix by Barney Stratford - m2urllib did not close sockets properly, fix by Miloslav Trmac - Allow SSL peer certificate to have subjectAltName without dNSName and use commonName for hostname check, fix by Miloslav Trmac - threading_locking_callback did not block on a lock when the lock was held by another thread, by Miloslav Trmac - Allow more blocking OpenSSL functions to run without GIL, by Miloslav Trmac - Fixed httpslib to send only the path+query+fragment part of the URL when using CONNECT proxy, by James Bowes - SSLServer.__init__ now takes optional bind_and_activate parameter and initializes by calling SocketServer.BaseServer.__init__, which are Python 2.6 compatibility fixes, by Christian - ftpslib now works with Python 2.6, by Theodore A. Roth - httpslib.ProxyHTTPSConnection needs to cast port into integer, by John M. Schanck - Added support for RSASSA-PSS signing and verifying, by Chris Collis - Added support for disabling padding when using RSA encryption, by Chris Collis - ASN1_INTEGERs can now be larger than fits in an int, for example to support X509 certificates with large serial numbers, patch by Mikhail Vorozhtsov and testcase by Barry G. - Reverted a change done in 0.17 to m2urllib2 which changed urls to include host when it should stay as it was - httpslib no longer uses urllib; instead it uses urlparse for url parsing - SMIME.text_crlf and text_crlf_bio were always raising TypeError; fixed - EVP.load_key and load_key_bio fixed to raise EVP.EVPError and BIO.BIOError instead of str (str exceptions not allowed in Python 2.6 and later) - SSL.Session.load_session fixed to raise SSL.SSLError instead of str - SMIME.load_pkcs7, load_pkcs7_bio, smime_load_pkcs7, smime_load_pkcs7_bio, text_crlf, text_crlf_bio fixed to raise BIO.BIOError, SMIME.PKCS7_Error and SMIME.SMIME_Error as appropriate instead of str - Added FIPS mode to unit tests, and used FIPS-compliant key sizes in other tests, by Miloslav Trmac. Note that tests run much slower because of this! - Unit tests cover 80% of the code 0.19.1 - 2008-10-12 ------------------- - Re-enable building when OpenSSL built without EC support, by Miloslav Trmac - Remove shebang from Engine.py since it is not executable, by Miloslav Trmac 0.19 - 2008-10-05 ----------------- - OpenSSL OBJ_* functions wrapped by Pavel Shramov - OpenSSL ENGINE interface wrapped, providing support for smart cards, by Martin Paljak and Pavel Shramov - EVP.PKey.get_rsa() now returns RSA_pub, which fixes segmentation fault when trying to encrypt using public key from X509 certificate, by Ben Timby - httpslib.ProxyHTTPSConnection now sends the required Host header, by Karl Grindley - Use the proxied User-Agent value in CONNECT requests, by James Antill and Miloslav Trmac - Fixed m2urllib.build_opener when optional handlers were in use, affected Python 2.5 and later, by Miloslav Trmac - Reverted the incorrect GIL change done in 0.18 to m2.passphrase_callback, which caused a deadlock when called from mod_python for example. Thanks to Michal Kochel and Keith Jackson. - SSL.Connection.accept() passed wrong certificate to postConnectionCheck callback - httpslib.HTTPSConnection now raises ValueError for illegal keyword argument - m2.pkey_write_pem[_no_cipher] changed to use the recommended (more secure) PEM_write_bio_PKCS8PrivateKey (used by PEM_write_bio_PrivateKey). - X509.load_cert, load_cert_bio, load_cert_der_string, new_stack_from_der, load_request and load_crl now raise X509Error for invalid data. Previously some of these raised a string as an error, some did not raise but caused strange errors later, for example x509.verify() would return -1. - Fixed SSL.Connection.get_socket_read_timeout and set_socket_read_timeout on 64bit platforms by adding SSL.timeout.struct_size() and using it instead of hardcoded size for socket.getsockopt - X509_Store.load_info now returns the value from the underlying m2.x509_store_load_locations call, and in case of error raises X509Error - Fixed SMIME.verify to raise the correct PKCS7_Error (used to raise SMIME_Error) when verification fails with Python 2.6 0.18.2 - 2007-10-12 ------------------- - typedef Py_ssize_t was insufficiently guarded, now follows PEP 353. This prevented building on at least Red Hat Linux and Debian Linux (unstable). 0.18.1 - 2007-10-08 ------------------- - Redo build fix when OpenSSL configured without Elliptic Curves (EC), see also INSTALL file 0.18 - 2007-07-26 ----------------- - Added EVP.pbkdf2 to derive key from password - X509_Store_Context.get1_chain added - Added X509_Name.__iter__, __getitem__, get_entries_by_nid which allow iterating over all X509_Name_Entries or getting just all commonName entries, for example - Added X509_Name_Entry.get_object, get_data, set_data - Added back PKCS7.get0_signers (was removed in 0.16) - X509_Extension.get_value accepts flag and indent parameters. - support multiple dNSName fields in subjectAltName - support multiple commonName fields for SSL peer hostname checking - Checking for erroneous returns from more OpenSSL EVP_* functions, which means that certain things that used to fail silently will now raise an EVP.EVPError; affected m2 functions are: digest_final, cipher_init, cipher_update, cipher_final and sign_update. sign_final will now raise EVP.EVPError instead of SystemError as well. - Fixed Pkey.verify_final to take a sign parameter - If a subjectAltName extension of type dNSName is present in peer certificate, use only the dNSNames when checking peer certificate hostname, as specified by RFC 2818. If no dNSNames are present, use subject commonName. - Fixed memory leaks in m2 functions ec_key_new_by_curve_name, pkey_get_modulus, ecdsa_verify, threading_init and X509.X509.verify, X509.X509_Stack (which manifested for example when calling X509.new_stack_from_der), SSL.Connection (which manifested with some connection errors or when connect was never called), twisted wrapper, SSL.Connection.makefile (in BIO.IOBuffer really) - Fixed threading regressions introduced in 0.16, by Aaron Reizes and Keith Jackson - Added SSL session caching support to HTTPSConnection, by Keith Jackson - Added the ability to save and load DER formatted X509 certificates and certificate requests, by Keith Jackson - m2xmlrpclib.py fixed to work with Python 2.5, by Miloslav Trmac - 64-bit correctness fixes, by Miloslav Trmac - Added X509_Name.as_hash, by Thomas Uram - Moved --openssl option from general setup.py option to build_ext option, meaning you need to do: python setup.py build build_ext --openssl=/path, by Philip Kershaw - Fixed build problem affecting certain systems where OpenSSL was built without EC support - M2CRYPTO_TEST_SSL_SLEEP environment variable controls how long to sleep after starting the test SSL server. Default is 0.5, but 0.1 or even 0.05 might work with modern computers. Makes tests finish significantly faster. 0.17 - 2006-12-20 ----------------- - setup.py has new test command to run unit tests (requires setuptools) - Added m2urllib2, by James Bowes (python 2.4 and later, at least for now) - Added CONNECT proxy for httpslib and m2urllib2, by James Bowes - Added PKey.get_modulus, X509.get_fingerprint, X509_Name.as_der and m2.bn_to_hex, by Thomas Uram - Prevent Connection.makefile from freeing bio redundantly, by Thomas Uram - Added Err.peek_error_code, by Thomas Uram - Fixed m2urllib.open_https to return the response headers, otherwise code that relied on that would break (for example msnlib-3.5), by Arno bakker - Fixed twisted wrapper to work with >16kb BIO buffers, by Martin Paljak - Added support for remaining ECs, by Larry Bugbee - Fixed DSA.save_key and DSA_.save_pub_key, by Larry Bugbee - SSL.Context.load_verify_locations raises ValueError if cafile and capath are both None - Fixed X509.check_purpose() (was always raising exceptions) - smime_read_pkcs7 was changed to automatically call BIO_set_mem_eof_return on memory BIOs because otherwise the read would fail with "SMIME_Error: not enough data" - X509.new_extension('subjectKeyIdentifier', 'hash') raises ValueError instead of crashing Python 0.16 - 2006-07-05 ----------------- - Minimum requirements updated: Python 2.3+, OpenSSL 0.9.7+, SWIG 1.3.24+ - Optional features from OpenSSL 0.9.8 and newer - Enhancements to EVP and X509 to allow proxy certificate handling, by Matt Rodriguez - SSLBio and related additions to help do SSL with BIOs directly, by Matt Rodriguez - Added --openssl option to build command which can be used to specify where OpenSSL is installed, by Matt Rodriguez - Added sign and verify to RSA class, and get_rsa to PKey class, by Matt Rodriguez - ECDSA signatures and ECDH key agreement, requires OpenSSL 0.9.8+, by Arno Bakker - Fix non-hashable type problems in SSL._ctxmap and users, by Michael Weiser - Fixed SSLServer.handle_error to take the correct number of arguments, by Dan Williams - Various DSA enhancements by Larry Bugbee - Added sha224, sha256, sha384 and sha512, by Larry Bugbee - Added serialNumber, SN, surname, GN and givenName fields to X509_Name, by Martin Paljak - m2.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT is the fourth certificate verification error that will be allowed when unknown CAs are allowed - post connection checks in Connection.accept() and connect() fixed (these were broken in 0.15) - Fixed EVP.Cipher to work with aes_* ciphers (used to crash Python). The actual problem was in m2.bytes_to_key. - SMIME methods and functions raise correct exceptions - Raise ValueError instead of AttributeError when a non-existing hash algorithm or SSL version is asked for - ssl_ctx_set_tmp_(dh|rsa) now return value, and the rsa version calls the rsa function instead of the dh function - digest_update and verify_update return type changed to int, which allows better error reporting; EVP.MessageDigest.update and EVP.PKey.verify_update likewise changed - X509_Name and ASN1_String as_text (new for ASN1_String) take optional parameters to control formatting. - Cipher_Stack, X509_Stack and X509_Extension_Stack are iterable - EVP.MessageDigest now properly cleans up the underlying data when the object gets deleted - It is now possible to set and get non-nid values to X509_Name (previously only set worked) - SSL.Connection.set_client_CA_list_from_file now uses the actual implementd function instead of raising exception - Multithreaded SSL no longer uses the SSL_set/get_app_data to set and restore thread state, but uses the standard PyGILState_STATE instead. - m2urllib no longer outputs the HTTP headers (there was an erronous call to set_debuglevel(1)) - Removed RCS_id, RCS_ID and _RCS_id from Python files - All known memory leaks fixed - SWIG and compiler warning fixes - More and better Epydoc formatted docstrings - More than doubled the number of unit tests, also made many demos into tests 0.15 - 2005-08-17 ----------------- - Support OpenSSL 0.9.8, Python 2.4.1, SWIG 1.3.24 - Fixed multiple memory leaks - Twisted integration - Safer defaults for SSL context and post connection check for clients - Eliminated C pointers from interfaces (some may still remain in callbacks) - Many cases where Python interpreter crashed have been fixed - Improved thread safety of many callbacks - And of course more of the OpenSSL API is covered, new docstrings and tests have been written Changes since 0.13 -------------------- - Fixed memory leak due to circular reference in SSL.Connection. Thanks to Michael Dunstan. Oops, patch is ZServerSSL-specific. Andre Reitz provided a generalised fix. Thanks Andre. - Fixed __getattr__ error in DSA. Thanks to Igor Belyi. - Added rand_poll, rand_screen and rand_win32_event functions to M2Crypto.Rand. - Updated ZServerSSL files to match Zope 2.7.0 versions. - Integrated (overlapping) patches by Peter Teniz and Heikki Toivonen covering operations on X.509-related structures that gives M2Crypto PKI functionality. Thanks Peter and Heikki. - Peter Teniz contributed demo2004/pki/x509auth.py. - Created demo2004/ directory that will contain new or updated demos. - Added verify_[init|update|final] in _evp.i. Patch by Zachery Corbiere. Thanks Zac. Changes since 0.12/0.11 ------------------------- - Patches from Artur Frysiak . Thanks Artur. = Allow using a passphrase callback in class SMIME. = Added method get0_signers to class PKCS7, which retrieves signers' certificates from a PKCS7 blob. = Added methods as_pem and save_pem to class X509. = Added file version.py. = Allow SSL.Context.load_verify_locations to accept both 'cafile' and 'capath'. - Fixed BIO.read() not reading until EOF. Thanks to Egil Muller for suggestion. - Honour 'mode' parameter in SSL.Connection.makefile. Thanks again to Egil Muller. - Roger Binns contributed epydoc-generated docs for M2Crypto. Thanks Roger. - Peter Teniz contributed patches to create X.509 requests and certificates. Thanks Peter. - Updated Medusa to 0.54. - Make various OpenSSL bignum functions (written long ago) available to Python. Changes since 0.11 -------------------- - ZServerSSL with client certificate-based authentication rides again. - Created Makefile for Python 2.3. - Modified LICENCE: changed my name to the generic "the author" in the all-caps disclaimer paragraph. - Allow to save RSA key pair in the clear. - ZServerSSL for Zope 2.7. - Excluded RC5. IDEA was taken out several releases ago. This should allow M2Crypto to build with stock OpenSSL on various Linuxen. - Added ssl_set_tmp_dh_callback. - Added ssl_set_tmp_rsa and ssl_set_tmp_rsa_callback to support weak-cipher browsers. - ZServerSSL exports SSL_CIPHER request header (a la mod_ssl) to Zope applications. - Perform distutils's SWIG .i search path tweaking within setup.py. setup.py should now work "out of the box". - Added contrib/smimeplus.py, a high-level S/MIME interface, contributed by Bernard Yue . Thanks Bernard. - Added in long forms of nid's in X509_Name. Thanks to William K Volkman for patch. - Updated Mac OS X build instructions. Thanks to Larry Bugbee Changes since 0.10 -------------------- - Dave Berkeley contributed fixes to SSL.Context-related memory leaks and code to set the size of the SSL session cache. - Brent Chun contributed the following: + Fixes to memory leaks. + Code to expose X.509 certificate chain operations. + Code to expose set/get operations on the SSL session cache. - Changed swig/ to SWIG/, for the convenience of people who don't read INSTALL. Some Makefiles may break because of this. setup.py continues to work, of course. - ZServerSSL tested with Zope 2.6.1. There is now a HOWTO. - Updated README and INSTALL. - Filled doc/ with stuff that went missing in several past releases. Changes since 0.09 -------------------- - Updated to OpenSSL 0.9.7. Thanks to Toby Allsopp for patches. - Added functionality to create a basic certificate request. Also contributed by Toby Allsopp. - Finally, AES! Changes since 0.08 -------------------- - Replaced demo/Zope/ZServer/__init__.py with the correct version for Zope 2.6.0. - Added a sample starts.bat for ZServerSSL. - Incoporated a patch by prashanth@jibe.biz that handled the new-in-Python-2.2.2 "strict" parameter for the various HTTP[S] connection classes in httplib.py. Thanks prashanth. This fixes M2Crypto's XMLRPC support for Python 2.2.2. (Apparently it was working for Python 2.2.1.) - Incorporated some cosmetic patches from Adam Karpierz . Thanks Adam. Changes since 0.07 snapshot #3 -------------------------------- - Updated to SWIG 1.3.17. - Excluded IDEA. - Tested with OpenSSL 0.9.6h. - ZServerSSL rides again for Zope 2.6.0. - setup.py does! - Removed Makefiles for Windows and Unix. (Makefile.osx remains.) - Included in contrib/ Isaac Salzberg's application of Mihai Ibanescu's patch that allows IIS interoperability thru an authenticating proxy. Thanks Isaac. - Included in contrib/ patch by Dave Brueck that has smarter non-blocking behaviour. Thanks Dave. Changes since 0.06 ----------------------- - test_ssl_win.py. (Requires Mark Hammond's Win32 extensions.) - Renamed demo/https to demo/medusa; updated Medusa to 2001 Jun release. - Improved _ssl.i's and M2Crypto.SSL.Connection's accept/connect methods. - M2Crypto.ftpslib for client-side FTP/TLS. - demo/medusa/ftps_server.py for server-side FTP/TLS. - Improved thread-safety. - Cleaned up echo client and servers. - Fixed missing import in m2urllib. - Fixed m2urllib to handle HTTP redirects. - Python 2.2 compatibility. - AuthCookie - secure authenticator cookies. Changes since 0.05 ----------------------- - Handled the cases where Python callbacks raised exceptions. - Fixed a NULL-deref bug in _ssl.i which crashes Medusa https when IE or Opera comes a-calling. - ZServerSSL rides again - a more robust ZServerSSL for Zope 2.3.0. - Added the MIME type 'application/x-x509-ca-cert' to demo/ssl/https_srv.py. This facilitates installing self-generated certificates into your browser. - ZSmime and GuardedFile bundled. - Documentation! A HOWTO on operating your own CA. - Documentation! A HOWTO on S/MIME. Examples are in demo/smime.howto. - Python 2.1 compatibility. - Fixed demo/https/https_server.py's CPU-spinning. (As per ZServerSSL.) - Fixed m2urllib's unexpected eof - demo/ssl/urllib_cli.py now works. - Renamed xmlrpclib2.py to m2xmlrpclib.py. - Kludged SSL.ssl_dispatcher to do blocking connect()'s: see demo/ssl/https_cli_async.py. - SWIG 1.3.6 does! Thanks to Keith Jackson . Changes since 0.04 ----------------------- - Fixed a silly reversed-logic bug in M2Crypto.SSL.Connection.setblocking(). - Fixed yet more memory leaks. Thanks to Ray Suorsa . - Build instructions for Borland BC++ 5.5 free compiler suite. - Bundles the June 2000 unencumbered release of Medusa. - SSL callback thread-safety. Thanks again to Ray Suorsa for insights and patches. - Renamed M2Crypto.M2Crypto to M2Crypto.m2 to prevent package/module loading confusion. - SSL.Session and a demo in demo/ssl/sess.py. - https_srv.py, an enhanced, https version of SimpleHTTPServer.py. - Interface change: SMIME.load_pkcs7_bio() is renamed SMIME.smime_load_pkcs7_bio(), similarly SMIME.load_pkcs7() to SMIME.smime_load_pkcs7(); these load PKCS7 objects generated by S/MIME. - Interface change: SMIME.load_pkcs7_bio() now loads a PKCS7 PEM file, i.e., a file of the format "-----BEGIN PKCS7-----". - Works with both Python 2.0 and Python 1.5.2. - OpenSSL 0.9.6. (Possibly incompatible with earlier OpenSSL releases.) - Unit tests with PyUnit. - Improved C code: = Custom Python exceptions. = Diligent error checking. = Fixed memory leaks. - Renamed M2Crypto.urllib2 to M2Crypto.m2urllib. - HTTPS clients of Python 1.5.2's and Python 2.0's httplib and urllib. Changes since 0.03 ----------------------- - SSL certificate-based authentication with Python callback. - More robust SSL.Connection - raises exceptions, not dumps core. - Fixed (some) memory leaks and multiple-free()s. - Cleaned up EVP.HMAC and EVP.PKey. - More X.509 certificate manipulation. - An interface to create SSL sessions. - Unified SSL read() and write() for synchronous and asynchronous operation. - S/MIME and PKCS #7. - Integrated with OpenSSL 0.9.5. - Enhanced the PRNG interface. Changes since 0.02 ----------------------- 1. Ephemeral DH for SSL. 2. ThreadingSSLServer now does. 3. XMLrpc over https. 4. ZServerSSL for Zope 2.1.3. 5. Encrypting monitor for Zope 2.1.3. 6. Beginnings of PGP2 support. 7. Replaced eval() calls with other (hopefully) safe ones. 8. Miscellaneous enhancements and bug fixes. Changes since 0.01 ----------------------- 1. Beginnings of SSL support. For building servers, blocking i/o: - An SSLServer modeled after SocketServer. - A ForkingSSLServer that seems to work well. - A ThreadingSSLServer that runs one thread at a time. (!) ;-) For building servers, nonblocking i/o: - An ssl_dispatcher modeled after asyncore.dispatcher. A HTTPS server based on Medusa. For client-side web programming: - httpslib - urllib2 2. Support for some BIO objects. 3. Reduced per-module name space pollution. 4. Have Swig check for NULL pointers: reduced .i cut-&-paste. 5. Standardise on MPINT for passing big integers between Python and OpenSSL. 6. Removed MD5, SHA1, RIPEMD160. Just use EVP.MessageDigest. 7. Removed HMAC. Just use EVP.HMAC. M2Crypto-0.22.6rc4/INSTALL.rst0000664000175000017500000001524012613361405015760 0ustar matejmatej00000000000000==================== Installing M2Crypto ==================== :Maintainer: Heikki Toivonen :Web-Site: http://chandlerproject.org/Projects/MeTooCrypto .. contents:: Pre-requisites -------------- The following software packages are pre-requisites: - **Python 2.6 or newer** - **OpenSSL 1.0.1e or newer** - **SWIG 1.3.40 or newer** - Python 2.6 platforms require the Python package unittest2 to be installed Note about OpenSSL versions early in the 0.9.7 series ----------------------------------------------------- Early OpenSSL 0.9.7 versions require the **i386** symbol to be defined. Uncomment this line in setup.py: #'-D\_\_i386\_\_', # Uncomment for early OpenSSL 0.9.7 versions if you get this compile-time error: This openssl-devel package does not work your architecture? Note about Fedora Core -based Distributions ------------------------------------------- Fedora Core (and RedHat, CentOS etc.) have made changes to OpenSSL configuration compared to many other Linux distributions. If you can not build M2Crypto normally, try the fedora\_setup.sh script included with M2Crypto sources. Installing on Unix-like systems, including Cygwin ------------------------------------------------- :: :: $ tar zxf m2crypto-.tar.gz $ cd m2crypto- $ python setup.py build $ python setup.py install If you have installed setuptools you can also optionally run tests like this: :: $ python setup.py test This assumes OpenSSL is installed in /usr. You can provide an alternate OpenSSL prefix location with --openssl option to build\_ext command. Other commands accept standard options if you need them. Some distributions, like Fedora Core, package OpenSSL headers in a different location from OpenSSL itself. In that case you need to tell build\_ext the additional include location with -I option. Differences when installing on Windows -------------------------------------- Before building from source, you need to install OpenSSL's include files, import libraries and DLLs. By default setup.py assumes that OpenSSL include files are in ``c:\pkg\openssl\include``, and the import libraries in ``c:\pkg\openssl\lib``. As with other platforms, you can specify a different OpenSSL location with --openssl option to build\_ext command. Using OpenSSL 0.9.8 on Windows requires Python be built with applink.c (add an include statement in python.c). This is not a requirement for Linux or MacOSX. (applink.c is provided by OpenSSL.) MSVC++ ~\ :sub:`:sub:`:sub:`~``` setup.py is already configured to work with MSVC++ by default. With MSVC++, the OpenSSL DLLs, as built, are named ``libeay32.dll`` and ``ssleay32.dll``. Install these somewhere on your PATH; for example in ``c:\bin``, together with ``openssl.exe``. For MSVC++, the import libraries, as built by OpenSSL, are named ``libeay32.lib`` and ``ssleay32.lib``. MINGW :sub:`:sub:`:sub:`~``` .. NOTE:: The following instructions for building M2Crypto with MINGW are from M2Crypto 0.12. These instructions should continue to work for this release, although I have not tested them. Read Sebastien Sauvage's webpage: :: http://sebsauvage.net/python/mingw.html For mingw32, the OpenSSL import libraries are named ``libeay32.a`` and ``libssl32.a``. You may need to edit setup.py file for these. You'll also need to create ``libpython2[123].a``, depending on your version of Python. OpenSSL DLLs for mingw32 are named ``libeay32.dll`` and ``libssl32.dll``. Install these somewhere on your PATH; for example in ``c:\bin``, together with ``openssl.exe``. Build M2Crypto: :: python setup.py build -cmingw32 python setup.py install BC++ :sub:`:sub:`~``\ ~ .. NOTE:: The following instructions for building M2Crypto with MSVC++ 6.0 and BC++ 5.5 free compiler suite are from M2Crypto 0.10. These instructions should continue to work for this release, although I have not tested them. For BC++ these files are created from the MSVC++-built ones using the tool ``coff2omf.exe``. I call them ``libeay32_bc.lib`` and ``ssleay32_bc.lib``, respectively. You will need to edit setup.py file for these. You'll also need Python's import library, e.g., ``python22.lib``, to be the BC++-compatible version; i.e., create ``python22_bc.lib`` from ``python22.lib``, save a copy of ``python22.lib`` (as ``python22_vc.lib``, say), then rename ``python22_bc.lib`` to ``python22.lib``. Now you are ready to build M2Crypto. Do one of the following:: :: python setup.py build python setup.py build -cbcpp Then, :: :: python setup.py install MacOSX ------ | Follow the standard instructions to build and install M2Crypto. | However, should you encounter difficulties, you may want to consider the following possibilities. - Distutils from Python 2.5 provides support for universal builds (ppc and i386) and Distutils requires a recent version of Xcode. See http://developer.apple.com/tools/download/ - OpenSSL 0.9.7l gets installed in /usr with Apple's Security Update 2006-007. If you need features in OpenSSL 0.9.8, you should consider installing 0.9.8 in /usr/local. The commands are: OpenSSL: ./config shared --prefix=/usr/local make make test sudo make install [or... install\_sw] M2Crypto: python setup.py build build\_ext --openssl=/usr/local sudo python setup.py install build\_ext --openssl=/usr/local To make Universal builds, you will need to uncomment a line in setup.py: extra\_link\_args = ['-Wl,-search\_paths\_first'], If that does not work, here is what Marc Hedlund was able to get working: First, download OpenSSL 0.9.8d and unpack it. Edit the OpenSSL Makefiles per PROBLEMS. Then: :: ./config no-shared no-asm --prefix=/usr/local make make test sudo make install make clean ./Configure no-shared no-asm --prefix=/usr/local darwin-ppc-cc make build_libs "CC=cc -arch ppc" lipo -info lib* mkdir -p build/ppc mv lib* build/ppc make clean ./Configure no-shared no-asm --prefix=/usr/local darwin-i386-cc make build_libs "CC=cc -arch i386" lipo -info lib* mkdir -p build/i386 mv lib* build/i386/ /bin/ls -1 build/i386/ > libnames.tmp mkdir universal Create a script in the OpenSSL directory called 'make\_universal', with these contents: :: #!/bin/sh for lib in `cat libnames.tmp`; do lipo -create build/*/$lib -output universal/$lib done exit 0 Then: :: sh make_universal lipo -info universal/lib* sudo cp universal/lib* /usr/local/lib lipo -info /usr/local/lib/lib{crypto,ssl}* cd ../m2crypto-0.17 Then edit the m2crypto setup.py and uncomment the extra\_link\_args line at the end. :: python setup.py build build_ext --openssl=/usr/local sudo python setup.py install build_ext --openssl=/usr/local M2Crypto-0.22.6rc4/LICENCE0000664000175000017500000000243612605232411015103 0ustar matejmatej00000000000000Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. Portions copyright (c) 2004-2006 Open Source Applications Foundation. All rights reserved. Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved. Copyright (c) 2008-2010 Heikki Toivonen. All rights reserved. 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. THE AUTHOR PROVIDES THIS SOFTWARE ``AS IS'' AND ANY EXPRESSED 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 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. M2Crypto-0.22.6rc4/MANIFEST.in0000664000175000017500000000053312613361405015655 0ustar matejmatej00000000000000include SWIG/*.i include SWIG/*.h include SWIG/*.def recursive-include tests *.py *.pem *.der *.b64 README *.pgp *.dat *.p7* recursive-include doc * recursive-include demo * recursive-include contrib * include INSTALL.rst include README.rst include CHANGES include epydoc.conf include LICENCE include fedora_setup.sh exclude M2Crypto/_m2crypto.py M2Crypto-0.22.6rc4/README.rst0000664000175000017500000000334112613361405015606 0ustar matejmatej00000000000000========= M2Crypto ========= :Maintainer: Heikki Toivonen :Web-Site: https://gitlab.com/m2crypto/m2crypto M2Crypto = Python + OpenSSL + SWIG ---------------------------------- M2Crypto is a crypto and SSL toolkit for Python. M2 stands for "me, too!" M2Crypto comes with the following: - **RSA**, **DSA**, **DH**, **HMACs**, **message digests**, **symmetric ciphers** including **AES**, - **SSL/TLS** functionality to implement **clients and servers**. - **Example SSL/TLS client and server programs**, which are variously **threading**, **forking** or based on **non-blocking socket IO**. - **HTTPS** extensions to Python's **httplib, urllib and xmlrpclib**. - Unforgeable HMAC'ing **AuthCookies** for **web session management**. - **FTP/TLS** client and server. - **S/MIME v2**. - **ZServerSSL**: A **HTTPS server for Zope**. - **ZSmime**: An S/MIME messenger for **Zope**. - And much more. M2Crypto is released under a very liberal BSD-style licence. See LICENCE for details. To install, see the file INSTALL. Look at the tests and demos for example use. Recommended reading before deploying in production is "Network Security with OpenSSL" by John Viega, Matt Messier and Pravir Chandra, ISBN 059600270X. Note these caveats: - Possible memory leaks, because some objects need to be freed on the Python side and other objects on the C side, and these may change between OpenSSL versions. (Multiple free's lead to crashes very quickly, so these should be relatively rare.) - No memory locking/clearing for keys, passphrases, etc. because AFAIK Python does not provide the features needed. On the C (OpenSSL) side things are cleared when the Python objects are deleted. Have fun! Your feedback is welcome. M2Crypto-0.22.6rc4/epydoc.conf0000664000175000017500000000140112212052026016233 0ustar matejmatej00000000000000# Copyright 2009 Heikki Toivonen. All rights reserved. # epydoc --no-private -v --config=epydoc.conf [epydoc] name = M2Crypto url = http://chandlerproject.org/Projects/MeTooCrypto output = html target = doc/api graph = all sourcecode = no private = no modules = ./M2Crypto # Private exclude-introspect = M2Crypto.__m2crypto # Variable shadows module, which causes the module to double in the doc # with second instance showing '. Exclude so we only get one (with '). exclude = M2Crypto.PGP.PublicKey exclude = M2Crypto.PGP.PublicKeyRing exclude = M2Crypto.PGP.packet exclude = M2Crypto.SSL.Cipher exclude = M2Crypto.SSL.Connection exclude = M2Crypto.SSL.Context exclude = M2Crypto.SSL.SSLServer exclude = M2Crypto.SSL.ssl_dispatcher exclude = M2Crypto.SSL.timeout M2Crypto-0.22.6rc4/fedora_setup.sh0000775000175000017500000000057512607370517017153 0ustar matejmatej00000000000000#!/bin/sh # This script is meant to work around the differences on Fedora Core-based # distributions (Redhat, CentOS, ...) compared to other common Linux # distributions. # # Usage: ./fedora_setup.sh [setup.py options] # arch=`uname -m` for i in SWIG/_{ec,evp}.i; do sed -i -e "s/opensslconf\./opensslconf-${arch}\./" "$i" done SWIG_FEATURES=-cpperraswarn python setup.py $* M2Crypto-0.22.6rc4/setup.py0000664000175000017500000001425012613362214015631 0ustar matejmatej00000000000000#!/usr/bin/env python """ Distutils/setuptools installer for M2Crypto. Copyright (c) 1999-2004, Ng Pheng Siong. All rights reserved. Portions created by Open Source Applications Foundation (OSAF) are Copyright (C) 2004-2007 OSAF. All Rights Reserved. Copyright 2008-2011 Heikki Toivonen. All rights reserved. """ import sys requires_list = [] if sys.version_info <= (2, 6): requires_list.append("unittest2") import os # noqa import platform try: from setuptools import setup from setuptools.command import build_ext except ImportError: from distutils.core import setup from distutils.command import build_ext from distutils.core import Extension from distutils.file_util import copy_file class _M2CryptoBuildExt(build_ext.build_ext): '''Specialization of build_ext to enable swig_opts to inherit any include_dirs settings made at the command line or in a setup.cfg file''' user_options = build_ext.build_ext.user_options + \ [('openssl=', 'o', 'Prefix for openssl installation location')] def initialize_options(self): '''Overload to enable custom openssl settings to be picked up''' build_ext.build_ext.initialize_options(self) # openssl is the attribute corresponding to openssl directory prefix # command line option if os.name == 'nt': self.libraries = ['ssleay32', 'libeay32'] self.openssl = 'c:\\pkg' else: self.libraries = ['ssl', 'crypto'] self.openssl = '/usr' def finalize_options(self): '''Overloaded build_ext implementation to append custom openssl include file and library linking options''' build_ext.build_ext.finalize_options(self) openssl_include_dir = os.path.join(self.openssl, 'include') openssl_library_dir = os.path.join(self.openssl, 'lib') self.swig_opts = ['-I%s' % i for i in self.include_dirs + [openssl_include_dir]] self.swig_opts.append('-includeall') self.swig_opts.append('-cpperraswarn') self.swig_opts.append('-modern') self.swig_opts.append('-builtin') # These two lines are a workaround for # http://bugs.python.org/issue2624 , hard-coding that we are only # building a single extension with a known path; a proper patch to # distutils would be in the run phase, when extension name and path are # known. self.swig_opts.append('-outdir') self.swig_opts.append(os.path.join(self.build_lib, 'M2Crypto')) # Fedora does hat tricks. if platform.linux_distribution()[0] in ['Fedora', 'CentOS']: if platform.architecture()[0] == '64bit': self.swig_opts.append('-D__x86_64__') elif platform.architecture()[0] == '32bit': self.swig_opts.append('-D__i386__') self.include_dirs += [os.path.join(self.openssl, openssl_include_dir), os.path.join(os.getcwd(), 'SWIG')] if sys.platform == 'cygwin': # Cygwin SHOULD work (there's code in distutils), but # if one first starts a Windows command prompt, then bash, # the distutils code does not seem to work. If you start # Cygwin directly, then it would work even without this change. # Someday distutils will be fixed and this won't be needed. self.library_dirs += [os.path.join(self.openssl, 'bin')] self.library_dirs += [os.path.join(self.openssl, openssl_library_dir)] def run(self): '''Overloaded build_ext implementation to allow inplace=1 to work, which is needed for (python setup.py test).''' # This is another workaround for http://bugs.python.org/issue2624 + the # corresponding lack of support in setuptools' test command. Note that # just using self.inplace in finalize_options() above does not work # because swig is not rerun if the __m2crypto.so extension exists. # Again, hard-coding our extension name and location. build_ext.build_ext.run(self) if self.inplace: copy_file(os.path.join(self.build_lib, 'M2Crypto', '_m2crypto.py'), os.path.join('M2Crypto', '_m2crypto.py'), verbose=self.verbose, dry_run=self.dry_run) if sys.platform == 'darwin': my_extra_compile_args = ["-Wno-deprecated-declarations"] else: my_extra_compile_args = [] m2crypto = Extension(name='M2Crypto.__m2crypto', sources=['SWIG/_m2crypto.i'], extra_compile_args=['-DTHREADING'], # Uncomment to build Universal Mac binaries #extra_link_args = ['-Wl,-search_paths_first'], ) setup(name='M2Crypto', version='0.22.6rc4', description='M2Crypto: A Python crypto and SSL toolkit', long_description='''\ M2Crypto is the most complete Python wrapper for OpenSSL featuring RSA, DSA, DH, EC, HMACs, message digests, symmetric ciphers (including AES); SSL functionality to implement clients and servers; HTTPS extensions to Python's httplib, urllib, and xmlrpclib; unforgeable HMAC'ing AuthCookies for web session management; FTP/TLS client and server; S/MIME; ZServerSSL: A HTTPS server for Zope and ZSmime: An S/MIME messenger for Zope. M2Crypto can also be used to provide SSL for Twisted.''', license='BSD-style license', platforms=['any'], author='Ng Pheng Siong', author_email='ngps at sandbox rulemaker net', maintainer='Matej Cepl', maintainer_email='mcepl@cepl.eu', url='https://gitlab.com/m2crypto/m2crypto', packages=['M2Crypto', 'M2Crypto.SSL', 'M2Crypto.PGP'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Operating System :: OS Independent', 'Programming Language :: C', 'Programming Language :: Python', 'Topic :: Security :: Cryptography', 'Topic :: Software Development :: Libraries :: Python Modules', ], ext_modules=[m2crypto], test_suite='tests.alltests.suite', install_requires=requires_list, cmdclass={'build_ext': _M2CryptoBuildExt} ) M2Crypto-0.22.6rc4/PKG-INFO0000664000175000017500000000216012613362233015212 0ustar matejmatej00000000000000Metadata-Version: 1.1 Name: M2Crypto Version: 0.22.6rc4 Summary: M2Crypto: A Python crypto and SSL toolkit Home-page: https://gitlab.com/m2crypto/m2crypto Author: Matej Cepl Author-email: mcepl@cepl.eu License: BSD-style license Description: M2Crypto is the most complete Python wrapper for OpenSSL featuring RSA, DSA, DH, EC, HMACs, message digests, symmetric ciphers (including AES); SSL functionality to implement clients and servers; HTTPS extensions to Python's httplib, urllib, and xmlrpclib; unforgeable HMAC'ing AuthCookies for web session management; FTP/TLS client and server; S/MIME; ZServerSSL: A HTTPS server for Zope and ZSmime: An S/MIME messenger for Zope. M2Crypto can also be used to provide SSL for Twisted. Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Operating System :: OS Independent Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Topic :: Security :: Cryptography Classifier: Topic :: Software Development :: Libraries :: Python Modules M2Crypto-0.22.6rc4/setup.cfg0000664000175000017500000000007312613362233015737 0ustar matejmatej00000000000000[egg_info] tag_build = tag_svn_revision = 0 tag_date = 0