2to3 -f except
[sfa.git] / sfa / trust / credential.py
index 6ef5e30..37af67b 100644 (file)
@@ -26,6 +26,8 @@
 # Credentials are signed XML files that assign a subject gid privileges to an object gid
 ##
 
+from __future__ import print_function
+
 import os, os.path
 import subprocess
 from types import StringTypes
@@ -181,21 +183,27 @@ class Signature(object):
         self.gid = gid
 
     def decode(self):
+        # Helper function to pull characters off the front of a string if present
+        def remove_prefix(text, prefix):
+            if text and prefix and text.startswith(prefix):
+                return text[len(prefix):]
+            return text
+
         try:
             doc = parseString(self.xml)
-        except ExpatError,e:
+        except ExpatError as e:
             logger.log_exc ("Failed to parse credential, %s"%self.xml)
             raise
         sig = doc.getElementsByTagName("Signature")[0]
         ## This code until the end of function rewritten by Aaron Helsinger
-        ref_id = sig.getAttribute("xml:id").strip().strip("Sig_")
+        ref_id = remove_prefix(sig.getAttribute("xml:id").strip(), "Sig_")
         # The xml:id tag is optional, and could be in a 
         # Reference xml:id or Reference UID sub element instead
         if not ref_id or ref_id == '':
             reference = sig.getElementsByTagName('Reference')[0]
-            ref_id = reference.getAttribute('xml:id').strip().strip('Sig_')
+            ref_id = remove_prefix(reference.getAttribute('xml:id').strip(), "Sig_")
             if not ref_id or ref_id == '':
-                ref_id = reference.getAttribute('URI').strip().strip('#')
+                ref_id = remove_prefix(reference.getAttribute('URI').strip(), "#")
         self.set_refid(ref_id)
         keyinfos = sig.getElementsByTagName("X509Data")
         gids = None
@@ -242,7 +250,7 @@ def filter_creds_by_caller(creds, caller_hrn_list):
         for cred in creds:
             try:
                 tmp_cred = Credential(string=cred)
-                if tmp_cred.get_cred_type() != Credential.SFA_CREDENTIAL_TYPE:
+                if tmp_cred.type != Credential.SFA_CREDENTIAL_TYPE:
                     continue
                 if tmp_cred.get_gid_caller().get_hrn() in caller_hrn_list:
                     caller_creds.append(cred)
@@ -273,17 +281,17 @@ class Credential(object):
         self.signature = None
         self.xml = None
         self.refid = None
-        self.cred_type = Credential.SFA_CREDENTIAL_TYPE
+        self.type = Credential.SFA_CREDENTIAL_TYPE
         self.version = None
 
         if cred:
             if isinstance(cred, StringTypes):
                 string = cred
-                self.cred_type = Credential.SFA_CREDENTIAL_TYPE
+                self.type = Credential.SFA_CREDENTIAL_TYPE
                 self.version = '3'
             elif isinstance(cred, dict):
                 string = cred['geni_value']
-                self.cred_type = cred['geni_type']
+                self.type = cred['geni_type']
                 self.version = cred['geni_version']
 
         if string or filename:
@@ -299,19 +307,25 @@ class Credential(object):
             else:
                 self.xml = str
                 self.decode()
-
-        # Find an xmlsec1 path
-        self.xmlsec_path = ''
-        paths = ['/usr/bin','/usr/local/bin','/bin','/opt/bin','/opt/local/bin']
-        for path in paths:
-            if os.path.isfile(path + '/' + 'xmlsec1'):
-                self.xmlsec_path = path + '/' + 'xmlsec1'
-                break
-        if not self.xmlsec_path:
-            logger.warn("Could not locate binary for xmlsec1 - SFA will be unable to sign stuff !!")
-
-    def get_cred_type(self): 
-        return self.cred_type
+        # not strictly necessary but won't hurt either
+        self.get_xmlsec1_path()
+
+    @staticmethod
+    def get_xmlsec1_path():
+        if not getattr(Credential, 'xmlsec1_path', None):
+            # Find a xmlsec1 binary path
+            Credential.xmlsec1_path = ''
+            paths = ['/usr/bin', '/usr/local/bin', '/bin', '/opt/bin', '/opt/local/bin']
+            try:     paths += os.getenv('PATH').split(':')
+            except:  pass
+            for path in paths:
+                xmlsec1 = os.path.join(path, 'xmlsec1')
+                if os.path.isfile(xmlsec1):
+                    Credential.xmlsec1_path = xmlsec1
+                    break
+        if not Credential.xmlsec1_path:
+            logger.error("Could not locate required binary 'xmlsec1' - SFA will be unable to sign stuff !!")
+        return Credential.xmlsec1_path
 
     def get_subject(self):
         if not self.gidObject:
@@ -686,8 +700,11 @@ class Credential(object):
         # Call out to xmlsec1 to sign it
         ref = 'Sig_%s' % self.get_refid()
         filename = self.save_to_random_tmp_file()
-        command='%s --sign --node-id "%s" --privkey-pem %s,%s %s' \
-            % (self.xmlsec_path, ref, self.issuer_privkey, ",".join(gid_files), filename)
+        xmlsec1 = self.get_xmlsec1_path()
+        if not xmlsec1:
+            raise Exception("Could not locate required 'xmlsec1' program")
+        command = '%s --sign --node-id "%s" --privkey-pem %s,%s %s' \
+            % (xmlsec1, ref, self.issuer_privkey, ",".join(gid_files), filename)
 #        print 'command',command
         signed = os.popen(command).read()
         os.remove(filename)
@@ -713,7 +730,7 @@ class Credential(object):
         doc = None
         try:
             doc = parseString(self.xml)
-        except ExpatError,e:
+        except ExpatError as e:
             raise CredentialNotVerifiable("Malformed credential")
         doc = parseString(self.xml)
         sigs = []
@@ -843,7 +860,7 @@ class Credential(object):
                     # or non PEM files
                     trusted_cert_objects.append(GID(filename=f))
                     ok_trusted_certs.append(f)
-                except Exception, exc:
+                except Exception as exc:
                     logger.error("Failed to load trusted cert from %s: %r"%( f, exc))
             trusted_certs = ok_trusted_certs
 
@@ -884,7 +901,10 @@ class Credential(object):
             #cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs])
             #command = '{} --verify --node-id "{}" {} {} 2>&1'.\
             #          format(self.xmlsec_path, ref, cert_args, filename)
-            command = [ self.xmlsec_path, '--verify', '--node-id', ref ]
+            xmlsec1 = self.get_xmlsec1_path()
+            if not xmlsec1:
+                raise Exception("Could not locate required 'xmlsec1' program")
+            command = [ xmlsec1, '--verify', '--node-id', ref ]
             for trusted in trusted_certs:
                 command += ["--trusted-pem", trusted ]
             command += [ filename ]
@@ -1136,7 +1156,7 @@ class Credential(object):
     #
     # @param dump_parents If true, also dump the parent certificates
     def dump (self, *args, **kwargs):
-        print self.dump_string(*args, **kwargs)
+        print(self.dump_string(*args, **kwargs))
 
     # SFA code ignores show_xml and disables printing the cred xml
     def dump_string(self, dump_parents=False, show_xml=False):
@@ -1179,7 +1199,7 @@ class Credential(object):
                 result += "\nEnd XML\n"
             except:
                 import traceback
-                print "exc. Credential.dump_string / XML"
+                print("exc. Credential.dump_string / XML")
                 traceback.print_exc()
 
         return result