def multiple_signatures(self, statement, to_sign, key=None, key_file=None): """ Sign multiple parts of a statement :param statement: The statement that should be sign, this is XML text :param to_sign: A list of (items, id, id attribute name) tuples that specifies what to sign :param key: A key that should be used for doing the signing :param key_file: A file that contains the key to be used :return: A possibly multiple signed statement """ for (item, sid, id_attr) in to_sign: if not sid: if not item.id: sid = item.id = sid() else: sid = item.id if not item.signature: item.signature = pre_signature_part(sid, self.cert_file) statement = self.sign_statement(statement, class_name(item), key=key, key_file=key_file, node_id=sid, id_attr=id_attr) return statement
def entities_descriptor(eds, valid_for, name, ident, sign, secc): entities = md.EntitiesDescriptor(entity_descriptor=eds) if valid_for: entities.valid_until = in_a_while(hours=valid_for) if name: entities.name = name if ident: entities.id = ident if sign: if not ident: ident = sid() if not secc.key_file: raise Exception("If you want to do signing you should define " + "a key to sign with") if not secc.my_cert: raise Exception("If you want to do signing you should define " + "where your public key are") entities.signature = pre_signature_part(ident, secc.my_cert, 1) entities.id = ident xmldoc = secc.sign_statement("%s" % entities, class_name(entities)) entities = md.entities_descriptor_from_string(xmldoc) return entities
def correctly_signed_message(self, decoded_xml, msgtype, must=False, origdoc=None): """Check if a request is correctly signed, if we have metadata for the entity that sent the info use that, if not use the key that are in the message if any. :param decoded_xml: The SAML message as a XML string :param msgtype: :param must: Whether there must be a signature :param origdoc: :return: """ try: _func = getattr(samlp, "%s_from_string" % msgtype) except AttributeError: _func = getattr(saml, "%s_from_string" % msgtype) msg = _func(decoded_xml) if not msg: raise TypeError("Not a %s" % msgtype) if not msg.signature: if must: raise SignatureError("Missing must signature") else: return msg return self._check_signature(decoded_xml, msg, class_name(msg), origdoc, must=must)
def multiple_signatures(self, statement, to_sign, key=None, key_file=None): """ Sign multiple parts of a statement :param statement: The statement that should be sign, this is XML text :param to_sign: A list of (items, id, id attribute name) tuples that specifies what to sign :param key: A key that should be used for doing the signing :param key_file: A file that contains the key to be used :return: A possibly multiple signed statement """ for (item, sid, id_attr) in to_sign: if not sid: if not item.id: sid = item.id = sid() else: sid = item.id if not item.signature: item.signature = pre_signature_part(sid, self.cert_file) statement = self.sign_statement(statement, class_name(item), key=key, key_file=key_file, node_id=sid, id_attr=id_attr) return statement
def entities_descriptor(eds, valid_for, name, ident, sign, secc): entities = md.EntitiesDescriptor(entity_descriptor=eds) if valid_for: entities.valid_until = in_a_while(hours=valid_for) if name: entities.name = name if ident: entities.id = ident if sign: if not ident: ident = sid() if not secc.key_file: raise Exception("If you want to do signing you should define " + "a key to sign with") if not secc.my_cert: raise Exception("If you want to do signing you should define " + "where your public key are") entities.signature = pre_signature_part(ident, secc.my_cert, 1) entities.id = ident xmldoc = secc.sign_statement("%s" % entities, class_name(entities)) entities = md.entities_descriptor_from_string(xmldoc) return entities
def sign(self, msg, mid=None, to_sign=None, sign_prepare=False): if msg.signature is None: msg.signature = pre_signature_part(msg.id, self.sec.my_cert, 1) if sign_prepare: return msg if mid is None: mid = msg.id try: to_sign.append([(class_name(msg), mid)]) except AttributeError: to_sign = [(class_name(msg), mid)] logger.info("REQUEST: %s" % msg) return signed_instance_factory(msg, self.sec, to_sign)
def sign_entity_descriptor(edesc, ident, secc): if not ident: ident = sid() edesc.signature = pre_signature_part(ident, secc.my_cert, 1) edesc.id = ident xmldoc = secc.sign_statement("%s" % edesc, class_name(edesc)) return md.entity_descriptor_from_string(xmldoc)
def sign_entity_descriptor(edesc, ident, secc): if not ident: ident = sid() edesc.signature = pre_signature_part(ident, secc.my_cert, 1) edesc.id = ident xmldoc = secc.sign_statement("%s" % edesc, class_name(edesc)) return md.entity_descriptor_from_string(xmldoc)
def sign_assertion(self, statement, **kwargs): """Sign a SAML assertion. See sign_statement() for the kwargs. :param statement: The statement to be signed :return: The signed statement """ return self.sign_statement(statement, class_name(saml.Assertion()), **kwargs)
def sign_attribute_query(self, statement, **kwargs): """Sign a SAML attribute query. See sign_statement() for the kwargs. :param statement: The statement to be signed :return: The signed statement """ return self.sign_statement(statement, class_name( samlp.AttributeQuery()), **kwargs)
def sign_assertion(self, statement, **kwargs): """Sign a SAML assertion. See sign_statement() for the kwargs. :param statement: The statement to be signed :return: The signed statement """ return self.sign_statement(statement, class_name(saml.Assertion()), **kwargs)
def sign_attribute_query(self, statement, **kwargs): """Sign a SAML attribute query. See sign_statement() for the kwargs. :param statement: The statement to be signed :return: The signed statement """ return self.sign_statement(statement, class_name(samlp.AttributeQuery()), **kwargs)
def correctly_signed_response(self, decoded_xml, must=False, origdoc=None): """ Check if a instance is correctly signed, if we have metadata for the IdP that sent the info use that, if not use the key that are in the message if any. :param decoded_xml: The SAML message as a XML string :param must: Whether there must be a signature :param origdoc: :return: None if the signature can not be verified otherwise an instance """ response = samlp.any_response_from_string(decoded_xml) if not response: raise TypeError("Not a Response") if response.signature: self._check_signature(decoded_xml, response, class_name(response), origdoc) if isinstance(response, Response) and response.assertion: # Try to find the signing cert in the assertion for assertion in response.assertion: if not assertion.signature: logger.debug("unsigned") if must: raise SignatureError("Signature missing") continue else: logger.debug("signed") try: self._check_signature(decoded_xml, assertion, class_name(assertion), origdoc) except Exception, exc: logger.error("correctly_signed_response: %s" % exc) raise
def correctly_signed_response(self, decoded_xml, must=False, origdoc=None): """ Check if a instance is correctly signed, if we have metadata for the IdP that sent the info use that, if not use the key that are in the message if any. :param decoded_xml: The SAML message as a XML string :param must: Whether there must be a signature :param origdoc: :return: None if the signature can not be verified otherwise an instance """ response = samlp.any_response_from_string(decoded_xml) if not response: raise TypeError("Not a Response") if response.signature: self._check_signature(decoded_xml, response, class_name(response), origdoc) if isinstance(response, Response) and response.assertion: # Try to find the signing cert in the assertion for assertion in response.assertion: if not assertion.signature: logger.debug("unsigned") if must: raise SignatureError("Signature missing") continue else: logger.debug("signed") try: self._check_signature(decoded_xml, assertion, class_name(assertion), origdoc) except Exception, exc: logger.error("correctly_signed_response: %s" % exc) raise
def _instance(klass, ava, seccont, base64encode=False, elements_to_sign=None): instance = klass() for prop in instance.c_attributes.values(): #print "# %s" % (prop) if prop in ava: if isinstance(ava[prop], bool): setattr(instance, prop, "%s" % ava[prop]) elif isinstance(ava[prop], int): setattr(instance, prop, "%d" % ava[prop]) else: setattr(instance, prop, ava[prop]) if "text" in ava: instance.set_text(ava["text"], base64encode) for prop, klassdef in instance.c_children.values(): #print "## %s, %s" % (prop, klassdef) if prop in ava: #print "### %s" % ava[prop] if isinstance(klassdef, list): # means there can be a list of values _make_vals(ava[prop], klassdef[0], seccont, instance, prop, base64encode=base64encode, elements_to_sign=elements_to_sign) else: cis = _make_vals(ava[prop], klassdef, seccont, instance, prop, True, base64encode, elements_to_sign) setattr(instance, prop, cis) if "extension_elements" in ava: for item in ava["extension_elements"]: instance.extension_elements.append( ExtensionElement(item["tag"]).loadd(item)) if "extension_attributes" in ava: for key, val in ava["extension_attributes"].items(): instance.extension_attributes[key] = val if "signature" in ava: elements_to_sign.append((class_name(instance), instance.id)) return instance
def _instance(klass, ava, seccont, base64encode=False, elements_to_sign=None): instance = klass() for prop in instance.c_attributes.values(): #print "# %s" % (prop) if prop in ava: if isinstance(ava[prop], bool): setattr(instance, prop, "%s" % ava[prop]) elif isinstance(ava[prop], int): setattr(instance, prop, "%d" % ava[prop]) else: setattr(instance, prop, ava[prop]) if "text" in ava: instance.set_text(ava["text"], base64encode) for prop, klassdef in instance.c_children.values(): #print "## %s, %s" % (prop, klassdef) if prop in ava: #print "### %s" % ava[prop] if isinstance(klassdef, list): # means there can be a list of values _make_vals(ava[prop], klassdef[0], seccont, instance, prop, base64encode=base64encode, elements_to_sign=elements_to_sign) else: cis = _make_vals(ava[prop], klassdef, seccont, instance, prop, True, base64encode, elements_to_sign) setattr(instance, prop, cis) if "extension_elements" in ava: for item in ava["extension_elements"]: instance.extension_elements.append( ExtensionElement(item["tag"]).loadd(item)) if "extension_attributes" in ava: for key, val in ava["extension_attributes"].items(): instance.extension_attributes[key] = val if "signature" in ava: elements_to_sign.append((class_name(instance), instance.id)) return instance
def use_soap(self, request, destination="", soap_headers=None, sign=False): """ Construct the necessary information for using SOAP+POST :param request: :param destination: :param soap_headers: :param sign: :return: dictionary """ headers = [("content-type", "application/soap+xml")] soap_message = make_soap_enveloped_saml_thingy(request, soap_headers) logger.debug("SOAP message: %s" % soap_message) if sign and self.sec: _signed = self.sec.sign_statement(soap_message, class_name=class_name(request), node_id=request.id) soap_message = _signed return {"url": destination, "method": "POST", "data": soap_message, "headers": headers}
def correctly_signed_message(self, decoded_xml, msgtype, must=False, origdoc=None): """Check if a request is correctly signed, if we have metadata for the entity that sent the info use that, if not use the key that are in the message if any. :param decoded_xml: The SAML message as a XML string :param msgtype: :param must: Whether there must be a signature :param origdoc: :return: """ try: _func = getattr(samlp, "%s_from_string" % msgtype) except AttributeError: _func = getattr(saml, "%s_from_string" % msgtype) msg = _func(decoded_xml) if not msg: raise TypeError("Not a %s" % msgtype) if not msg.signature: if must: raise SignatureError("Missing must signature") else: return msg return self._check_signature(decoded_xml, msg, class_name(msg), origdoc, must=must)
def use_soap(self, request, destination="", soap_headers=None, sign=False): """ Construct the necessary information for using SOAP+POST :param request: :param destination: :param soap_headers: :param sign: :return: dictionary """ headers = [("content-type", "application/soap+xml")] soap_message = make_soap_enveloped_saml_thingy(request, soap_headers) logger.debug("SOAP message: %s" % soap_message) if sign and self.sec: _signed = self.sec.sign_statement(soap_message, class_name=class_name(request), node_id=request.id) soap_message = _signed return {"url": destination, "method": "POST", "data": soap_message, "headers": headers}
except UnravelError: return None except Exception, exc: logger.error("%s" % exc) raise logger.debug(">> %s", resp) if resp is None: return None elif isinstance(resp, AuthnResponse): self.users.add_information_about_person(resp.session_info()) logger.info("--- ADDED person info ----") else: logger.error("Response type not supported: %s" % ( class_name(resp),)) return resp # ------------------------------------------------------------------------ # SubjectQuery, AuthnQuery, RequestedAuthnContext, AttributeQuery, # AuthzDecisionQuery all get Response as response def parse_authz_decision_query_response(self, response, binding=BINDING_SOAP): """ Verify that the response is OK """ kwargs = {"entity_id": self.config.entityid, "attribute_converters": self.config.attribute_converters} return self._parse_response(response, AuthzResponse, "", binding, **kwargs)
def sign_assertion_using_xmlsec(self, statement, **kwargs): """ Deprecated function. See sign_assertion(). """ return self.sign_statement(statement, class_name(saml.Assertion()), **kwargs)
def sign_assertion_using_xmlsec(self, statement, **kwargs): """ Deprecated function. See sign_assertion(). """ return self.sign_statement(statement, class_name(saml.Assertion()), **kwargs)