add ECP unit test

Test ECP.
3 different variations of the SP provided IDP List are exercised.

Signed-off-by: John Dennis <jdennis@redhat.com>
License: MIT
This commit is contained in:
John Dennis 2015-06-05 07:51:38 -04:00 committed by Benjamin Dauvergne
parent 9a2f8d404e
commit 964530aaca
1 changed files with 385 additions and 0 deletions

View File

@ -1131,6 +1131,386 @@ START_TEST(test08_test_authnrequest_flags)
}
END_TEST
typedef enum {
ECP_IDP_LIST_NONE,
ECP_IDP_LIST_ECP,
ECP_IDP_LIST_BOGUS,
} EcpIdpListVariant;
/* Build an IDPList whose members have an endpoint supporing
* the protocol_type and http_method.
*/
static LassoNode *
get_idp_list(const LassoServer *server, LassoMdProtocolType protocol_type, LassoHttpMethod http_method)
{
GList *idp_entity_ids = NULL;
GList *entity_id = NULL;
GList *idp_entries = NULL;
LassoSamlp2IDPList *idp_list;
LassoSamlp2IDPEntry *idp_entry;
idp_list = LASSO_SAMLP2_IDP_LIST(lasso_samlp2_idp_list_new());
idp_entity_ids =
lasso_server_get_filtered_provider_list(server,
LASSO_PROVIDER_ROLE_IDP,
protocol_type, http_method);
for (entity_id = g_list_first(idp_entity_ids); entity_id != NULL;
entity_id = g_list_next(entity_id)) {
idp_entry = LASSO_SAMLP2_IDP_ENTRY(lasso_samlp2_idp_entry_new());
idp_entry->ProviderID = g_strdup(entity_id->data);
idp_entry->Name = g_strdup_printf("[NAME] %s", idp_entry->ProviderID);
idp_entry->Loc = g_strdup_printf("[LOCATION] %s", idp_entry->ProviderID);
idp_entries = g_list_append(idp_entries, idp_entry);
}
lasso_release_list_of_strings(idp_entity_ids);
idp_list->IDPEntry = idp_entries;
return LASSO_NODE(idp_list);
}
static LassoNode *
get_bogus_idp_list()
{
char *idp_entity_ids[] = {"http://bogus_1/metadata", NULL};
char **idp_entity_id_iter = NULL;
char *entity_id = NULL;
GList *idp_entries = NULL;
LassoSamlp2IDPList *idp_list;
LassoSamlp2IDPEntry *idp_entry;
idp_list = LASSO_SAMLP2_IDP_LIST(lasso_samlp2_idp_list_new());
for (idp_entity_id_iter = idp_entity_ids, entity_id = *idp_entity_id_iter;
*idp_entity_id_iter != NULL;
idp_entity_id_iter++) {
idp_entry = LASSO_SAMLP2_IDP_ENTRY(lasso_samlp2_idp_entry_new());
idp_entry->ProviderID = g_strdup(entity_id);
idp_entry->Name = g_strdup_printf("[NAME] %s", idp_entry->ProviderID);
idp_entry->Loc = g_strdup_printf("[LOCATION] %s", idp_entry->ProviderID);
idp_entries = g_list_append(idp_entries, idp_entry);
}
idp_list->IDPEntry = idp_entries;
return LASSO_NODE(idp_list);
}
static void validate_idp_list(LassoEcp *ecp, EcpIdpListVariant ecpIDPListVariant, LassoSamlp2IDPList *idp_list)
{
if (ecpIDPListVariant == ECP_IDP_LIST_NONE) {
check_null(ecp->sp_idp_list);
check_null(ecp->known_sp_provided_idp_entries_supporting_ecp);
} else if (ecpIDPListVariant == ECP_IDP_LIST_ECP || ecpIDPListVariant == ECP_IDP_LIST_BOGUS) {
GList *ecp_iter, *src_iter;
check_not_null(ecp->sp_idp_list);
check_not_null(idp_list);
check_null(ecp->sp_idp_list->GetComplete);
check_null(idp_list->GetComplete);
check_equals(g_list_length(ecp->sp_idp_list->IDPEntry),
g_list_length(idp_list->IDPEntry));
for (ecp_iter = g_list_first(ecp->sp_idp_list->IDPEntry), src_iter = g_list_first(idp_list->IDPEntry);
ecp_iter && src_iter;
ecp_iter = g_list_next(ecp_iter), src_iter = g_list_next(src_iter)) {
LassoSamlp2IDPEntry *ecp_item, *src_item;
ecp_item = LASSO_SAMLP2_IDP_ENTRY(ecp_iter->data);
src_item = LASSO_SAMLP2_IDP_ENTRY(src_iter->data);
check_not_null(ecp_item->ProviderID);
check_not_null(src_item->ProviderID);
check_str_equals(ecp_item->ProviderID, src_item->ProviderID);
check_not_null(ecp_item->Name);
check_not_null(src_item->Name);
check_str_equals(ecp_item->Name, src_item->Name);
check_not_null(ecp_item->Loc);
check_not_null(src_item->Loc);
check_str_equals(ecp_item->Loc, src_item->Loc);
}
if (ecpIDPListVariant == ECP_IDP_LIST_ECP) {
check_not_null(ecp->known_sp_provided_idp_entries_supporting_ecp);
for (ecp_iter = g_list_first(ecp->known_sp_provided_idp_entries_supporting_ecp),
src_iter = g_list_first(idp_list->IDPEntry);
ecp_iter && src_iter;
ecp_iter = g_list_next(ecp_iter), src_iter = g_list_next(src_iter)) {
gchar *ecp_item, *src_item;
ecp_item = ecp_iter->data;
src_item = src_iter->data;
check_not_null(ecp_item);
check_not_null(src_item);
check_str_equals(ecp_item, src_item);
}
} else {
check_null(ecp->known_sp_provided_idp_entries_supporting_ecp);
}
}
check_equals(g_list_length(ecp->known_idp_entity_ids_supporting_ecp), 1);
check_str_equals((char*)g_list_nth(ecp->known_idp_entity_ids_supporting_ecp, 0)->data, "http://idp5/metadata");
}
void test_ecp(EcpIdpListVariant ecpIDPListVariant)
{
char *serviceProviderContextDump = NULL, *identityProviderContextDump = NULL;
LassoServer *spContext = NULL, *ecpContext=NULL, *idpContext = NULL;
LassoLogin *spLoginContext = NULL, *idpLoginContext = NULL;
LassoEcp *ecp = NULL;
LassoSamlp2AuthnRequest *request = NULL;
gboolean is_passive = FALSE;
char *provider_name = NULL;
char *relayState = NULL;
char *messageID = NULL;
char *spPaosRequestMsg = NULL;
char *ecpSoapRequestMsg = NULL;
char *idpSoapResponseMsg = NULL;
char *ecpPaosResponseMsg = NULL;
char *spLoginDump = NULL;
LassoSaml2Assertion *assertion;
LassoSamlp2IDPList *idp_list = NULL;
/*
* SAML2 Profile for ECP (Section 4.2) defines these steps for an ECP
* transaction
*
* 1. ECP issues HTTP Request to SP
* 2. SP issues <AuthnRequest> to ECP using PAOS
* 3. ECP determines IdP
* 4. ECP conveys <AuthnRequest> to IdP using SOAP
* 5. IdP identifies principal
* 6. IdP issues <Response> to ECP, targeted at SP using SOAP
* 7. ECP conveys <Response> to SP using PAOS
* 8. SP grants or denies access to principal
*/
/*
* Act as the SP who generates an AuthnRequest & conveys it in PAOS
*/
/* Create new SP Login Context */
serviceProviderContextDump = generateServiceProviderContextDump();
spContext = lasso_server_new_from_dump(serviceProviderContextDump);
spLoginContext = lasso_login_new(spContext);
check_not_null(spLoginContext);
check_good_rc(lasso_login_init_authn_request(spLoginContext, "http://idp5/metadata",
LASSO_HTTP_METHOD_PAOS));
/* Set PAOS authn request parameters */
request = LASSO_SAMLP2_AUTHN_REQUEST(LASSO_PROFILE(spLoginContext)->request);
fail_unless(LASSO_IS_SAMLP2_AUTHN_REQUEST(request), "request should be authn_request");
request->IsPassive = is_passive;
lasso_assign_string(request->NameIDPolicy->Format, LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT);
request->NameIDPolicy->AllowCreate = 1;
provider_name = "test_sp_001";
lasso_assign_string(request->ProviderName, provider_name);
relayState = "fake[]";
lasso_assign_string(LASSO_PROFILE(spLoginContext)->msg_relayState, relayState);
messageID = "id-1234";
lasso_profile_set_message_id(LASSO_PROFILE(spLoginContext), messageID);
if (ecpIDPListVariant == ECP_IDP_LIST_ECP) {
idp_list = LASSO_SAMLP2_IDP_LIST(get_idp_list(spContext,
LASSO_MD_PROTOCOL_TYPE_SINGLE_SIGN_ON,
LASSO_HTTP_METHOD_SOAP));
lasso_profile_set_idp_list(LASSO_PROFILE(spLoginContext), LASSO_NODE(idp_list));
} else if (ecpIDPListVariant == ECP_IDP_LIST_BOGUS) {
idp_list = LASSO_SAMLP2_IDP_LIST(get_bogus_idp_list());
lasso_profile_set_idp_list(LASSO_PROFILE(spLoginContext), LASSO_NODE(idp_list));
}
/* Build PAOS authn request message */
check_good_rc(lasso_login_build_authn_request_msg(spLoginContext));
/*
* spPaosRequestMsg is what will be sent back to the ECP client.
* No reason to validate the contents of spPaosRequestMsg here
* because in the next step the spPaosRequestMsg will be parsed
* and we'll validate the parsed values.
*/
lasso_assign_string(spPaosRequestMsg, LASSO_PROFILE(spLoginContext)->msg_body);
check_not_null(spPaosRequestMsg);
check_null(LASSO_PROFILE(spLoginContext)->msg_url);
check_not_null(strstr(spPaosRequestMsg, "RelayState"));
/* Finished with SP Login Context, will create new one later */
lasso_server_destroy(spContext);
spContext = NULL;
spLoginDump = lasso_node_dump(LASSO_NODE(spLoginContext));
lasso_login_destroy(spLoginContext);
spLoginContext = NULL;
/*
* Act as the ECP client who just received a PAOS request (spPaosRequestMsg).
*/
/* Create an ECP client & load an IdP */
ecpContext = lasso_server_new(NULL, NULL, NULL, NULL);
lasso_provider_set_protocol_conformance(LASSO_PROVIDER(ecpContext), LASSO_PROTOCOL_SAML_2_0);
lasso_server_add_provider(ecpContext, LASSO_PROVIDER_ROLE_IDP,
TESTSDATADIR "/idp5-saml2/metadata.xml", NULL, NULL);
ecp = lasso_ecp_new(ecpContext);
check_not_null(ecp);
/* parse the spPaosRequestMsg */
check_good_rc(lasso_ecp_process_authn_request_msg(ecp, spPaosRequestMsg));
/* Validate ECP properties received in the spPaosRequestMsg */
check_null(ecp->assertion_consumer_url);
check_str_equals(ecp->response_consumer_url, "http://sp5/singleSignOnSOAP");
check_str_equals(ecp->message_id, messageID);
check_str_equals(ecp->relaystate, relayState);
check_str_equals(ecp->issuer->content, "http://sp5/metadata");
check_str_equals(ecp->provider_name, provider_name);
check_equals(ecp->is_passive, is_passive);
/* Validate ECP IdP list info & default IdP URL */
validate_idp_list(ecp, ecpIDPListVariant, idp_list);
check_str_equals(LASSO_PROFILE(ecp)->msg_url, "http://idp5/singleSignOnSOAP");
/*
* ecpSoapRequestMsg is what we'll post to the IdP at the msg_url.
*/
lasso_assign_string(ecpSoapRequestMsg, LASSO_PROFILE(ecp)->msg_body);
check_not_null(ecpSoapRequestMsg);
/*
* Act as the IdP which just received the SOAP request (ecpSoapRequestMsg)
*/
/* Create an IdP */
identityProviderContextDump = generateIdentityProviderContextDump();
idpContext = lasso_server_new_from_dump(identityProviderContextDump);
idpLoginContext = lasso_login_new(idpContext);
check_not_null(idpLoginContext);
/* Parse the ecpSoapRequestMsg */
check_good_rc(lasso_login_process_authn_request_msg(idpLoginContext, ecpSoapRequestMsg));
check_true(lasso_login_must_authenticate(idpLoginContext));
check_equals(idpLoginContext->protocolProfile, LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP);
check_false(lasso_login_must_ask_for_consent(idpLoginContext));
check_good_rc(lasso_login_validate_request_msg(idpLoginContext,
1, /* authentication_result */
0 /* is_consent_obtained */ ));
/* Build IdP response */
check_good_rc(lasso_login_build_assertion(idpLoginContext,
LASSO_SAML_AUTHENTICATION_METHOD_PASSWORD,
"FIXME: authenticationInstant",
"FIXME: reauthenticateOnOrAfter",
"FIXME: notBefore",
"FIXME: notOnOrAfter"));
assertion = (LassoSaml2Assertion*)lasso_login_get_assertion(idpLoginContext);
check_true(LASSO_IS_SAML2_ASSERTION(assertion));
lasso_saml2_assertion_set_basic_conditions(LASSO_SAML2_ASSERTION(assertion), 60, 120, FALSE);
lasso_release_gobject(assertion);
/* Build IdP SOAP response message */
check_good_rc(lasso_login_build_response_msg(idpLoginContext, NULL));
/* idpSoapResponseMsg is what we'll send back to the ECP client */
lasso_assign_string(idpSoapResponseMsg, LASSO_PROFILE(idpLoginContext)->msg_body);
check_not_null(idpSoapResponseMsg);
/*
* Resume acting as the ECP client, process IdP response
*/
check_good_rc(lasso_ecp_process_response_msg(ecp, idpSoapResponseMsg));
/* Validate ECP properties, only the assertion_consumer_url should have changed */
check_str_equals(ecp->assertion_consumer_url, "http://sp5/singleSignOnSOAP");
check_str_equals(ecp->response_consumer_url, "http://sp5/singleSignOnSOAP");
check_str_equals(ecp->response_consumer_url, ecp->assertion_consumer_url); /* MUST match! */
check_str_equals(ecp->message_id, messageID);
check_str_equals(ecp->relaystate, relayState);
check_str_equals(ecp->issuer->content, "http://sp5/metadata");
check_str_equals(ecp->provider_name, provider_name);
check_equals(ecp->is_passive, is_passive);
/* Validate ECP IdP list info */
validate_idp_list(ecp, ecpIDPListVariant, idp_list);
lasso_assign_string(ecpPaosResponseMsg, LASSO_PROFILE(ecp)->msg_body);
check_not_null(ecpPaosResponseMsg);
check_str_equals(LASSO_PROFILE(ecp)->msg_url, ecp->assertion_consumer_url);
/* Act as the SP again which has just been posted the ecpPaosResponseMsg */
/* Create new SP Login Context */
spContext = lasso_server_new_from_dump(serviceProviderContextDump);
spLoginContext = lasso_login_new(spContext);
check_not_null(spLoginContext);
/* Parse the ecpPaosResponseMsg */
check_good_rc(lasso_login_process_paos_response_msg(spLoginContext, ecpPaosResponseMsg));
/* Verify we got back the same relayState and messageID */
check_str_equals(LASSO_PROFILE(spLoginContext)->msg_relayState, relayState);
check_str_equals(lasso_profile_get_message_id(LASSO_PROFILE(spLoginContext)), messageID);
g_free(serviceProviderContextDump);
g_free(identityProviderContextDump);
lasso_release_gobject(spContext);
lasso_release_gobject(ecpContext);
lasso_release_gobject(idpContext);
lasso_release_gobject(spLoginContext);
lasso_release_gobject(idpLoginContext);
lasso_release_gobject(ecp);
lasso_release_string(spLoginDump);
lasso_release_string(spPaosRequestMsg);
lasso_release_string(ecpSoapRequestMsg);
lasso_release_string(idpSoapResponseMsg);
lasso_release_string(ecpPaosResponseMsg);
lasso_release_gobject(idp_list);
}
START_TEST(test09_ecp)
{
test_ecp(ECP_IDP_LIST_NONE);
}
END_TEST
START_TEST(test10_ecp)
{
test_ecp(ECP_IDP_LIST_ECP);
}
END_TEST
START_TEST(test11_ecp)
{
test_ecp(ECP_IDP_LIST_BOGUS);
}
END_TEST
Suite*
login_saml2_suite()
{
@ -1142,6 +1522,7 @@ login_saml2_suite()
TCase *tc_idpKeyRollover = tcase_create("Login initiated by idp, idp use two differents signing keys (simulate key roll-over)");
TCase *tc_spKeyRollover = tcase_create("Login initiated by idp, sp use two differents encrypting keys (simulate key roll-over)");
TCase *tc_hmacSignature = tcase_create("Login initiated by sp, using shared-key signature");
TCase *tc_ecp = tcase_create("ECP Login");
suite_add_tcase(s, tc_generate);
suite_add_tcase(s, tc_spLogin);
suite_add_tcase(s, tc_spLoginMemory);
@ -1149,6 +1530,7 @@ login_saml2_suite()
suite_add_tcase(s, tc_idpKeyRollover);
suite_add_tcase(s, tc_spKeyRollover);
suite_add_tcase(s, tc_hmacSignature);
suite_add_tcase(s, tc_ecp);
tcase_add_test(tc_generate, test01_saml2_generateServersContextDumps);
tcase_add_test(tc_spLogin, test02_saml2_serviceProviderLogin);
tcase_add_test(tc_spLoginMemory, test03_saml2_serviceProviderLogin);
@ -1157,6 +1539,9 @@ login_saml2_suite()
tcase_add_test(tc_spKeyRollover, test06_sso_sp_with_key_rollover);
tcase_add_test(tc_hmacSignature, test07_sso_sp_with_hmac_sha1_signatures);
tcase_add_test(tc_spLogin, test08_test_authnrequest_flags);
tcase_add_test(tc_ecp, test09_ecp);
tcase_add_test(tc_ecp, test10_ecp);
tcase_add_test(tc_ecp, test11_ecp);
return s;
}