woraround for undefined 'options' in checkCredentials
[sfa.git] / sfa / trust / auth.py
index d72c3f8..0b4d337 100644 (file)
@@ -4,7 +4,8 @@
 import sys
 
 from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \
-    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden
+    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden, \
+    BadArgs
 from sfa.util.sfalogging import logger
 from sfa.util.config import Config
 from sfa.util.xrn import Xrn, get_authority
@@ -16,6 +17,7 @@ from sfa.trust.credential import Credential
 from sfa.trust.trustedroots import TrustedRoots
 from sfa.trust.hierarchy import Hierarchy
 from sfa.trust.sfaticket import SfaTicket
+from sfa.trust.speaksfor_util import determine_speaks_for
 
 
 class Auth:
@@ -34,7 +36,21 @@ class Auth:
         self.trusted_cert_list = TrustedRoots(self.config.get_trustedroots_dir()).get_list()
         self.trusted_cert_file_list = TrustedRoots(self.config.get_trustedroots_dir()).get_file_list()
 
-    def checkCredentials(self, creds, operation, xrns=[], check_sliver_callback=None):
+    def checkCredentials(self, creds, operation, xrns=[], check_sliver_callback=None, speaking_for_hrn=None):
+
+        def log_invalid_cred(cred):
+            cred_obj=Credential(string=cred)
+            logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
+            error = sys.exc_info()[:2]
+            return error
+
+        # if xrns are specified they cannot be None or empty string
+        if xrns:
+            for xrn in xrns:
+                if not xrn:
+                    raise BadArgs("Invalid urn or hrn")
+
+        
         if not isinstance(xrns, list):
             xrns = [xrns]
 
@@ -51,16 +67,27 @@ class Auth:
         # won't work if either creds or hrns is empty - let's make it more explicit
         if not creds: raise Forbidden("no credential provided")
         if not hrns: hrns = [None]
-        for cred in creds:
-            for hrn in hrns:
-                try:
-                    self.check(cred, operation, hrn)
-                    valid.append(cred)
-                except:
-                    cred_obj=Credential(cred=cred)
-                    logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
-                    error = sys.exc_info()[:2]
-                    continue
+        error=[None,None]
+
+        # if speaks for gid matches caller cert then we've found a valid
+        # speaks for credential
+        ### Thierry : we have no options to pass determine_speaks_for in this context
+        # so only as a workaround here:
+        options={}
+        speaks_for_gid = determine_speaks_for(logger, creds, self.peer_cert, \
+                                              options, self.trusted_cert_list)
+
+        if self.peer_cert and \
+           not self.peer_cert.is_pubkey(speaks_for_gid.get_pubkey()):
+            valid = creds
+        else:
+            for cred in creds:
+                for hrn in hrns:
+                    try:
+                        self.check(cred, operation, hrn)
+                        valid.append(cred)
+                    except:
+                        error = log_invalid_cred(cred)
         
         # make sure all sliver xrns are validated against the valid credentials
         if sliver_xrns:
@@ -71,10 +98,10 @@ class Auth:
             check_sliver_callback(valid, sliver_xrns)
                 
         if not len(valid):
-            msg = "Valid credential not found for method: %s" % operation
-            if xrns:
-                msg += " target: %s" % xrns 
-            raise Forbidden(msg)
+            raise Forbidden("Invalid credential %s -- %s"%(error[0],error[1]))
+        
+        if speaking_for_hrn and not speaks_for_cred:
+            raise InsufficientRights('Access denied: "geni_speaking_for" option specified but no valid speaks for credential found: %s -- %s' % (error[0],error[1]))
         
         return valid