d3ed5daad9e0ea43aad9643e332de387dd43c572
[cascardo/ipsilon.git] / ipsilon / providers / saml2 / provider.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 from ipsilon.providers.common import ProviderException
21 import cherrypy
22 import lasso
23
24
25 NAMEID_MAP = {
26     'email': lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL,
27     'encrypted': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENCRYPTED,
28     'entity': lasso.SAML2_NAME_IDENTIFIER_FORMAT_ENTITY,
29     'kerberos': lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS,
30     'persistent': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
31     'transient': lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT,
32     'unspecified': lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED,
33     'windows': lasso.SAML2_NAME_IDENTIFIER_FORMAT_WINDOWS,
34     'x509': lasso.SAML2_NAME_IDENTIFIER_FORMAT_X509,
35 }
36
37
38 class InvalidProviderId(ProviderException):
39
40     def __init__(self, code):
41         message = 'Invalid Provider ID: %s' % code
42         super(InvalidProviderId, self).__init__(message)
43         self._debug(message)
44
45
46 class NameIdNotAllowed(Exception):
47
48     def __init__(self):
49         message = 'The specified Name ID is not allowed'
50         super(NameIdNotAllowed, self).__init__(message)
51         self.message = message
52
53     def __str__(self):
54         return repr(self.message)
55
56
57 class ServiceProvider(object):
58
59     def __init__(self, config, provider_id):
60         self.cfg = config
61         data = self.cfg.get_data(name='id', value=provider_id)
62         if len(data) != 1:
63             raise InvalidProviderId('multiple matches')
64         idval = data.keys()[0]
65         data = self.cfg.get_data(idval=idval)
66         self._properties = data[idval]
67
68     @property
69     def provider_id(self):
70         return self._properties['id']
71
72     @property
73     def name(self):
74         return self._properties['name']
75
76     @property
77     def allowed_namedids(self):
78         if 'allowed nameid' in self._properties:
79             return self._properties['allowed nameid']
80         else:
81             return self.cfg.default_allowed_nameids
82
83     @property
84     def default_nameid(self):
85         if 'default nameid' in self._properties:
86             return self._properties['default nameid']
87         else:
88             return self.cfg.default_nameid
89
90     def get_valid_nameid(self, nip):
91         self._debug('Requested NameId [%s]' % (nip.format,))
92         if nip.format is None:
93             return NAMEID_MAP[self.default_nameid]
94         elif nip.format == lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED:
95             return NAMEID_MAP[self.default_nameid]
96         else:
97             allowed = self.allowed_namedids
98             self._debug('Allowed NameIds %s' % (repr(allowed)))
99             for nameid in allowed:
100                 if nip.format == NAMEID_MAP[nameid]:
101                     return nip.format
102         raise NameIdNotAllowed(nip.format)
103
104     def _debug(self, fact):
105         if cherrypy.config.get('debug', False):
106             cherrypy.log(fact)
107
108     def normalize_username(self, username):
109         if 'strip domain' in self._properties:
110             return username.split('@', 1)[0]
111         return username