lasso_saml20_login_process_authn_request_msg(LassoLogin *login, const char *authn_request_msg)
{
	LassoNode *request = NULL;
	LassoProfile *profile = LASSO_PROFILE(login);
	LassoSamlp2StatusResponse *response = NULL;
	LassoSamlp2AuthnRequest *authn_request = NULL;
	LassoProvider *remote_provider = NULL;
	LassoServer *server = NULL;
	const gchar *protocol_binding = NULL;
	const char *status1 = LASSO_SAML2_STATUS_CODE_RESPONDER;
	const char *status2 = NULL;
	int rc = 0;

	if (authn_request_msg == NULL) {
		if (profile->request == NULL) {
			return critical_error(LASSO_PROFILE_ERROR_MISSING_REQUEST);
		}

		/* AuthnRequest already set by .._init_idp_initiated_authn_request, or from a
		 * previously failed call to process_authn_request that we retry. */
		request = lasso_ref(profile->request);
	} else {
		request = lasso_samlp2_authn_request_new();
		lasso_check_good_rc(lasso_saml20_profile_process_any_request(profile, request, authn_request_msg));
	}
	if (! LASSO_IS_SAMLP2_AUTHN_REQUEST(request)) {
		return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
	}
	authn_request = LASSO_SAMLP2_AUTHN_REQUEST(request);
	/* intialize the response */
	response = (LassoSamlp2StatusResponse*) lasso_samlp2_response_new();
	lasso_assign_string(response->InResponseTo,
			LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
	/* reset response binding */
	login->protocolProfile = 0;

	/* find the remote provider */
	if (! authn_request->parent.Issuer || ! authn_request->parent.Issuer->content) {
		rc = LASSO_PROFILE_ERROR_INVALID_REQUEST;
		goto cleanup;
	}
	remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
	if (remote_provider == NULL) {
		rc = LASSO_PROFILE_ERROR_UNKNOWN_PROVIDER;
		goto cleanup;
	}
	lasso_extract_node_or_fail(server, lasso_profile_get_server(&login->parent), SERVER,
			LASSO_PROFILE_ERROR_MISSING_SERVER);
	remote_provider->role = LASSO_PROVIDER_ROLE_SP;
	server->parent.role = LASSO_PROVIDER_ROLE_IDP;

	if (((authn_request->ProtocolBinding != NULL) ||
			(authn_request->AssertionConsumerServiceURL != NULL)) &&
			(authn_request->AssertionConsumerServiceIndex != -1))
	{
		rc = LASSO_PROFILE_ERROR_INVALID_REQUEST;
		goto cleanup;
	}

	/* try to find a protocol profile for sending the response */
	protocol_binding = authn_request->ProtocolBinding;
	if (protocol_binding || authn_request->AssertionConsumerServiceURL)
	{
		if (authn_request->AssertionConsumerServiceURL) {
			if (protocol_binding) {
				if (! lasso_saml20_provider_check_assertion_consumer_service_url(
							remote_provider, 
							authn_request->AssertionConsumerServiceURL,
							authn_request->ProtocolBinding)) {
					// Sent ACS URL is unknown
					rc = LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE;
					goto cleanup;
				}
			} else {
				// Only ACS URL sent, choose the first associated binding
				protocol_binding = lasso_saml20_provider_get_assertion_consumer_service_binding_by_url(
						remote_provider, authn_request->AssertionConsumerServiceURL);
				if (! protocol_binding) {
					rc = LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE;
					goto cleanup;
				}
				lasso_assign_string(authn_request->ProtocolBinding,
						protocol_binding);
			}
		}

		if (lasso_strisequal(protocol_binding,LASSO_SAML2_METADATA_BINDING_ARTIFACT)) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART;
		} else if (lasso_strisequal(protocol_binding,LASSO_SAML2_METADATA_BINDING_POST)) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST;
		} else if (lasso_strisequal(protocol_binding,LASSO_SAML2_METADATA_BINDING_SOAP)) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP;
		} else if (lasso_strisequal(protocol_binding,LASSO_SAML2_METADATA_BINDING_REDIRECT)) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_REDIRECT;
			goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE);
		} else if (lasso_strisequal(protocol_binding,LASSO_SAML2_METADATA_BINDING_PAOS)) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP;
		} else {
			rc = LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE;
			goto cleanup;
		}
	} else {
		/* protocol binding not set; so it will look into
		 * AssertionConsumerServiceIndex
		 * Also, if AssertionConsumerServiceIndex is not set in request,
		 * its value will be -1, which is just the right value to get
		 * default assertion consumer...  (convenient)
		 */
		gchar *binding;
		int service_index = authn_request->AssertionConsumerServiceIndex;

		binding = lasso_saml20_provider_get_assertion_consumer_service_binding(
				remote_provider, service_index);
		if (binding == NULL) {
			if (service_index == -1) {
				goto_cleanup_with_rc(LASSO_LOGIN_ERROR_NO_DEFAULT_ENDPOINT);
			} else {
				goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_PROTOCOLPROFILE);
			}
		} else if (lasso_strisequal(binding,"HTTP-Artifact")) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART;
		} else if (lasso_strisequal(binding,"HTTP-POST")) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_POST;
		} else if (lasso_strisequal(binding,"HTTP-Redirect")) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_REDIRECT;
		} else if (lasso_strisequal(binding,"SOAP")) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP;
		} else if (lasso_strisequal(binding,"PAOS")) {
			login->protocolProfile = LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_LECP;
		}
		lasso_release_string(binding);
	}


	if (_lasso_login_must_verify_authn_request_signature(profile) && profile->signature_status)
	{
		status1 = LASSO_SAML2_STATUS_CODE_REQUESTER;
		status2 = LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE;
		rc = profile->signature_status;
	} else {
		status1 = LASSO_SAML2_STATUS_CODE_SUCCESS;
		status2 = NULL;
	}
	lasso_saml20_profile_init_response(profile, response,
				status1, status2);
cleanup:
	lasso_release_gobject(request);
	lasso_release_gobject(response);
	return rc;
}