Better regexp use
[snf-occi] / snfOCCI / voms / __init__.py
1 import collections
2 import commands
3 import ctypes
4 import os
5 import tempfile 
6
7 import M2Crypto
8
9 from snfOCCI.config import VOMS_CONFIG
10 import voms_helper
11 import exception
12
13 SSL_CLIENT_S_DN_ENV = "SSL_CLIENT_S_DN"
14 SSL_CLIENT_CERT_ENV = "SSL_CLIENT_CERT"
15 SSL_CLIENT_CERT_CHAIN_0_ENV = "SSL_CLIENT_CERT_CHAIN_0"
16
17
18 class VomsError(exception.Error):
19     """Voms credential management error"""
20
21     errors = {
22         0: ('none', None),
23         1: ('nosocket', 'Socket problem'),
24         2: ('noident', 'Cannot identify itself (certificate problem)'),
25         3: ('comm', 'Server problem'),
26         4: ('param', 'Wrong parameters'),
27         5: ('noext', 'VOMS extension missing'),
28         6: ('noinit', 'Initialization error'),
29         7: ('time', 'Error in time checking'),
30         8: ('idcheck', 'User data in extension different from the real'),
31         9: ('extrainfo', 'VO name and URI missing'),
32         10: ('format', 'Wrong data format'),
33         11: ('nodata', 'Empty extension'),
34         12: ('parse', 'Parse error'),
35         13: ('dir', 'Directory error'),
36         14: ('sign', 'Signature error'),
37         15: ('server', 'Unidentifiable VOMS server'),
38         16: ('mem', 'Memory problems'),
39         17: ('verify', 'Generic verification error'),
40         18: ('type', 'Returned data of unknown type'),
41         19: ('order', 'Ordering different than required'),
42         20: ('servercode', 'Error from the server'),
43         21: ('notavail', 'Method not available'),
44     }
45
46     http_codes = {
47         5: (400, "Bad Request"),
48         11: (400, "Bad Request"),
49         14: (401, "Not Authorized"),
50     }
51
52
53 def _get_cert_chain(ssl_info):
54     """Return certificate and chain from the ssl info in M2Crypto format"""
55
56     cert = ssl_info.get(SSL_CLIENT_CERT_ENV, "")
57     chain = ssl_info.get(SSL_CLIENT_CERT_CHAIN_0_ENV, "")
58
59     cert = M2Crypto.X509.load_cert_string(cert)
60     aux = M2Crypto.X509.load_cert_string(chain)
61     chain = M2Crypto.X509.X509_Stack()
62     chain.push(aux)
63
64     return (cert, chain)
65
66
67 def _get_voms_info(ssl_info):
68     """Extract voms info from ssl_info and return dict with it."""
69
70     try:
71         cert, chain = _get_cert_chain(ssl_info)
72     except M2Crypto.X509.X509Error as e:
73         print e
74
75     with voms_helper.VOMS(VOMS_CONFIG["vomsdir_path"],VOMS_CONFIG["ca_path"], VOMS_CONFIG["vomsapi_lib"]) as v:
76
77         voms_data = v.retrieve(cert, chain)
78         
79         
80         if not voms_data:
81             print "error \n"
82             raise VomsError(v.error.value)
83
84         d = {}
85         for attr in ('user', 'userca', 'server', 'serverca',
86                      'voname',  'uri', 'version', 'serial',
87                      ('not_before', 'date1'), ('not_after', 'date2')):
88             if isinstance(attr, basestring):
89                 d[attr] = getattr(voms_data, attr)
90             else:
91                 d[attr[0]] = getattr(voms_data, attr[1])
92
93         d["fqans"] = []
94         for fqan in iter(voms_data.fqan):
95             if fqan is None:
96                 break
97             d["fqans"].append(fqan)
98
99     return d
100
101
102 def _split_fqan(fqan):
103         """
104         gets a fqan and returns a tuple containing
105         (vo/groups, role, capability)
106         """
107         l = fqan.split("/")
108         capability = l.pop().split("=")[-1]
109         role = l.pop().split("=")[-1]
110         vogroup = "/".join(l)
111         return (vogroup, role, capability)
112     
113
114 def _split_fqan(fqan):
115         """
116         gets a fqan and returns a tuple containing
117         (vo/groups, role, capability)
118         """
119         l = fqan.split("/")
120         capability = l.pop().split("=")[-1]
121         role = l.pop().split("=")[-1]
122         vogroup = "/".join(l)
123         return (vogroup, role, capability)
124
125
126 def authenticate(ssl_data):
127     try:
128         voms_info = _get_voms_info(ssl_data)
129     except VomsError as e:
130         raise e
131
132     user_dn = voms_info["user"]
133     user_vo = voms_info["voname"]
134     user_fqans = voms_info["fqans"]
135
136     return user_dn, user_vo, user_fqans