Merge branch 'release-2.4.0'
This commit is contained in:
commit
c7cf89b387
75
NEWS
75
NEWS
|
@ -1,6 +1,81 @@
|
|||
NEWS
|
||||
====
|
||||
|
||||
2.4.0 - June 6th 2011
|
||||
---------------------
|
||||
93 files changed, 32160 insertions(+), 607 deletions(-)
|
||||
|
||||
Minor version number increase since ABI was extended (new methods).
|
||||
|
||||
- Improvements to autoconf and automake files to compile under Darwin (Mac Os
|
||||
X).
|
||||
- Key rollover support:
|
||||
Lasso is now able to accept messages signed by any key declared as a signing
|
||||
key in a metadata and not just the last one. You can also decrypt encrypted
|
||||
nodes using any of a list of private keys, allowing roll-over of encryption
|
||||
certificates. Signing key roll-over is automatic, your provider just have to
|
||||
provide the new signing key in their metadata. For multiple-encryption key
|
||||
you can load another private key than the one loaded in the LassoServer
|
||||
constuctor with code like that:
|
||||
|
||||
>>> import lasso
|
||||
>>> server = lasso.Server(our_metadata, first_private_key_path)
|
||||
>>> server.setEncryptionPrivateKey(second_private_key_path)
|
||||
|
||||
See the FAQ file for the workflow of a proper key roll-over.
|
||||
|
||||
- Partial logout reponse now produces a specific error code when parsed by
|
||||
lasso_logout_process_response_msg()
|
||||
- Bugs in lasso_assertion_query_build_request_msg() were fixed
|
||||
- Processing of assertions is not stopped when checking that first level
|
||||
status code is not success, so that later code can check the second level
|
||||
status code.
|
||||
- A new generic error for denied request was added,
|
||||
LASSO_PROFILE_ERROR_REQUEST_DENIED
|
||||
- A new API lasso_server_load_metadata() was added to load federation files
|
||||
(XML files containing metadata from multiple providers) and to check
|
||||
signatures on them.
|
||||
- Better warning and errors are reported in logs when failing to load a
|
||||
metadata file.
|
||||
- Bugs around missing namespace declaration for dump file were fixed, it
|
||||
prevented reloading dumped object (like LassoLogin).
|
||||
- lasso_node_get_xml_node_for_any_type() must be able to copy the content of
|
||||
an XML node to another (namespace, attribute and children). It did not, now
|
||||
it is fixed. It can be used for example to add specific attribute like «
|
||||
xsi:type="string" » to a Saml2AttributeValue. Here is a python snippet to do that:
|
||||
|
||||
>>> import lasso
|
||||
>>> a = lasso.Saml2AttributeValue()
|
||||
>>> a.setOriginalXmlnode('<Dummy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="string">Value</Dummy>')
|
||||
>>> print a.debug(0)
|
||||
<saml:AttributeValue xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="string">Value</saml:AttributeValue>
|
||||
- support for symetric keys signatures: for a long time XMLDisg standard has
|
||||
supported HMAC signature, or signature based on a shared secret key an hash
|
||||
algorithm. Lasso now does support to share a key with another Lasso using
|
||||
service or identity provider and to verify and sign SAML exchange using this
|
||||
key. Performance can be 100 times more than with assymetric cryptography,
|
||||
i.e. RSA.
|
||||
- nodes able to hold any XML attribyte (like saml:AttributeValue) contains a
|
||||
hashtable to for holding those attributes, those hashtable have a new syntax
|
||||
for attributes of another namespace than the current node namespace,
|
||||
inspired by the Python ElementTree library:
|
||||
|
||||
{the_namespace}the_attribute_name
|
||||
|
||||
ex:
|
||||
|
||||
{http://www.w3.org/2001/XMLSchema-instance}type
|
||||
|
||||
for the classic xsi:type attribute.
|
||||
- The perfs benchmarking tools now allows to select a different metadata set
|
||||
(for example to test with different public key sizes).
|
||||
- Perl minimal version for the binding was downgraded to 5
|
||||
- pseudo-XSchema validation: the new XML deserializer does more to enforce
|
||||
constraints of the schema defining SAML messages. It means Lasso is less
|
||||
forgiving with non-conform implementation of SAML.
|
||||
- a FAQ file was started.
|
||||
|
||||
|
||||
2.3.6 - November 29th 2011
|
||||
--------------------------
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -136,6 +136,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
|
|||
def generate_constructors(self, klass):
|
||||
method_prefix = format_as_underscored(klass.name) + '_'
|
||||
for m in self.binding_data.functions:
|
||||
name = m.rename or m.name
|
||||
if m.name == method_prefix + 'new':
|
||||
php_args = []
|
||||
c_args = []
|
||||
|
@ -163,18 +164,36 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
|
|||
print >> self.fd, ' }'
|
||||
print >> self.fd, ''
|
||||
|
||||
if m.name == method_prefix + 'new_from_dump':
|
||||
if len(m.args) == 1:
|
||||
print >> self.fd, ' public static function newFromDump($dump) {'
|
||||
print >> self.fd, ' return cptrToPhp(%s($dump));' % m.name
|
||||
elif name.startswith(method_prefix) and m.args \
|
||||
and clean_type(unconstify(m.args[0][0])) != klass.name:
|
||||
if m.rename:
|
||||
php_name = m.rename
|
||||
else:
|
||||
print >> self.fd, ' public static function newFromDump($server, $dump) {'
|
||||
print >> self.fd, ' return cptrToPhp(%s($server->_cptr, $dump));' % m.name
|
||||
# XXX: Else throw an exception
|
||||
print >> self.fd, ' }'
|
||||
print >> self.fd, ''
|
||||
elif m.name == method_prefix + 'new_full':
|
||||
pass
|
||||
mname = m.name
|
||||
mname = mname[len(method_prefix):]
|
||||
if 'new' in mname and not mname.startswith('new'):
|
||||
continue
|
||||
php_name = format_underscore_as_camelcase(mname)
|
||||
php_args = []
|
||||
c_args = []
|
||||
for arg in m.args:
|
||||
arg_type, arg_name, arg_options = arg
|
||||
if arg_options.get('optional'):
|
||||
php_args.append('$%s = null' % arg_name)
|
||||
else:
|
||||
php_args.append('$%s' % arg_name)
|
||||
|
||||
if self.is_object(arg_type):
|
||||
c_args.append('$%s->_cptr' % arg_name)
|
||||
else:
|
||||
c_args.append('$%s' % arg_name)
|
||||
php_args = ', '.join(php_args)
|
||||
c_args = ', '.join(c_args)
|
||||
print >>self.fd, ' public static function %s(%s) {' % (php_name, php_args)
|
||||
print >>self.fd, ' return cptrToPhp(%s(%s));' % (m.name, c_args)
|
||||
print >>self.fd, ' }'
|
||||
print >>self.fd, ''
|
||||
|
||||
|
||||
|
||||
def generate_getter(self, c, m):
|
||||
|
@ -312,12 +331,14 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
|
|||
php_args.append('%s = null' % arg_name)
|
||||
else:
|
||||
php_args.append(arg_name)
|
||||
if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*') or \
|
||||
arg_type in ['int', 'gint', 'gboolean', 'const gboolean'] or \
|
||||
arg_type in self.binding_data.enums:
|
||||
if is_xml_node(arg) or is_boolean(arg) or is_cstring(arg) or \
|
||||
is_int(arg, self.binding_data) or is_glist(arg) or \
|
||||
is_hashtable(arg) or is_time_t_pointer(arg):
|
||||
c_args.append(arg_name)
|
||||
elif is_object(arg):
|
||||
c_args.append('%s->_cptr' % arg_name)
|
||||
else:
|
||||
c_args.append('%s._cptr' % arg_name)
|
||||
raise Exception('Does not handle argument of type: %s' % ((m, arg),))
|
||||
if is_out(arg):
|
||||
php_args.pop()
|
||||
php_args.append(arg_name)
|
||||
|
|
|
@ -15,7 +15,7 @@ dnl - Second number is the number of supported API versions where API version >
|
|||
dnl first number.
|
||||
dnl - Third number is the current API version implementation version number.
|
||||
dnl See libtool explanations about current, age and release, later in this file.
|
||||
AC_INIT([lasso], 2.3.6, lasso-devel@lists.labs.libre-entreprise.org)
|
||||
AC_INIT([lasso], 2.4.0, lasso-devel@lists.labs.libre-entreprise.org)
|
||||
dnl Check if autoconf ver > 2.53
|
||||
AC_PREREQ(2.53)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
@ -184,7 +184,7 @@ dnl - interfaces removed -> AGE = 0
|
|||
# m = a
|
||||
# r = r
|
||||
current=`expr $VERSION_MAJOR + $VERSION_MINOR`
|
||||
LASSO_VERSION_INFO="12:4:9"
|
||||
LASSO_VERSION_INFO="13:0:10"
|
||||
AC_SUBST(LASSO_VERSION_INFO)
|
||||
|
||||
dnl Compute the minimal supported ABI version for Win32 scripts and resources files.
|
||||
|
|
153
lasso/key.c
153
lasso/key.c
|
@ -24,6 +24,7 @@
|
|||
#include "key.h"
|
||||
#include "keyprivate.h"
|
||||
#include "xml/private.h"
|
||||
#include "xmlsec/xmltree.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* private methods */
|
||||
|
@ -172,7 +173,7 @@ lasso_key_new_for_signature_from_file(char *filename_or_buffer,
|
|||
* Return value:(transfer full): a newly allocated #LassoKey object
|
||||
*/
|
||||
LassoKey*
|
||||
lasso_key_new_for_signature_from_memory(void *buffer,
|
||||
lasso_key_new_for_signature_from_memory(const void *buffer,
|
||||
size_t size,
|
||||
char *password,
|
||||
LassoSignatureMethod signature_method,
|
||||
|
@ -221,6 +222,149 @@ lasso_key_new_for_signature_from_base64_string(char *base64_string,
|
|||
return key;
|
||||
}
|
||||
|
||||
static xmlNode *
|
||||
find_xmlnode_with_saml2_id(xmlNode *xmlnode, const char *id)
|
||||
{
|
||||
xmlNode *found = NULL;
|
||||
xmlNode *t;
|
||||
|
||||
if (! xmlnode)
|
||||
return NULL;
|
||||
|
||||
if (xmlHasProp(xmlnode, BAD_CAST "ID")) {
|
||||
xmlChar *value;
|
||||
|
||||
value = xmlGetProp(xmlnode, BAD_CAST "ID");
|
||||
if (lasso_strisequal((char*)value, id)) {
|
||||
found = xmlnode;
|
||||
}
|
||||
xmlFree(value);
|
||||
}
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
t = xmlSecGetNextElementNode(xmlnode->children);
|
||||
while (t) {
|
||||
found = find_xmlnode_with_saml2_id(t, id);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
t = xmlSecGetNextElementNode(t->next);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_saml2_xml_verify:
|
||||
* @key: a #LassoKey object
|
||||
* @id: the value of the ID attribute of signed node
|
||||
* @document: the document containing the signed node
|
||||
*
|
||||
* Verify the first signature node child of the node with the given id. It follows from the profile
|
||||
* of XMLDsig used by the SAML 2.0 specification.
|
||||
*
|
||||
* Return value: 0 if the signature validate, an error code otherwise.
|
||||
*/
|
||||
lasso_error_t
|
||||
lasso_key_saml2_xml_verify(LassoKey *key, char *id, xmlNode *document)
|
||||
{
|
||||
xmlNode *signed_node;
|
||||
LassoSignatureContext signature_context;
|
||||
|
||||
|
||||
signed_node = find_xmlnode_with_saml2_id(document, id);
|
||||
if (! signed_node) {
|
||||
return LASSO_DS_ERROR_INVALID_REFERENCE_FOR_SAML;
|
||||
}
|
||||
signature_context = lasso_key_get_signature_context(key);
|
||||
return lasso_verify_signature(signed_node, signed_node->doc, "ID", NULL,
|
||||
signature_context.signature_key, NO_OPTION, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_saml2_xml_sign:
|
||||
* @key: a #LassoKey object
|
||||
* @id: the value of the ID attribute of signed node
|
||||
* @document: the document containing the signed node
|
||||
*
|
||||
* Sign the first signature node child of the node with the given id. It no signature node is found
|
||||
* a new one is added at the end of the children list of the signed node.
|
||||
*
|
||||
* The passed document node is modified in-place.
|
||||
*
|
||||
* Return value: The modified xmlNode object, or NULL if the signature failed.
|
||||
*/
|
||||
xmlNode*
|
||||
lasso_key_saml2_xml_sign(LassoKey *key, const char *id, xmlNode *document)
|
||||
{
|
||||
xmlNode *signed_node;
|
||||
LassoSignatureContext signature_context;
|
||||
|
||||
signed_node = find_xmlnode_with_saml2_id(document, id);
|
||||
if (! signed_node) {
|
||||
return NULL;
|
||||
}
|
||||
signature_context = lasso_key_get_signature_context(key);
|
||||
lasso_xmlnode_add_saml2_signature_template(signed_node, signature_context, id);
|
||||
if (lasso_sign_node(signed_node, signature_context,
|
||||
"ID", id) == 0) {
|
||||
return document;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_query_verify:
|
||||
* key: a #LassoKey object
|
||||
* query: a raw HTTP query string
|
||||
*
|
||||
* Check if this query string contains a proper SAML2 signature for this key.
|
||||
*
|
||||
* Return value: 0 if a valid signature was found, an error code otherwise.
|
||||
*/
|
||||
lasso_error_t
|
||||
lasso_key_query_verify(LassoKey *key, const char *query)
|
||||
{
|
||||
LassoSignatureContext signature_context;
|
||||
lasso_bad_param(KEY, key);
|
||||
|
||||
signature_context = lasso_key_get_signature_context(key);
|
||||
if (! lasso_validate_signature_context(signature_context))
|
||||
return LASSO_ERROR_UNDEFINED;
|
||||
return lasso_saml2_query_verify_signature(query, signature_context.signature_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_query_verify:
|
||||
* key: a #LassoKey object
|
||||
* query: a raw HTTP query string
|
||||
*
|
||||
* Sign the given query string using the given key.
|
||||
*
|
||||
* Return value: the signed query string.
|
||||
*/
|
||||
char*
|
||||
lasso_key_query_sign(LassoKey *key, const char *query)
|
||||
{
|
||||
LassoSignatureContext signature_context;
|
||||
|
||||
if (! LASSO_IS_KEY(key))
|
||||
return NULL;
|
||||
signature_context = lasso_key_get_signature_context(key);
|
||||
if (! lasso_validate_signature_context(signature_context))
|
||||
return NULL;
|
||||
return lasso_query_sign((char*)query, signature_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_get_signature_context:
|
||||
* @key: a #LassoKey object
|
||||
*
|
||||
* Private method to extract the signature context embedded in a LassoKey object.
|
||||
*
|
||||
* Return value: a #LassoSignatureContext structure value.
|
||||
*/
|
||||
LassoSignatureContext
|
||||
lasso_key_get_signature_context(LassoKey *key) {
|
||||
if (key->private_data && key->private_data->type == LASSO_KEY_TYPE_FOR_SIGNATURE) {
|
||||
|
@ -228,6 +372,13 @@ lasso_key_get_signature_context(LassoKey *key) {
|
|||
}
|
||||
return LASSO_SIGNATURE_CONTEXT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_key_get_key_type:
|
||||
* @key: a #LassoKey object
|
||||
*
|
||||
* Return the type of key, i.e. which operation it supports.
|
||||
*/
|
||||
LassoKeyType
|
||||
lasso_key_get_key_type(LassoKey *key) {
|
||||
lasso_return_val_if_fail(LASSO_IS_KEY(key),
|
||||
|
|
10
lasso/key.h
10
lasso/key.h
|
@ -65,7 +65,7 @@ struct _LassoKeyClass {
|
|||
|
||||
LASSO_EXPORT GType lasso_key_get_type();
|
||||
|
||||
LASSO_EXPORT LassoKey* lasso_key_new_for_signature_from_memory(void *buffer, size_t size,
|
||||
LASSO_EXPORT LassoKey* lasso_key_new_for_signature_from_memory(const void *buffer, size_t size,
|
||||
char *password, LassoSignatureMethod signature_method, char *certificate);
|
||||
|
||||
LASSO_EXPORT LassoKey* lasso_key_new_for_signature_from_base64_string(char *base64_string,
|
||||
|
@ -74,6 +74,14 @@ LASSO_EXPORT LassoKey* lasso_key_new_for_signature_from_base64_string(char *base
|
|||
LASSO_EXPORT LassoKey* lasso_key_new_for_signature_from_file(char *filename_or_buffer,
|
||||
char *password, LassoSignatureMethod signature_method, char *certificate);
|
||||
|
||||
LASSO_EXPORT lasso_error_t lasso_key_query_verify(LassoKey* key, const char *query);
|
||||
|
||||
LASSO_EXPORT char* lasso_key_query_sign(LassoKey *key, const char *query);
|
||||
|
||||
LASSO_EXPORT lasso_error_t lasso_key_saml2_xml_verify(LassoKey *key, char *id, xmlNode *document);
|
||||
|
||||
LASSO_EXPORT xmlNode *lasso_key_saml2_xml_sign(LassoKey *key, const char *id, xmlNode *document);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -534,7 +534,24 @@ lasso_saml20_provider_load_metadata(LassoProvider *provider, xmlNode *root_node)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean has_synchronous_methods(LassoProvider *provider, LassoMdProtocolType protocol_type)
|
||||
enum {
|
||||
FOR_RESPONSE = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* has_synchronous_methods:
|
||||
* @provider: a #LassoProvider object
|
||||
* @protocol_type: a #LassoMdProtocolType value
|
||||
* @for_response: a boolean stating whether we need the answer for receiving a response.
|
||||
*
|
||||
* Return whether the given @provider support a certain protocol with a synchronous binding.
|
||||
* If we need to receive a response for this protocol, @for_response must be set to True.
|
||||
*
|
||||
* Return result: TRUE if @provider supports @protocol_type with a synchronous binding, eventually
|
||||
* for receiving responses, FALSE otherwise.
|
||||
*/
|
||||
static gboolean has_synchronous_methods(LassoProvider *provider, LassoMdProtocolType protocol_type,
|
||||
gboolean for_response)
|
||||
{
|
||||
GList *t = NULL;
|
||||
const char *kind = NULL;
|
||||
|
@ -547,6 +564,11 @@ static gboolean has_synchronous_methods(LassoProvider *provider, LassoMdProtocol
|
|||
return LASSO_HTTP_METHOD_NONE;
|
||||
}
|
||||
|
||||
if (for_response && protocol_type == LASSO_MD_PROTOCOL_TYPE_SINGLE_SIGN_ON)
|
||||
{
|
||||
kind = LASSO_SAML2_METADATA_ELEMENT_ASSERTION_CONSUMER_SERVICE;
|
||||
}
|
||||
|
||||
lasso_foreach(t, provider->private_data->endpoints) {
|
||||
EndpointType *endpoint_type = (EndpointType*)t->data;
|
||||
if (endpoint_type && lasso_strisequal(endpoint_type->kind, kind)) {
|
||||
|
@ -581,7 +603,7 @@ lasso_saml20_provider_get_first_http_method(LassoProvider *provider,
|
|||
/* a synchronous method needs another synchronous method for receiving the
|
||||
* response on the local side */
|
||||
if (http_method_kind(result) == SYNCHRONOUS
|
||||
&& ! has_synchronous_methods(provider, protocol_type))
|
||||
&& ! has_synchronous_methods(provider, protocol_type, FOR_RESPONSE))
|
||||
continue;
|
||||
if (result != LASSO_HTTP_METHOD_NONE)
|
||||
break;
|
||||
|
|
|
@ -721,10 +721,18 @@ lasso_saml2_assertion_add_attribute_with_node(LassoSaml2Assertion *assertion, co
|
|||
lasso_assign_string(attribute->NameFormat, LASSO_SAML2_ATTRIBUTE_NAME_FORMAT_URI);
|
||||
lasso_list_add_new_gobject(attribute->AttributeValue, attribute_value);
|
||||
|
||||
attribute_statement = LASSO_SAML2_ATTRIBUTE_STATEMENT(lasso_saml2_attribute_statement_new());
|
||||
if (assertion->AttributeStatement
|
||||
&& LASSO_IS_SAML2_ATTRIBUTE_STATEMENT(
|
||||
assertion->AttributeStatement->data)) {
|
||||
attribute_statement =
|
||||
(LassoSaml2AttributeStatement*)
|
||||
assertion->AttributeStatement->data;
|
||||
} else {
|
||||
attribute_statement = LASSO_SAML2_ATTRIBUTE_STATEMENT(lasso_saml2_attribute_statement_new());
|
||||
lasso_list_add_new_gobject(assertion->AttributeStatement, attribute_statement);
|
||||
}
|
||||
lasso_list_add_new_gobject(attribute_statement->Attribute, attribute);
|
||||
|
||||
lasso_list_add_new_gobject(assertion->AttributeStatement, attribute_statement);
|
||||
cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ lasso_create_hmac_key(const xmlSecByte * buf, xmlSecSize size);
|
|||
lasso_error_t
|
||||
lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size);
|
||||
|
||||
LassoSignatureContext lasso_make_signature_context_from_buffer(const char *buffer, size_t length,
|
||||
LassoSignatureContext lasso_make_signature_context_from_buffer(const void *buffer, size_t length,
|
||||
const char *password, LassoSignatureMethod signature_method,
|
||||
const char *certificate);
|
||||
|
||||
|
@ -299,6 +299,12 @@ void set_xsi_type(xmlNode *node,
|
|||
const xmlChar *type_ns_prefix,
|
||||
const xmlChar *type_ns_href,
|
||||
const xmlChar *type_name);
|
||||
|
||||
void lasso_xmlnode_add_saml2_signature_template(xmlNode *node, LassoSignatureContext context,
|
||||
const char *id);
|
||||
|
||||
gchar* lasso_xmlnode_build_deflated_query(xmlNode *xmlnode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -1012,6 +1012,17 @@ lasso_node_build_deflated_query(LassoNode *node)
|
|||
{
|
||||
/* actually deflated and b64'ed and url-escaped */
|
||||
xmlNode *xmlnode;
|
||||
gchar *result;
|
||||
|
||||
xmlnode = lasso_node_get_xmlNode(node, FALSE);
|
||||
result = lasso_xmlnode_build_deflated_query(xmlnode);
|
||||
xmlFreeNode(node);
|
||||
return result;
|
||||
}
|
||||
|
||||
gchar*
|
||||
lasso_xmlnode_build_deflated_query(xmlNode *xmlnode)
|
||||
{
|
||||
xmlOutputBufferPtr buf;
|
||||
xmlCharEncodingHandlerPtr handler = NULL;
|
||||
xmlChar *buffer;
|
||||
|
@ -1021,17 +1032,12 @@ lasso_node_build_deflated_query(LassoNode *node)
|
|||
int rc = 0;
|
||||
z_stream stream;
|
||||
|
||||
xmlnode = lasso_node_get_xmlNode(node, FALSE);
|
||||
|
||||
handler = xmlFindCharEncodingHandler("utf-8");
|
||||
buf = xmlAllocOutputBuffer(handler);
|
||||
xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 0, "utf-8");
|
||||
xmlOutputBufferFlush(buf);
|
||||
buffer = buf->conv ? buf->conv->content : buf->buffer->content;
|
||||
|
||||
xmlFreeNode(xmlnode);
|
||||
xmlnode = NULL;
|
||||
|
||||
in_len = strlen((char*)buffer);
|
||||
ret = g_malloc(in_len * 2);
|
||||
/* deflating should never increase the required size but we are
|
||||
|
@ -1079,6 +1085,35 @@ lasso_node_build_deflated_query(LassoNode *node)
|
|||
return rret;
|
||||
}
|
||||
|
||||
void
|
||||
lasso_get_query_string_param_value(const char *qs, const char *param_key, char **value,
|
||||
size_t *length)
|
||||
{
|
||||
size_t key_size = strlen(param_key);
|
||||
|
||||
*value = NULL;
|
||||
*length = 0;
|
||||
while (qs) {
|
||||
if (strncmp(qs, param_key, key_size) == 0 &&
|
||||
qs[key_size] == '=')
|
||||
{
|
||||
char *end;
|
||||
*value = qs[key_size+1];
|
||||
end = strchr(*value, '&');
|
||||
if (! end) {
|
||||
end = strchr(*value, ';');
|
||||
}
|
||||
if (end) {
|
||||
*length = (ptrdiff_t)(end - *value)
|
||||
} else {
|
||||
*length = strlen(*value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
qs = strchr(qs, '&');
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate_string)
|
||||
{
|
||||
|
@ -2367,7 +2402,7 @@ lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size)
|
|||
* successful, LASSO_SIGNATURE_CONTEXT_NONE otherwise. The caller must free the #xmlSecKey.
|
||||
*/
|
||||
LassoSignatureContext
|
||||
lasso_make_signature_context_from_buffer(const char *buffer, size_t length, const char *password,
|
||||
lasso_make_signature_context_from_buffer(const void *buffer, size_t length, const char *password,
|
||||
LassoSignatureMethod signature_method, const char *certificate) {
|
||||
LassoSignatureContext context = LASSO_SIGNATURE_CONTEXT_NONE;
|
||||
|
||||
|
@ -2466,3 +2501,76 @@ set_xsi_type(xmlNode *node,
|
|||
type_ns_href,
|
||||
type_name);
|
||||
}
|
||||
|
||||
void
|
||||
lasso_xmlnode_add_saml2_signature_template(xmlNode *node, LassoSignatureContext context,
|
||||
const char *id) {
|
||||
xmlSecTransformId transform_id;
|
||||
xmlNode *existing_signature = NULL, *signature = NULL, *reference, *key_info;
|
||||
char *uri;
|
||||
|
||||
if (! lasso_validate_signature_context(context) || ! node)
|
||||
return;
|
||||
|
||||
switch (context.signature_method) {
|
||||
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||
transform_id = xmlSecTransformRsaSha1Id;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
transform_id = xmlSecTransformDsaSha1Id;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
transform_id = xmlSecTransformHmacSha1Id;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
existing_signature = xmlSecFindChild(node, xmlSecNodeSignature, xmlSecDSigNs);
|
||||
signature = xmlSecTmplSignatureCreate(NULL,
|
||||
xmlSecTransformExclC14NId,
|
||||
transform_id, NULL);
|
||||
if (existing_signature) {
|
||||
xmlSecReplaceNode(existing_signature, signature);
|
||||
} else {
|
||||
xmlAddChild(node, signature);
|
||||
}
|
||||
|
||||
/* Normally the signature is son of the signed node, which holds an Id attribute, but in
|
||||
* other cases, set snippet->offset to 0 and use xmlSecTmpSignatureAddReference from another
|
||||
* node get_xmlNode virtual method to add the needed reference.
|
||||
*/
|
||||
if (id) {
|
||||
uri = g_strdup_printf("#%s", id);
|
||||
reference = xmlSecTmplSignatureAddReference(signature,
|
||||
xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
|
||||
lasso_release(uri);
|
||||
}
|
||||
|
||||
/* add enveloped transform */
|
||||
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
|
||||
/* add exclusive C14N transform */
|
||||
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
|
||||
/* if the key is the public part of an asymetric key, add its certificate or the key itself */
|
||||
switch (context.signature_method) {
|
||||
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
/* asymetric cryptography methods */
|
||||
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
|
||||
if (xmlSecKeyGetData(context.signature_key, xmlSecOpenSSLKeyDataX509Id)) {
|
||||
/* add <dsig:KeyInfo/> */
|
||||
xmlSecTmplKeyInfoAddX509Data(key_info);
|
||||
} else {
|
||||
xmlSecTmplKeyInfoAddKeyValue(key_info);
|
||||
}
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
if (context.signature_key->name) {
|
||||
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
|
||||
xmlSecTmplKeyInfoAddKeyName(key_info, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
|
141
lasso/xml/xml.c
141
lasso/xml/xml.c
|
@ -2810,11 +2810,7 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
|
|||
LassoNodeClass *klass = NULL;
|
||||
LassoNodeClassData *node_data = NULL;
|
||||
LassoSignatureContext context;
|
||||
xmlSecTransformId transform_id;
|
||||
xmlNode *signature = NULL, *reference, *key_info;
|
||||
char *uri;
|
||||
char *id;
|
||||
|
||||
char *id = NULL;
|
||||
|
||||
node_data = lasso_legacy_get_signature_node_data(node, &klass);
|
||||
if (! node_data)
|
||||
|
@ -2828,66 +2824,11 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
|
|||
if (lasso_legacy_extract_and_copy_signature_parameters(node, node_data))
|
||||
context = lasso_node_get_signature(node);
|
||||
|
||||
if (! lasso_validate_signature_context(context))
|
||||
return;
|
||||
|
||||
switch (context.signature_method) {
|
||||
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||
transform_id = xmlSecTransformRsaSha1Id;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
transform_id = xmlSecTransformDsaSha1Id;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
transform_id = xmlSecTransformHmacSha1Id;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
signature = xmlSecTmplSignatureCreate(NULL,
|
||||
xmlSecTransformExclC14NId,
|
||||
transform_id, NULL);
|
||||
xmlAddChild(xmlnode, signature);
|
||||
|
||||
/* Normally the signature is son of the signed node, which holds an Id attribute, but in
|
||||
* other cases, set snippet->offset to 0 and use xmlSecTmpSignatureAddReference from another
|
||||
* node get_xmlNode virtual method to add the needed reference.
|
||||
*/
|
||||
if (snippet_signature->offset) {
|
||||
id = SNIPPET_STRUCT_MEMBER(char *, node, G_TYPE_FROM_CLASS(klass), snippet_signature);
|
||||
uri = g_strdup_printf("#%s", id);
|
||||
reference = xmlSecTmplSignatureAddReference(signature,
|
||||
xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
|
||||
lasso_release(uri);
|
||||
}
|
||||
|
||||
/* add enveloped transform */
|
||||
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
|
||||
/* add exclusive C14N transform */
|
||||
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
|
||||
/* if the key is the public part of a symetric key, add its certificate or the key itself */
|
||||
switch (context.signature_method) {
|
||||
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
/* symetric cryptography methods */
|
||||
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
|
||||
if (xmlSecKeyGetData(context.signature_key, xmlSecOpenSSLKeyDataX509Id)) {
|
||||
/* add <dsig:KeyInfo/> */
|
||||
xmlSecTmplKeyInfoAddX509Data(key_info);
|
||||
} else {
|
||||
xmlSecTmplKeyInfoAddKeyValue(key_info);
|
||||
}
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
if (context.signature_key->name) {
|
||||
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
|
||||
xmlSecTmplKeyInfoAddKeyName(key_info, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
lasso_xmlnode_add_saml2_signature_template(xmlnode, context, id);
|
||||
}
|
||||
|
||||
static struct XmlSnippet*
|
||||
|
@ -3475,3 +3416,81 @@ lasso_node_get_namespace(LassoNode *node)
|
|||
return (const char*)klass->node_data->ns->href;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lasso_node_export_to_saml2_query:
|
||||
* @node: the #LassoNode object to pass as a query
|
||||
* @param_name: the key value for the query string parameter
|
||||
* @url:(allow-none): an optional URL to prepend to the query string
|
||||
* @key:(allow-none): a #LassoKey object
|
||||
*
|
||||
* Export a node as signed query string, the node must support serialization as a query.
|
||||
*
|
||||
* Return value: an HTTP URL or query string if successful, NULL otherwise.
|
||||
*/
|
||||
char*
|
||||
lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const char *url,
|
||||
LassoKey *key)
|
||||
{
|
||||
char *value = NULL, *query = NULL, *signed_query = NULL, *result = NULL;
|
||||
xmlChar *encoded_param = NULL;
|
||||
|
||||
value = lasso_node_build_deflated_query(xmlnode);
|
||||
if (! value)
|
||||
goto cleanup;
|
||||
encoded_param = xmlURIEscapeStr(BAD_CAST param_name, NULL);
|
||||
if (! encoded_param)
|
||||
goto cleanup;
|
||||
query = g_strdup_printf("%s=%s", encoded_param, value);
|
||||
if (! query)
|
||||
goto cleanup;
|
||||
if (LASSO_IS_KEY(key)) {
|
||||
signed_query = lasso_key_query_sign(key, query);
|
||||
} else {
|
||||
lasso_transfer_string(signed_query, query);
|
||||
}
|
||||
if (! signed_query)
|
||||
goto cleanup;
|
||||
if (url) {
|
||||
result = lasso_concat_url_query(url, signed_query);
|
||||
} else {
|
||||
lasso_transfer_string(result, signed_query);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
lasso_release_string(value);
|
||||
lasso_release_xml_string(encoded_param);
|
||||
lasso_release_string(query);
|
||||
lasso_release_string(signed_query);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_node_new_from_saml2_query:
|
||||
* @url_or_qs: an URL containing a query string or a query string only
|
||||
* @param_name: the key value for the query string parameter to extract as a #LassoNode.
|
||||
* @key:(allow-none): a #LassoKey object
|
||||
*
|
||||
* Verify the signature on a SAML-2 encoded query string and return the encoded node.
|
||||
*
|
||||
* Return value: a newly build #LassoNode if successful, NULL otherwise.
|
||||
*/
|
||||
LassoNode*
|
||||
lasso_node_new_from_saml2_query(const char *url_or_qs, const char *param_name, LassoKey *key)
|
||||
{
|
||||
char *needle = NULL;
|
||||
LassoNode *result = NULL;
|
||||
|
||||
if (! url_or_qs || ! param_name)
|
||||
return NULL;
|
||||
needle = strchr(url_or_qs, '?');
|
||||
if (needle) {
|
||||
url_or_qs = (const char*)(needle+1);
|
||||
}
|
||||
if (key) {
|
||||
goto_cleanup_if_fail(lasso_key_query_verify(key, url_or_qs) == 0);
|
||||
}
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -194,6 +194,11 @@ LASSO_EXPORT gchar* lasso_get_prefix_for_idwsf2_dst_service_href(const gchar *hr
|
|||
|
||||
LASSO_EXPORT char* lasso_node_debug(LassoNode *node, int level);
|
||||
|
||||
typedef struct _LassoKey LassoKey;
|
||||
|
||||
LASSO_EXPORT char* lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const
|
||||
char *url, LassoKey *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -2057,13 +2057,11 @@ START_TEST(test15_ds_key_info)
|
|||
list = (GList){ .data = ds_key_info, .next = NULL, .prev = NULL };
|
||||
lasso_saml2_key_info_confirmation_data_type_set_key_info(kicdt, &list);
|
||||
dump = lasso_node_debug((LassoNode*)sc, 10);
|
||||
printf("1 %s\n", dump);
|
||||
lasso_release_gobject(sc);
|
||||
lasso_release_gobject(ds_key_info);
|
||||
node = lasso_node_new_from_dump(dump);
|
||||
lasso_release_string(dump);
|
||||
dump = lasso_node_debug(node, 10);
|
||||
printf("2 %s\n", dump);
|
||||
lasso_release_string(dump);
|
||||
}
|
||||
END_TEST
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "../lasso/xml/saml_name_identifier.h"
|
||||
#include "../lasso/xml/samlp_response.h"
|
||||
#include "../lasso/utils.h"
|
||||
#include "../lasso/key.h"
|
||||
|
||||
|
||||
Suite* random_suite();
|
||||
|
@ -328,6 +329,105 @@ LlTxKnCrWAXftSm1rNtewTsF\n\
|
|||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(test08_lasso_key)
|
||||
{
|
||||
/* normal query as produces by Lasso */
|
||||
const char query1[] = "SAMLRequest=fZHNasMwEIRfxeieWrYTtQjb4DgJBNqSNqWHXopw1kQgS6523Z%2B3r%2BxQSKDkOppvd2aVo%2BpML6uBjvYZPgZAir47Y1FODwUbvJVOoUZpVQcoqZH76uFepjdc9t6Ra5xhZ8h1QiGCJ%2B0si7argr0vxTLJ1guRilpU8%2FWtyKpNnaXrukoF32SCRa%2FgMfgLFvAAIQ6wtUjKUpB4wmc8nSX8hXOZ3Ml0%2FsaijfMNTIUK1iqDMGK7sFl%2Fwp9S5mNWOY3z5ZGol3GM%2FSLugNRBkcrjc0N%2ButJj6LNd7ZzRzc%2B4plN0ve6o6MOsnayyH6sggSUW7XfjsKdBGd1q8AX7JwOLKmPcV%2B1BUUhOfgAWl6dkl19W%2FgI%3D&RelayState=fake%5B%5D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=wDxMSEPKhK%2FuU06cmL50oVx%2B7eP5%2FQirShQE%2BLv9pT3CrVwb6WBV1Tp9XS2VVJ2odLHogdA%2FE1XDW7BIRKYgkN8bXVlC2GybSYBhyn8bwAuyHs%2BnMW48LF%2FE5vFiZxbw8tMWUAktdvDuaXoZLhubX7UgV%2B%2BdRyjhckolpXTC9xuJdoHJUDF0vzzNm8xZs6LR7tjWUoz5CcjMJA3LVfWmpE5UjCyRmGbi9knGWHdY75CFtArD%2BNSkGeNx9xySrUlik6e57Zlodv4V9WBdeopAWskO58BA27GqTmnSLooeo%2FrtLxc1NZeuau11YxNzwl%2FvN8%2FQ5IsR3Xic8X1TaCCtwg%3D%3D";
|
||||
/* SAMLRequest field was moved in the middle, Signature to the beginning and all & were
|
||||
* changed to ; */
|
||||
const char query2[] = "Signature=wDxMSEPKhK%2FuU06cmL50oVx%2B7eP5%2FQirShQE%2BLv9pT3CrVwb6WBV1Tp9XS2VVJ2odLHogdA%2FE1XDW7BIRKYgkN8bXVlC2GybSYBhyn8bwAuyHs%2BnMW48LF%2FE5vFiZxbw8tMWUAktdvDuaXoZLhubX7UgV%2B%2BdRyjhckolpXTC9xuJdoHJUDF0vzzNm8xZs6LR7tjWUoz5CcjMJA3LVfWmpE5UjCyRmGbi9knGWHdY75CFtArD%2BNSkGeNx9xySrUlik6e57Zlodv4V9WBdeopAWskO58BA27GqTmnSLooeo%2FrtLxc1NZeuau11YxNzwl%2FvN8%2FQ5IsR3Xic8X1TaCCtwg%3D%3D;RelayState=fake%5B%5D;SAMLRequest=fZHNasMwEIRfxeieWrYTtQjb4DgJBNqSNqWHXopw1kQgS6523Z%2B3r%2BxQSKDkOppvd2aVo%2BpML6uBjvYZPgZAir47Y1FODwUbvJVOoUZpVQcoqZH76uFepjdc9t6Ra5xhZ8h1QiGCJ%2B0si7argr0vxTLJ1guRilpU8%2FWtyKpNnaXrukoF32SCRa%2FgMfgLFvAAIQ6wtUjKUpB4wmc8nSX8hXOZ3Ml0%2FsaijfMNTIUK1iqDMGK7sFl%2Fwp9S5mNWOY3z5ZGol3GM%2FSLugNRBkcrjc0N%2ButJj6LNd7ZzRzc%2B4plN0ve6o6MOsnayyH6sggSUW7XfjsKdBGd1q8AX7JwOLKmPcV%2B1BUUhOfgAWl6dkl19W%2FgI%3D;SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1";
|
||||
const char query3[] = "RelayState=fake%5B%5D&SAMLRequest=fZHNasMwEIRfxeieWrYTtQjb4DgJBNqSNqWHXopw1kQgS6523Z%2B3r%2BxQSKDkOppvd2aVo%2BpML6uBjvYZPgZAir47Y1FODwUbvJVOoUZpVQcoqZH76uFepjdc9t6Ra5xhZ8h1QiGCJ%2B0si7argr0vxTLJ1guRilpU8%2FWtyKpNnaXrukoF32SCRa%2FgMfgLFvAAIQ6wtUjKUpB4wmc8nSX8hXOZ3Ml0%2FsaijfMNTIUK1iqDMGK7sFl%2Fwp9S5mNWOY3z5ZGol3GM%2FSLugNRBkcrjc0N%2ButJj6LNd7ZzRzc%2B4plN0ve6o6MOsnayyH6sggSUW7XfjsKdBGd1q8AX7JwOLKmPcV%2B1BUUhOfgAWl6dkl19W%2FgI%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=wDxMSEPKhK%2FuU06cmL50oVx%2B7eP5%2FQirShQE%2BLv9pT3CrVwb6WBV1Tp9XS2VVJ2odLHogdA%2FE1XDW7BIRKYgkN8bXVlC2GybSYBhyn8bwAuyHs%2BnMW48LF%2FE5vFiZxbw8tMWUAktdvDuaXoZLhubX7UgV%2B%2BdRyjhckolpXTC9xuJdoHJUDF0vzzNm8xZs6LR7tjWUoz5CcjMJA3LVfWmpE5UjCyRmGbi9knGWHdY75CFtArD%2BNSkGeNx9xySrUlik6e57Zlodv4V9WBdeopAWskO58BA27GqTmnSLooeo%2FrtLxc1NZeuau11YxNzwl%2FvN8%2FQ5IsR3Xic8X1TacCtwg%3D%3D";
|
||||
/* sp5-saml2 key */
|
||||
const char pkey[] = "-----BEGIN CERTIFICATE-----\n\
|
||||
MIIDnjCCAoagAwIBAgIBATANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJGUjEP\n\
|
||||
MA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczETMBEGA1UEChMKRW50cm91\n\
|
||||
dmVydDEPMA0GA1UEAxMGRGFtaWVuMB4XDTA2MTAyNzA5MDc1NFoXDTExMTAyNjA5\n\
|
||||
MDc1NFowVDELMAkGA1UEBhMCRlIxDzANBgNVBAgTBkZyYW5jZTEOMAwGA1UEBxMF\n\
|
||||
UGFyaXMxEzARBgNVBAoTCkVudHJvdXZlcnQxDzANBgNVBAMTBkRhbWllbjCCASIw\n\
|
||||
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM06Hx6VgHYR9wUf/tZVVTRkVWNq\n\
|
||||
h9x+PvHA2qH4OYMuqGs4Af6lU2YsZvnrmRdcFWv0+UkdAgXhReCWAZgtB1pd/W9m\n\
|
||||
6qDRldCCyysow6xPPKRz/pOTwRXm/fM0QGPeXzwzj34BXOIOuFu+n764vKn18d+u\n\
|
||||
uVAEzk1576pxTp4pQPzJfdNLrLeQ8vyCshoFU+MYJtp1UA+h2JoO0Y8oGvywbUxH\n\
|
||||
ioHN5PvnzObfAM4XaDQohmfxM9Uc7Wp4xKAc1nUq5hwBrHpjFMRSz6UCfMoJSGIi\n\
|
||||
+3xJMkNCjL0XEw5NKVc5jRKkzSkN5j8KTM/k1jPPsDHPRYzbWWhnNtd6JlkCAwEA\n\
|
||||
AaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0\n\
|
||||
ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFP2WWMDShux3iF74+SoO1xf6qhqaMB8G\n\
|
||||
A1UdIwQYMBaAFGjl6TRXbQDHzSlZu+e8VeBaZMB5MA0GCSqGSIb3DQEBBQUAA4IB\n\
|
||||
AQAZ/imK7UMognXbs5RfSB8cMW6iNAI+JZqe9XWjvtmLfIIPbHM96o953SiFvrvQ\n\
|
||||
BZjGmmPMK3UH29cjzDx1R/RQaYTyMrHyTePLh3BMd5mpJ/9eeJCSxPzE2ECqWRUa\n\
|
||||
pkjukecFXqmRItwgTxSIUE9QkpzvuQRb268PwmgroE0mwtiREADnvTFkLkdiEMew\n\
|
||||
fiYxZfJJLPBqwlkw/7f1SyzXoPXnz5QbNwDmrHelga6rKSprYKb3pueqaIe8j/AP\n\
|
||||
NC1/bzp8cGOcJ88BD5+Ny6qgPVCrMLE5twQumJ12V3SvjGNtzFBvg2c/9S5OmVqR\n\
|
||||
LlTxKnCrWAXftSm1rNtewTsF\n\
|
||||
-----END CERTIFICATE-----";
|
||||
LassoKey *key = lasso_key_new_for_signature_from_memory(pkey, strlen(pkey), NULL,
|
||||
LASSO_SIGNATURE_METHOD_RSA_SHA1, NULL);
|
||||
LassoKey *key2 = lasso_key_new_for_signature_from_file(
|
||||
TESTSDATADIR "/sp5-saml2/private-key.pem", NULL,
|
||||
LASSO_SIGNATURE_METHOD_RSA_SHA1, NULL);
|
||||
char *message = "<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"_E3F8E9116EE08F0E2607CF9789649BB4\" Version=\"2.0\" IssueInstant=\"2012-03-09T11:34:48Z\" ForceAuthn=\"false\" IsPassive=\"false\"><saml:Issuer>http://sp5/metadata</saml:Issuer><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n\
|
||||
<SignedInfo>\n\
|
||||
<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n\
|
||||
<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\n\
|
||||
<Reference URI=\"#_E3F8E9116EE08F0E2607CF9789649BB4\">\n\
|
||||
<Transforms>\n\
|
||||
<Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\n\
|
||||
<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\n\
|
||||
</Transforms>\n\
|
||||
<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\n\
|
||||
<DigestValue>tMncKjklMJaJLbmB7bARmX14Fdg=</DigestValue>\n\
|
||||
</Reference>\n\
|
||||
</SignedInfo>\n\
|
||||
<SignatureValue>VjAHErXE8rz5yQ/t9Ubws11E59PsU/tXPtL6eCMAVLQxV4Bv0dwyYkeHtge1DXDT\n\
|
||||
usTy1c17+iuYCVqD3Db51+LMVsHchj0j44fhu/PXNQTmgiT2AuVfH97YhiBWykAs\n\
|
||||
LwT8MiE9vNGiHQwsWVjhdzooVmU0M80m0Ij2DFMcYiKzmuMhE4M65qUO4tygQLiL\n\
|
||||
YB5oPe0VYKEBJLfaTvuijLBTi4ecx6aU+HptAvuEOcCbcJZtGyv7jr2yuEDSq72S\n\
|
||||
0hwOV0CIsQoSf/vL7R9RzTs2bpgYVGqgerhpWsz6dqo7YX0NSj9pMbXZiOyX/YzS\n\
|
||||
uP3QSjow05NiPhy8ywKW8A==</SignatureValue>\n\
|
||||
<KeyInfo>\n\
|
||||
<KeyValue>\n\
|
||||
<RSAKeyValue>\n\
|
||||
<Modulus>\n\
|
||||
zTofHpWAdhH3BR/+1lVVNGRVY2qH3H4+8cDaofg5gy6oazgB/qVTZixm+euZF1wV\n\
|
||||
a/T5SR0CBeFF4JYBmC0HWl39b2bqoNGV0ILLKyjDrE88pHP+k5PBFeb98zRAY95f\n\
|
||||
PDOPfgFc4g64W76fvri8qfXx3665UATOTXnvqnFOnilA/Ml900ust5Dy/IKyGgVT\n\
|
||||
4xgm2nVQD6HYmg7Rjyga/LBtTEeKgc3k++fM5t8AzhdoNCiGZ/Ez1RztanjEoBzW\n\
|
||||
dSrmHAGsemMUxFLPpQJ8yglIYiL7fEkyQ0KMvRcTDk0pVzmNEqTNKQ3mPwpMz+TW\n\
|
||||
M8+wMc9FjNtZaGc213omWQ==\n\
|
||||
</Modulus>\n\
|
||||
<Exponent>\n\
|
||||
AQAB\n\
|
||||
</Exponent>\n\
|
||||
</RSAKeyValue>\n\
|
||||
</KeyValue>\n\
|
||||
</KeyInfo>\n\
|
||||
</Signature><samlp:NameIDPolicy Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\" AllowCreate=\"true\"/></samlp:AuthnRequest>";
|
||||
xmlDoc *doc;
|
||||
|
||||
doc = xmlParseDoc(BAD_CAST message);
|
||||
fail_unless(key != NULL, "Cannot load public key");
|
||||
fail_unless(lasso_key_query_verify(key, query1) == 0, "Signature was not validated");
|
||||
/* test reordering and semi-colon separator support */
|
||||
fail_unless(lasso_key_query_verify(key, query2) == 0, "Disordered signature was not validated");
|
||||
fail_unless(lasso_key_query_verify(key, query3) != 0, "Altered signature was validated");
|
||||
fail_unless(lasso_key_saml2_xml_verify(key,
|
||||
"_E3F8E9116EE08F0E2607CF9789649BB4", xmlDocGetRootElement(doc)) == 0,
|
||||
"XML Signature is not validated");
|
||||
g_object_unref(key);
|
||||
fail_unless(key2 != NULL, "Cannot load public key2");
|
||||
fail_unless(lasso_key_query_verify(key2, query1) == 0, "Signature was not validated");
|
||||
/* test reordering and semi-colon separator support */
|
||||
fail_unless(lasso_key_query_verify(key2, query2) == 0, "Disordered signature was not validated");
|
||||
fail_unless(lasso_key_query_verify(key2, query3) != 0, "Altered signature was validated");
|
||||
fail_unless(lasso_key_saml2_xml_verify(key2,
|
||||
"_E3F8E9116EE08F0E2607CF9789649BB4", xmlDocGetRootElement(doc)) == 0,
|
||||
"XML Signature is not validated");
|
||||
g_object_unref(key2);
|
||||
lasso_release_doc(doc);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite*
|
||||
random_suite()
|
||||
{
|
||||
|
@ -335,6 +435,7 @@ random_suite()
|
|||
TCase *tc_providers = tcase_create("Provider stuffs");
|
||||
TCase *tc_servers = tcase_create("Server stuffs");
|
||||
TCase *tc_node = tcase_create("Node stuff");
|
||||
TCase *tc_keys = tcase_create("Lasso keys");
|
||||
|
||||
suite_add_tcase(s, tc_providers);
|
||||
tcase_add_test(tc_providers, test01_provider_new);
|
||||
|
@ -351,6 +452,9 @@ random_suite()
|
|||
tcase_add_test(tc_node, test06_lib_statuscode);
|
||||
tcase_add_test(tc_node, test07_saml2_query_verify_signature);
|
||||
|
||||
suite_add_tcase(s, tc_keys);
|
||||
tcase_add_test(tc_keys, test08_lasso_key);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue