remove unnecessary code
[sfa.git] / sfa / trust / auth.py
1 #
2 # SfaAPI authentication 
3 #
4 ### $Id$
5 ### $URL$
6 #
7
8 import time
9
10 from sfa.trust.credential import Credential
11 from sfa.trust.trustedroot import TrustedRootList
12 from sfa.trust.rights import RightList
13 from sfa.util.faults import *
14 from sfa.trust.hierarchy import Hierarchy
15 from sfa.util.config import *
16 from sfa.util.namespace import *
17 from sfa.trust.gid import GID
18 from sfa.util.sfaticket import *
19
20 class Auth:
21     """
22     Credential based authentication
23     """
24
25     def __init__(self, peer_cert = None, config = None ):
26         self.peer_cert = peer_cert
27         self.hierarchy = Hierarchy()
28         if not config:
29             self.config = Config()
30         self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
31
32
33     def check(self, cred, operation):
34         """
35         Check the credential against the peer cert (callerGID included 
36         in the credential matches the caller that is connected to the 
37         HTTPS connection, check if the credential was signed by a 
38         trusted cert and check if the credential is allowd to perform 
39         the specified operation.    
40         """
41         self.client_cred = Credential(string = cred)
42         self.client_gid = self.client_cred.get_gid_caller()
43         self.object_gid = self.client_cred.get_gid_object()
44         
45         # make sure the client_gid is not blank
46         if not self.client_gid:
47             raise MissingCallerGID(self.client_cred.get_subject())
48        
49         # validate the client cert if it exists
50         if self.peer_cert:
51             self.verifyPeerCert(self.peer_cert, self.client_gid)                   
52
53         # make sure the client is allowed to perform the operation
54         if operation:
55             if not self.client_cred.can_perform(operation):
56                 raise InsufficientRights(operation)
57
58         if self.trusted_cert_list:
59             self.client_cred.verify_chain(self.trusted_cert_list)
60             if self.client_gid:
61                 self.client_gid.verify_chain(self.trusted_cert_list)
62             if self.object_gid:
63                 self.object_gid.verify_chain(self.trusted_cert_list)
64         else:
65            raise MissingTrustedRoots(self.config.get_trustedroots_dir())
66
67         return True
68
69     def check_ticket(self, ticket):
70         """
71         Check if the tickt was signed by a trusted cert
72         """
73         if self.trusted_cert_list:
74             client_ticket = SfaTicket(string=ticket)
75             client_ticket.verify_chain(self.trusted_cert_list)
76         else:
77            raise MissingTrustedRoots(self.config.get_trustedroots_dir())
78
79         return True 
80
81     def verifyPeerCert(self, cert, gid):
82         # make sure the client_gid matches client's certificate
83         if not cert.is_pubkey(gid.get_pubkey()):
84             raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())            
85
86     def verifyGidRequestHash(self, gid, hash, arglist):
87         key = gid.get_pubkey()
88         if not key.verify_string(str(arglist), hash):
89             raise BadRequestHash(hash)
90
91     def verifyCredRequestHash(self, cred, hash, arglist):
92         gid = cred.get_gid_caller()
93         self.verifyGidRequestHash(gid, hash, arglist)
94
95     def validateGid(self, gid):
96         if self.trusted_cert_list:
97             gid.verify_chain(self.trusted_cert_list)
98
99     def validateCred(self, cred):
100         if self.trusted_cert_list:
101             cred.verify_chain(self.trusted_cert_list)
102             caller_gid = cred.get_gid_caller()
103             object_gid = cred.get_gid_object()
104             if caller_gid:
105                 caller_gid.verify_chain(self.trusted_cert_list)
106             if object_gid:
107                 object_gid.verify_chain(self.trusted_cert_list)
108
109     def authenticateGid(self, gidStr, argList, requestHash=None):
110         gid = GID(string = gidStr)
111         self.validateGid(gid)
112         # request_hash is optional
113         if requestHash:
114             self.verifyGidRequestHash(gid, requestHash, argList)
115         return gid
116
117     def authenticateCred(self, credStr, argList, requestHash=None):
118         cred = Credential(string = credStr)
119         self.validateCred(cred)
120         # request hash is optional
121         if requestHash:
122             self.verifyCredRequestHash(cred, requestHash, argList)
123         return cred
124
125     def authenticateCert(self, certStr, requestHash):
126         cert = Certificate(string=certStr)
127         self.validateCert(self, cert)   
128
129     def gidNoop(self, gidStr, value, requestHash):
130         self.authenticateGid(gidStr, [gidStr, value], requestHash)
131         return value
132
133     def credNoop(self, credStr, value, requestHash):
134         self.authenticateCred(credStr, [credStr, value], requestHash)
135         return value
136
137     def verify_cred_is_me(self, credential):
138         is_me = False 
139         cred = Credential(string=credential)
140         caller_gid = cred.get_gid_caller()
141         caller_hrn = caller_gid.get_hrn()
142         if caller_hrn != self.config.SFA_INTERFACE_HRN:
143             raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
144
145         return   
146         
147     def get_auth_info(self, auth_hrn):
148         """
149         Given an authority name, return the information for that authority.
150         This is basically a stub that calls the hierarchy module.
151         
152         @param auth_hrn human readable name of authority  
153         """
154
155         return self.hierarchy.get_auth_info(auth_hrn)
156
157
158     def veriry_auth_belongs_to_me(self, name):
159         """
160         Verify that an authority belongs to our hierarchy. 
161         This is basically left up to the implementation of the hierarchy
162         module. If the specified name does not belong, ane exception is 
163         thrown indicating the caller should contact someone else.
164
165         @param auth_name human readable name of authority
166         """
167
168         # get auth info will throw an exception if the authority doesnt exist
169         self.get_auth_info(name)
170
171
172     def verify_object_belongs_to_me(self, name):
173         """
174         Verify that an object belongs to our hierarchy. By extension,
175         this implies that the authority that owns the object belongs
176         to our hierarchy. If it does not an exception is thrown.
177     
178         @param name human readable name of object        
179         """
180         auth_name = self.get_authority(name)
181         if not auth_name:
182             auth_name = name 
183         if name == self.config.SFA_INTERFACE_HRN:
184             return
185         self.verify_auth_belongs_to_me(auth_name) 
186              
187     def verify_auth_belongs_to_me(self, name):
188         # get auth info will throw an exception if the authority doesnt exist
189         self.get_auth_info(name) 
190
191
192     def verify_object_permission(self, name):
193         """
194         Verify that the object gid that was specified in the credential
195         allows permission to the object 'name'. This is done by a simple
196         prefix test. For example, an object_gid for plc.arizona would 
197         match the objects plc.arizona.slice1 and plc.arizona.
198     
199         @param name human readable name to test  
200         """
201         object_hrn = self.object_gid.get_hrn()
202         if object_hrn == name:
203             return
204         if name.startswith(object_hrn + "."):
205             return
206         #if name.startswith(get_authority(name)):
207             #return
208     
209         raise PermissionError(name)
210
211     def determine_user_rights(self, caller_hrn, record):
212         """
213         Given a user credential and a record, determine what set of rights the
214         user should have to that record.
215         
216         This is intended to replace determine_rights() and
217         verify_cancreate_credential()
218         """
219
220         rl = RightList()
221         type = record['type']
222
223         if type=="slice":
224             researchers = record.get("researcher", [])
225             pis = record.get("PI", [])
226             if (caller_hrn in researchers + pis):
227                 rl.add("refresh")
228                 rl.add("embed")
229                 rl.add("bind")
230                 rl.add("control")
231                 rl.add("info")
232
233         elif type == "authority":
234             pis = record.get("PI", [])
235             operators = record.get("operator", [])
236             if (caller_hrn == self.config.SFA_INTERFACE_HRN):
237                 rl.add("authority,sa,ma",)
238             if (caller_hrn in pis):
239                 rl.add("authority,sa")
240             if (caller_hrn in operators):
241                 rl.add("authority,ma")
242
243         elif type == "user":
244             rl.add("refresh")
245             rl.add("resolve")
246             rl.add("info")
247
248         elif type == "node":
249             rl.add("operator")
250
251         return rl
252
253     def verify_cancreate_credential(self, src_cred, record):
254         """
255         Verify that a user can retrive a particular type of credential.
256         For slices, the user must be on the researcher list. For SA and
257         MA the user must be on the pi and operator lists respectively
258         """
259
260         type = record.get_type()
261         cred_object_hrn = src_cred.get_gid_object().get_hrn()
262         if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
263             return
264         if type=="slice":
265             researchers = record.get("researcher", [])
266             if not (cred_object_hrn in researchers):
267                 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
268         elif type == "sa":
269             pis = record.get("pi", [])
270             if not (cred_object_hrn in pis):
271                 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
272         elif type == "ma":
273             operators = record.get("operator", [])
274             if not (cred_object_hrn in operators):
275                 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
276
277     def get_authority(self, hrn):
278         return get_authority(hrn)