# Credentials are signed XML files that assign a subject gid privileges to an object gid
##
-import os
+import os, os.path
+import subprocess
from types import StringTypes
import datetime
from StringIO import StringIO
return subject
# sounds like this should be __repr__ instead ??
- def get_summary_tostring(self):
+ def pretty_cred(self):
if not self.gidObject:
self.decode()
obj = self.gidObject.get_printable_subject()
caller = self.gidCaller.get_printable_subject()
exp = self.get_expiration()
# Summarize the rights too? The issuer?
- return "[ Grant %s rights on %s until %s ]" % (caller, obj, exp)
+ return "[ Grant {caller} rights on {obj} until {exp} ]".format(**locals())
def get_signature(self):
if not self.signature:
# Below throws InUse exception if we forgot to clone the attribute first
oldAttr = signed_cred.setAttributeNode(attr.cloneNode(True))
if oldAttr and oldAttr.value != attr.value:
- msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value)
+ msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % \
+ (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value)
logger.warn(msg)
#raise CredentialNotVerifiable("Can't encode new valid delegated credential: %s" % msg)
xmlschema = etree.XMLSchema(schema_doc)
if not xmlschema.validate(tree):
error = xmlschema.error_log.last_error
- message = "%s: %s (line %s)" % (self.get_summary_tostring(), error.message, error.line)
+ message = "%s: %s (line %s)" % (self.pretty_cred(), error.message, error.line)
raise CredentialNotVerifiable(message)
if trusted_certs_required and trusted_certs is None:
# make sure it is not expired
if self.get_expiration() < datetime.datetime.utcnow():
- raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.strftime(SFATIME_FORMAT)))
+ raise CredentialNotVerifiable("Credential %s expired at %s" % \
+ (self.pretty_cred(),
+ self.expiration.strftime(SFATIME_FORMAT)))
# Verify the signatures
filename = self.save_to_random_tmp_file()
- if trusted_certs is not None:
- cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs])
# If caller explicitly passed in None that means skip cert chain validation.
# - Strange and not typical
if trusted_certs is None:
break
-# print "Doing %s --verify --node-id '%s' %s %s 2>&1" % \
-# (self.xmlsec_path, ref, cert_args, filename)
- verified = os.popen('%s --verify --node-id "%s" %s %s 2>&1' \
- % (self.xmlsec_path, ref, cert_args, filename)).read()
- if not verified.strip().startswith("OK"):
+ # Thierry - jan 2015
+ # up to fedora20 we used os.popen and checked that the output begins with OK
+ # turns out, with fedora21, there is extra input before this 'OK' thing
+ # looks like we're better off just using the exit code - that's what it is made for
+ #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 ]
+ for trusted in trusted_certs:
+ command += ["--trusted-pem", trusted ]
+ command += [ filename ]
+ logger.debug("Running " + " ".join(command))
+ try:
+ verified = subprocess.check_output(command, stderr=subprocess.STDOUT)
+ logger.debug("xmlsec command returned {}".format(verified))
+ if "OK\n" not in verified:
+ logger.warning("WARNING: xmlsec1 seemed to return fine but without a OK in its output")
+ except subprocess.CalledProcessError as e:
+ verified = e.output
# xmlsec errors have a msg= which is the interesting bit.
mstart = verified.find("msg=")
msg = ""
mstart = mstart + 4
mend = verified.find('\\', mstart)
msg = verified[mstart:mend]
- raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s %s" % (self.get_summary_tostring(), ref, msg, verified.strip()))
+ logger.warning("Credential.verify - failed - xmlsec1 returned {}".format(verified.strip()))
+ raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s" % \
+ (self.pretty_cred(), ref, msg))
os.remove(filename)
# Verify the parents (delegation)
# Give up, credential does not pass issuer verification
- raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
+ raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % \
+ (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
##
# parents rights (and check delegate bits)
if not parent_cred.get_privileges().is_superset(self.get_privileges()):
raise ChildRightsNotSubsetOfParent(("Parent cred ref %s rights " % parent_cred.get_refid()) +
- self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % (self.get_summary_tostring(), self.get_refid())) +
+ self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % \
+ (self.get_summary_tostring(), self.get_refid())) +
self.get_privileges().save_to_string())
# make sure my target gid is the same as the parent's
if not parent_cred.get_gid_object().save_to_string() == \
self.get_gid_object().save_to_string():
- raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+ raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % \
+ (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
# make sure my expiry time is <= my parent's
if not parent_cred.get_expiration() >= self.get_expiration():
- raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+ raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % \
+ (self.pretty_cred(), parent_cred.pretty_cred()))
# make sure my signer is the parent's caller
if not parent_cred.get_gid_caller().save_to_string(False) == \
self.get_signature().get_issuer_gid().save_to_string(False):
- raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+ raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % \
+ (self.pretty_cred(), parent_cred.pretty_cred()))
# Recurse
if parent_cred.parent:
# else this looks like a delegated credential, and the real caller is the issuer
else:
actual_caller_hrn=issuer_hrn
- logger.info("actual_caller_hrn: caller_hrn=%s, issuer_hrn=%s, returning %s"%(caller_hrn,issuer_hrn,actual_caller_hrn))
+ logger.info("actual_caller_hrn: caller_hrn=%s, issuer_hrn=%s, returning %s"
+ %(caller_hrn,issuer_hrn,actual_caller_hrn))
return actual_caller_hrn
##