source: fedd/federation/util.py @ 227f558

axis_examplecompt_changesinfo-opsversion-1.30version-2.00version-3.01version-3.02
Last change on this file since 227f558 was 12e6ca8, checked in by Ted Faber <faber@…>, 16 years ago

Code to accept self signed certs under older M2Crypto

  • Property mode set to 100644
File size: 4.0 KB
Line 
1#!/usr/local/bin/python
2
3import re
4import string
5import logging
6
7from M2Crypto import SSL
8from fedid import fedid
9
10class fedd_ssl_context(SSL.Context):
11    """
12    Simple wrapper around an M2Crypto.SSL.Context to initialize it for fedd.
13    """
14    def __init__(self, my_cert, trusted_certs=None, password=None):
15        """
16        construct a fedd_ssl_context
17
18        @param my_cert: PEM file with my certificate in it
19        @param trusted_certs: PEM file with trusted certs in it (optional)
20        """
21        SSL.Context.__init__(self)
22
23        # load_cert takes a callback to get a password, not a password, so if
24        # the caller provided a password, this creates a nonce callback using a
25        # lambda form.
26        if password != None and not callable(password):
27            # This is cute.  password = lambda *args: password produces a
28            # function object that returns itself rather than one that returns
29            # the object itself.  This is because password is an object
30            # reference and after the assignment it's a lambda.  So we assign
31            # to a temp.
32            pwd = password
33            password =lambda *args: pwd
34
35        if password != None:
36            self.load_cert(my_cert, callback=password)
37        else:
38            self.load_cert(my_cert)
39
40        # If no trusted certificates are specified, allow unknown CAs.
41        if trusted_certs: 
42            self.load_verify_locations(trusted_certs)
43            self.set_verify(SSL.verify_peer, 10)
44        else:
45            # More legacy code.  Recent versions of M2Crypto express the
46            # allow_unknown_ca option through a callback turned to allow it.
47            # Older versions use a standard callback that respects the
48            # attribute.  This should work under both regines.
49            callb = getattr(SSL.cb, 'ssl_verify_callback_allow_unknown_ca', 
50                    SSL.cb.ssl_verify_callback)
51            self.set_allow_unknown_ca(True)
52            self.set_verify(SSL.verify_peer, 10, callback=callb)
53
54def read_simple_accessdb(fn, auth, mask=[]):
55    """
56    Read a simple access database.  Each line is a fedid (of the form
57    fedid:hexstring) and a comma separated list of atributes to be assigned to
58    it.  This parses out the fedids and adds the attributes to the authorizer.
59    comments (preceded with a #) and blank lines are ignored.  Exceptions (e.g.
60    file exceptions and ValueErrors from badly parsed lines) are propagated.
61    """
62
63    rv = [ ]
64    lineno = 0
65    fedid_line = re.compile("fedid:([" + string.hexdigits + "]+)\s+" +\
66            "(\w+\s*(,\s*\w+)*)")
67
68    # If a single string came in, make it a list
69    if isinstance(mask, basestring): mask = [ mask ]
70
71    f = open(fn, 'r')
72    for line in f:
73        lineno += 1
74        line = line.strip()
75        if line.startswith('#') or len(line) == 0: 
76            continue
77        m = fedid_line.match(line)
78        if m :
79            fid = fedid(hexstr=m.group(1))
80            for a in [ a.strip() for a in m.group(2).split(",") \
81                    if not mask or a.strip() in mask ]:
82                auth.set_attribute(fid, a.strip())
83        else:
84            raise ValueError("Badly formatted line in accessdb: %s line %d" %\
85                    (nf, lineno))
86    f.close()
87    return rv
88       
89
90def pack_id(id):
91    """
92    Return a dictionary with the field name set by the id type.  Handy for
93    creating dictionaries to be converted to messages.
94    """
95    if isinstance(id, fedid): return { 'fedid': id }
96    elif id.startswith("http:") or id.startswith("https:"): return { 'uri': id }
97    else: return { 'localname': id}
98
99def unpack_id(id):
100    """return id as a type determined by the key"""
101    for k in ("localname", "fedid", "uri", "kerberosUsername"):
102        if id.has_key(k): return id[k]
103    return None
104
105def set_log_level(config, sect, log):
106    """ Set the logging level to the value passed in sect of config."""
107    # The getattr sleight of hand finds the logging level constant
108    # corrersponding to the string.  We're a little paranoid to avoid user
109    # mayhem.
110    if config.has_option(sect, "log_level"):
111        level_str = config.get(sect, "log_level")
112        try:
113            level = int(getattr(logging, level_str.upper(), -1))
114
115            if  logging.DEBUG <= level <= logging.CRITICAL:
116                log.setLevel(level)
117            else:
118                log.error("Bad experiment_log value: %s" % level_str)
119
120        except ValueError:
121            log.error("Bad experiment_log value: %s" % level_str)
122
Note: See TracBrowser for help on using the repository browser.