validate_idp_list was not using the correct list elements when it
iterated over the known_sp_provided_idp_entries_supporting_ecp list.
It treated them as lists of strings instead of lists of
LassoSamlp2IDPEntry.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
CFLAGS is initialized to the empty string in configure.ac, this
effectively turned off user supplied values for CFLAGS preventing site
specific values from being used. A further complicating factor was of
all the user supplied values documented in Automake only CFLAGS was
disabled allowing all other user supplied variables to take
effect. Some variables must be coordinated (e.g. CFLAGS with LDFLAGS),
the fact LDFLAGS was picked up from the environment but CFLAGS was
discarded caused build failures due to incompatible combination of
compiler and linker options.
The problem was first introduced in commit: 73d9c98f "Reset CFLAGS
when --enable-debugging is used". This patch simply removes hardcoding
CFLAGS to the empty string and appends the debug options
(--enable-debugging) to the existing CFLAGS.
Proper use of the variables is described in the Automake documentation
in the section "Flag Variables Ordering"
https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
Although the Automake documentation claims manipulating CFLAGS
directly is improper use there are many examples of this in the
existing configure.ac, this patch makes no attempt at addressing this
issue, rather it makes existing usage consistent. In the particular
case of debug flags appending to CFLAGS is probably the only valid
solution because the debug flags must appear at the end of the list of
flags in order to override earlier flags, CFLAGS always appears last
in the Makefile (see above Automake doc).
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
This bug was introduced in commit 8d06806d, the check for a correct namespace on
head node of parsed XML fragments does not handle the case where the node has no
namespace. Using lasso_equal_namespace() fix this.
lasso_log is a private function of lasso and as such cannot be
referenced by the loader.
This is equivalent to commit e0bda691 in the PHP binding which
exhibited the same problem.
lasso_log is referenced in jobject_to_gobject() because of
lasso_assign_gobject macro, which includes the lasso_release_gobject
macro which invokes the message macro which expands to lasso_log.
License: MIT
Signed-off-by: John Dennis <jdennis@redhat.com>
enumeration type were being wrongly interpreted as objects types because
is_object() was used instead of the local specialisation done in
PhpCode.is_object().
Also fix docstring of getters/setters.
The new OASIS "SAML V2.0 Enhanced Client or Proxy Profile Version 2.0"
specification added new options that can appear in the PAOS HTTP header.
Section 2.3.1 enumerates the following URN options which can appear
in the PAOS HEADER:
urn:oasis:names:tc:SAML:protocol:ext:channel-binding
urn:oasis:names:tc:SAML:2.0:cm:holder-of-key
urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp:2.0:WantAuthnRequestsSigned
urn:oasis:names:tc:SAML:2.0:conditions:delegation
Of these only the holder-of-key was previously defined in Lasso,
this patch adds the other 3 constants.
License: MIT
Signed-off-by: John Dennis <jdennis@redhat.com>
Note: the rest of this message is formatted as reStructuredText (rst).
Test Failure
============
The unit tests run by "make check" fail with the following error:
::
tests.c:61:F:Lasso keys:test08_lasso_key:0: No logging output expected: message «ID _E3F8E9116EE08F0E2607CF9789649BB4 already defined
» was emitted for domain «Lasso» at the level «128»
This is not a regression in Lasso, rather the failure is caused by one
of the components Lasso is dependent upon. It was first observed when
the identical Lasso package was built in Fedora 22, no problems were
observed in Fedora 21. This implies one or more updated components in
Fedora 22 is the cause.
This was a particularity difficult error to track down, first one had
to identify who was emitting the message and on what file descriptor
(stream) and who was triggering on the message emission and causing a
check failure. The obvious assumption the check library was
responsible for detecting the message emission and failing the test is
wrong.
Who is emitting the message and why?
------------------------------------
The message is emitted by libxml2 in the function `xmlAddID()`
(valid.c:2578). It occurs at the end of xmlAddID() when it detects the
ID (which is supposed to be unique to the document is already defined,
which for valid XML is illegal (violates uniquenesss constraint). The
message emission occurs because of the code fragment
::
if (xmlHashAddEntry(table, value, ret) < 0) {
#ifdef LIBXML_VALID_ENABLED
/*
* The id is already defined in this DTD.
*/
xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
"ID %s already defined\n", value, NULL, NULL);
#endif /* LIBXML_VALID_ENABLED */
xmlFreeID(ret);
return(NULL);
}
Why is the message emission different between libxml2 versions?
---------------------------------------------------------------
The change occured between libxml2 version 2.9.1 and 2.9.2 in commit
a16eb968075a82ec33b2c1e77db8909a35b44620
::
commit a16eb968075a82ec33b2c1e77db8909a35b44620
Author: Daniel Veillard <veillard@redhat.com>
Date: Tue Jun 10 16:06:14 2014 +0800
erroneously ignores a validation error if no error callback set
Reported by Stefan Behnel
https://bugzilla.gnome.org/show_bug.cgi?id=724903
diff --git a/valid.c b/valid.c
index aedd9d7..1e03a7c 100644
--- a/valid.c
+++ b/valid.c
@@ -2633,11 +2633,8 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
/*
* The id is already defined in this DTD.
*/
- if ((ctxt != NULL) && (ctxt->error != NULL)) {
- xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
- "ID %s already defined\n",
- value, NULL, NULL);
- }
+ xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED,
+ "ID %s already defined\n", value, NULL, NULL);
#endif /* LIBXML_VALID_ENABLED */
xmlFreeID(ret);
return(NULL);
In both versions of libxml2 the conditional complilation
LIBXML_VALID_ENABLED is enabled by default via the configure
script. What is different is the the requirement ctxt be
non-NULL. Lasso invokes xmlAddID with a NULL ctxt parameter. Because
the NULL test for ctxt is absent in libxlm2 2.9.2 the message is now
emitted where previously it was not.
Who triggers on messge emission and fails the test?
---------------------------------------------------
This is a Lasso feature, it is not part of libcheck. In tests/tests.c
is the following function
::
void error_logger(const gchar *log_domain, GLogLevelFlags log_level,
const gchar *message, G_GNUC_UNUSED gpointer user_data)
{
fail("No logging output expected: message «%s» was emitted for domain «%s» at the level"
" «%d»", message, log_domain, log_level);
}
Before the test are run the error_logger function is installed as a
glib handler
::
g_log_set_default_handler(error_logger, NULL);
When the message is emitted the error_logger traps it and invokes the
libcheck (deprecated) function fail() which aborts the test case.
Why does `test08_lasso_key` cause an XML validation failure?
------------------------------------------------------------
`test08_lasso_key` invokes `lasso_key_saml2_xml_verify()` twice on the
same XML document. Any time `lasso_key_saml2_xml_verify()` is called
more than once the XML validation will fail on the second and
subsequent invocations. This occurs because
`lasso_key_saml2_xml_verify()` invokes `lasso_verify_signature()`
passing it the node id in the `id_attr_name` parameter. Inside
`lasso_verify_signature()` is this code fragment:
::
/* Find ID */
if (id_attr_name) {
id = xmlGetProp(signed_node, (xmlChar*)id_attr_name);
if (id) {
xmlAddID(NULL, doc, id, xmlHasProp(signed_node, (xmlChar*)id_attr_name));
}
}
Note that it unconditionally invokes `xmlAddID()`, which adds the ID
to the set of unique element ID's in the document. But if you invoke
`xmlAddID()` more than once with the same ID in the same document you
violate the uniqueness constraint.
The ID needs to be registered in the document because the <Reference>
element of the <SignedInfo> may utilize an XPointer reference to the
signed data. In it's simplest form the XPointer reference is an ID
attribute on a node. Thus to locate the signed data referenced by the
ID it should (must?) be in a table of ID's for the document.
Simple Solution (patch)
-----------------------
The solution is simple now that the problem is understood. The ID
should not be unconditionally added to the document, instead it should
only be added if it's not already registered. Prior to calling
`xmlAddID()` one should call `xmlGetID()` and test for a NULL result
indicating the ID has not be registered previously.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
lasso_get_hmac_key() did not check return value. Now check the return
code, emit a critical message and return early with cleanup.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
ECP needs a place to store the messageID and idp_list. Normally values
like this would located in a "context" passed to the relevant
routines. But currently there is no such context, the closest thing to
a context we have is the profile so we add them here in the profile
private data using accessors. They are currently not relevant outside
of ECP.
Adds functions:
lasso_profile_get_message_id()
lasso_profile_set_message_id()
lasso_profile_get_idp_list()
lasso_profile_set_idp_list()
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Re-implement lasso_profile_saml20_build_paos_request_msg() and
lasso_saml20_login_process_paos_response_msg() to use the
functionality introduced by earlier patches and to assure they are
functionally complete.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
ECP needs a place to store the messageID and idp_list. Normally values
like this would located in a "context" passed to the relevant
routines. But currently there is no such context, the closest thing to
a context we have is the profile so we add them here in the profile
private data using accessors. They are currently not relevant outside
of ECP.
Adds functions:
lasso_profile_get_message_id()
lasso_profile_set_message_id()
lasso_profile_get_idp_list()
lasso_profile_set_idp_list()
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
ECP does not require an SP to know the remote IdP provider. Existing
code made the assumption the remote provider always was
necessary. Determination and setting of the remote consumer URL is
different in the presence of ECP. Rework the logic to reflect
differing requirements.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Lasso uses an internal private variable bound to the provider to
indicate which protocol the provider is servicing. It is vital this
value be correctly set because many Lasso routines used it to dispatch
to the appropriate protocol handlers.
Normally the provider's protocol conformance is set as a side-effect
of parsing the XML metadata that describes the provider (e.g. an SP or
IdP). However there are some providers (e.g. an ECP client) which do
not have metadata. For providers lacking metadata it is essential
there be a mechanism to set the protocol conformance otherwise the
library will malfunction.
The function comes with documentation that includes a clear warning
this is to be used only in limited circumstances.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Implement everything needed to support a SAMLv2 ECP client.
Re-implement lasso_ecp_process_authn_request_msg() and
lasso_ecp_process_response_msg() to use the Lasso XML serialization
subsystem with the ECP and PASO LassoNode's introduced earlier. This
replaces one-off explicit direct use of the libxml API with Lasso
common code. In the process provide support for 100% of the ECP and
PAOS SAMLv2 parameters, not just a subset. Include support for
receiving an IDPList from the SP in conjuction with selecting an IdP
known to the ECP client. Add extensive documentation.
Modify LassoSamlp2AuthnRequest to preserve it's original XML (enable
keep_xmlnode flag) so that when serializing the SOAP request the
LassoSamlp2AuthnRequest received from the SP is exactly duplicated.
Add the following internal static utility functions:
is_provider_in_sp_idplist()
is_idp_entry_in_entity_id_list()
intersect_sp_idplist_with_entity_id_list()
Add the following exported utility functions:
lasso_ecp_is_provider_in_sp_idplist()
lasso_ecp_is_idp_entry_known_idp_supporting_ecp()
lasso_ecp_set_known_sp_provided_idp_entries_supporting_ecp()
lasso_ecp_has_sp_idplist()
lasso_ecp_get_endpoint_url_by_entity_id()
lasso_ecp_process_sp_idp_list()
Add the following members to the ECP class:
message_id
response_consumer_url
relaystate
issuer
provider_name
is_passive
sp_idp_list
known_sp_provided_idp_entries_supporting_ecp
known_idp_entity_ids_supporting_ecp
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Re-implement lasso_node_export_to_ecp_soap_response() and
lasso_node_export_to_paos_request(). Add new function
lasso_node_export_to_paos_request_full() with full functionality which
deprecates lasso_node_export_to_paos_request().
The existing code had two significant deficiencies, it performed
explicit direct xml manipulation using the libxml API rather than
calling into Lasso's extensive XML utilities, this was in stark
contrast the rest of the Lasso library. It also failed to handle a
number of ECP parameters leaving a functionality gap in the API.
The new code makes use of the Lasso XML serialization
subsystem. Rather than hand crafted xml manipulation we use the ECP
and PAOS LassoNode objects introduced in an earlier patch. This is
consistent with the rest of Lasso and because those LassoNodes are
used elsewhere we have a better guarantee of robustness because the
same common code is being called from multiple places. Other Lasso
common utilities (some introduced in previous patches) are invoked
instead of handcrafted xml manipulation, once again common code is
preferred.
Finally lasso_node_export_to_paos_request_full() was introduced to
expose in the Lasso API all ECP
parameters. lasso_node_export_to_paos_request() now trivially calls
into lasso_node_export_to_paos_request_full().
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Add lasso_server_get_filtered_provider_list() utility.
Iterate over the server providers and build a list of provider EntityID's who
have the specified role and at least one endpoint matching the
protocol_type and http_method. Return a GList list of EntityID's
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
Locate the provider in the server's list of providers, then select an
endpoint given the @endpoint_description and return that endpoint's URL.
If the provider cannot be found or if the provider does not have a
matching endpoint NULL will be returned.
Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT