33
33
#include <lasso/id-ff/identityprivate.h>
34
34
#include <lasso/id-ff/sessionprivate.h>
35
35
#include <lasso/id-ff/profileprivate.h>
36
#include <lasso/id-ff/serverprivate.h>
38
#include <lasso/xml/xml_enc.h>
37
40
#include <lasso/xml/saml-2.0/samlp2_logout_request.h>
38
41
#include <lasso/xml/saml-2.0/samlp2_logout_response.h>
51
54
LassoFederation *federation;
52
55
LassoSession *session;
53
56
LassoSamlp2RequestAbstract *request;
57
LassoSaml2EncryptedElement *encrypted_element = NULL;
55
59
/* session existence has been checked in id-ff/ */
56
60
session = lasso_profile_get_session(profile);
58
62
assertion_n = lasso_session_get_assertion(session, profile->remote_providerID);
59
63
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
60
message(G_LOG_LEVEL_CRITICAL, "Assertion not found");
61
return LASSO_ERROR_UNDEFINED;
64
return critical_error(LASSO_PROFILE_ERROR_MISSING_ASSERTION);
64
67
assertion = LASSO_SAML2_ASSERTION(assertion_n);
66
69
if (assertion->Subject == NULL) {
67
return LASSO_ERROR_UNDEFINED;
70
return LASSO_PROFILE_ERROR_MISSING_SUBJECT;
73
if (assertion->Subject->NameID == NULL) {
74
return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
70
77
name_id = assertion->Subject->NameID;
71
78
if (name_id->Format && strcmp(name_id->Format,
72
79
LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) == 0) {
80
char *name_id_sp_name_qualifier = NULL;
73
82
if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
74
83
return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
86
if (remote_provider->private_data->affiliation_id) {
87
name_id_sp_name_qualifier = remote_provider->private_data->affiliation_id;
89
name_id_sp_name_qualifier = profile->remote_providerID;
76
92
federation = g_hash_table_lookup(profile->identity->federations,
77
profile->remote_providerID);
93
name_id_sp_name_qualifier);
78
94
if (federation == NULL) {
79
95
return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
146
162
LASSO_SAMLP2_LOGOUT_REQUEST(request)->NameID = g_object_ref(profile->nameIdentifier);
148
/* XXX: SessionIndex */
165
if (remote_provider &&
166
remote_provider->private_data->encryption_mode & LASSO_ENCRYPTION_MODE_NAMEID
167
&& remote_provider->private_data->encryption_public_key != NULL) {
168
encrypted_element = LASSO_SAML2_ENCRYPTED_ELEMENT(lasso_node_encrypt(
169
LASSO_NODE(LASSO_SAMLP2_LOGOUT_REQUEST(request)->NameID),
170
remote_provider->private_data->encryption_public_key,
171
remote_provider->private_data->encryption_sym_key_type));
172
if (encrypted_element != NULL) {
173
LASSO_SAMLP2_LOGOUT_REQUEST(request)->EncryptedID = encrypted_element;
174
LASSO_SAMLP2_LOGOUT_REQUEST(request)->NameID = NULL;
150
178
logout->initial_http_request_method = http_method;
159
187
LassoProfile *profile = LASSO_PROFILE(logout);
189
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->sign_method =
190
LASSO_SIGNATURE_METHOD_RSA_SHA1;
191
if (profile->server->certificate) {
192
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->sign_type =
193
LASSO_SIGNATURE_TYPE_WITHX509;
195
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->sign_type =
196
LASSO_SIGNATURE_TYPE_SIMPLE;
161
198
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->private_key_file =
162
199
g_strdup(profile->server->private_key);
163
200
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->certificate_file =
166
203
if (logout->initial_http_request_method == LASSO_HTTP_METHOD_SOAP) {
167
204
profile->msg_url = lasso_provider_get_metadata_one(remote_provider,
168
205
"SingleLogoutService SOAP");
206
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Destination = g_strdup(
169
208
profile->msg_body = lasso_node_export_to_soap(profile->request);
177
216
if (url == NULL) {
178
217
return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
219
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Destination = g_strdup(url);
180
220
query = lasso_node_export_to_query(profile->request,
181
221
profile->server->signature_method,
182
222
profile->server->private_key);
185
225
return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
187
profile->msg_url = g_strdup_printf("%s?%s", url, query);
227
profile->msg_url = lasso_concat_url_query(url, query);
228
profile->msg_body = NULL;
199
242
LassoProfile *profile = LASSO_PROFILE(logout);
200
243
LassoProvider *remote_provider;
201
244
LassoMessageFormat format;
245
LassoSaml2NameID *name_id;
246
LassoSaml2EncryptedElement *encrypted_id;
247
LassoSaml2EncryptedElement* encrypted_element = NULL;
248
xmlSecKey *encryption_private_key = NULL;
203
250
profile->request = lasso_samlp2_logout_request_new();
204
251
format = lasso_node_init_from_message(LASSO_NODE(profile->request), request_msg);
206
253
return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
256
if (profile->remote_providerID) {
257
g_free(profile->remote_providerID);
260
if (LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->relayState) {
261
profile->msg_relayState = g_strdup(
262
LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->relayState);
265
profile->remote_providerID = g_strdup(
266
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
210
267
remote_provider = g_hash_table_lookup(profile->server->providers,
211
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
268
profile->remote_providerID);
212
270
if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
213
271
return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
222
280
if (format == LASSO_MESSAGE_FORMAT_QUERY)
223
281
profile->http_request_method = LASSO_HTTP_METHOD_REDIRECT;
225
profile->nameIdentifier = g_object_ref(
226
LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID);
283
name_id = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID;
284
encrypted_id = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->EncryptedID;
286
if (name_id == NULL && encrypted_id != NULL) {
287
encryption_private_key = profile->server->private_data->encryption_private_key;
288
encrypted_element = LASSO_SAML2_ENCRYPTED_ELEMENT(encrypted_id);
289
if (encrypted_element != NULL && encryption_private_key == NULL) {
290
return LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
292
if (encrypted_element != NULL && encryption_private_key != NULL) {
293
profile->nameIdentifier = LASSO_NODE(lasso_node_decrypt(
294
encrypted_id, encryption_private_key));
295
LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID = LASSO_SAML2_NAME_ID(
296
profile->nameIdentifier);
297
LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->EncryptedID = NULL;
301
profile->nameIdentifier = g_object_ref(name_id);
228
305
return profile->signature_status;
242
319
if (LASSO_IS_SAMLP2_LOGOUT_REQUEST(profile->request) == FALSE)
243
320
return LASSO_PROFILE_ERROR_MISSING_REQUEST;
322
if (profile->remote_providerID) {
323
g_free(profile->remote_providerID);
245
326
profile->remote_providerID = g_strdup(
246
327
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
286
367
/* Get the name identifier */
287
name_id = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID;
368
name_id = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->NameID;
288
369
if (name_id == NULL) {
289
370
message(G_LOG_LEVEL_CRITICAL, "Name identifier not found in logout request");
290
371
/* XXX: which status code in SAML 2.0 ? */
302
383
/* verify authentication */
303
384
assertion_n = lasso_session_get_assertion(profile->session, profile->remote_providerID);
304
if (assertion_n == NULL) {
385
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
305
386
message(G_LOG_LEVEL_WARNING, "%s has no assertion", profile->remote_providerID);
306
387
lasso_saml20_profile_set_response_status(profile,
307
388
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
308
return LASSO_ERROR_UNDEFINED;
389
return LASSO_PROFILE_ERROR_MISSING_ASSERTION;
311
392
assertion = LASSO_SAML2_ASSERTION(assertion_n);
313
394
/* If name identifier is federated, then verify federation */
314
395
if (strcmp(name_id->Format, LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT) == 0) {
396
char *name_id_sp_name_qualifier = NULL;
315
397
if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
316
398
/* XXX: which SAML 2 status code ? */
317
399
lasso_saml20_profile_set_response_status(profile,
318
400
LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST);
319
401
return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
404
if (remote_provider->private_data->affiliation_id) {
405
name_id_sp_name_qualifier = remote_provider->private_data->affiliation_id;
407
name_id_sp_name_qualifier = profile->remote_providerID;
321
410
federation = g_hash_table_lookup(profile->identity->federations,
322
profile->remote_providerID);
411
name_id_sp_name_qualifier);
323
412
if (LASSO_IS_FEDERATION(federation) == FALSE) {
324
413
/* XXX: which status code in SAML 2 ? */
325
414
lasso_saml20_profile_set_response_status(profile,
333
422
profile->remote_providerID);
334
423
lasso_saml20_profile_set_response_status(profile,
335
424
LASSO_LIB_STATUS_CODE_FEDERATION_DOES_NOT_EXIST);
336
return LASSO_ERROR_UNDEFINED;
425
return LASSO_LOGOUT_ERROR_FEDERATION_NOT_FOUND;
388
477
return; /* original service provider (initiated logout) */
390
479
assertion_n = lasso_session_get_assertion(profile->session, provider->ProviderID);
391
if (assertion_n == NULL)
480
if (LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) {
392
481
return; /* not authenticated with this provider */
393
484
assertion = LASSO_SAML2_ASSERTION(assertion_n);
395
486
supported_profiles = lasso_provider_get_metadata_list(provider,
418
509
response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
419
510
LASSO_PROVIDER(profile->server)->ProviderID));
420
511
response->IssueInstant = lasso_get_current_time();
421
response->InResponseTo = g_strdup(
422
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
512
if (profile->request) {
513
response->InResponseTo = g_strdup(
514
LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
423
516
lasso_saml20_profile_set_response_status(profile,
424
517
LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
464
557
return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
560
LASSO_SAMLP2_LOGOUT_RESPONSE(profile->response)->relayState = g_strdup(
561
profile->msg_relayState);
467
562
query = lasso_node_export_to_query(LASSO_NODE(profile->response),
468
563
profile->server->signature_method,
469
564
profile->server->private_key);
472
567
return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
474
profile->msg_url = g_strdup_printf("%s?%s", url, query);
569
profile->msg_url = lasso_concat_url_query(url, query);
475
570
profile->msg_body = NULL;
481
576
return LASSO_PROFILE_ERROR_MISSING_REQUEST;
487
lasso_saml20_process_response_msg(LassoLogout *logout, const char *response_msg)
580
lasso_saml20_logout_process_response_msg(LassoLogout *logout, const char *response_msg)
489
582
LassoProfile *profile = LASSO_PROFILE(logout);
490
583
LassoHttpMethod response_method;
539
632
if (response->Status == NULL || response->Status->StatusCode == NULL
540
633
|| response->Status->StatusCode->Value == NULL) {
541
634
message(G_LOG_LEVEL_CRITICAL, "No Status in LogoutResponse !");
542
return LASSO_ERROR_UNDEFINED;
635
return LASSO_PROFILE_ERROR_MISSING_STATUS_CODE;
544
637
status_code_value = response->Status->StatusCode->Value;
548
641
* rebuild the request message with HTTP method */
549
642
/* XXX is this still what to do for SAML 2.0? */
644
if (strcmp(status_code_value, LASSO_SAML2_STATUS_CODE_RESPONDER) == 0) {
645
/* Responder -> look inside */
646
if (response->Status->StatusCode->StatusCode) {
647
status_code_value = response->Status->StatusCode->StatusCode->Value;
649
if (status_code_value == NULL) {
650
return LASSO_PROFILE_ERROR_MISSING_STATUS_CODE;
551
653
if (strcmp(status_code_value, LASSO_SAML2_STATUS_CODE_REQUEST_DENIED) == 0) {
552
654
/* assertion no longer on IdP so removing it locally
555
657
profile->session, profile->remote_providerID);
556
658
return LASSO_LOGOUT_ERROR_REQUEST_DENIED;
660
if (strcmp(status_code_value, LASSO_SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL) == 0) {
661
return LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL;
558
663
message(G_LOG_LEVEL_CRITICAL, "Status code is not success: %s", status_code_value);
559
return LASSO_ERROR_UNDEFINED;
664
return LASSO_PROFILE_ERROR_STATUS_NOT_SUCCESS;
562
667
/* LogoutResponse status code value is ok */
565
670
/* if SOAP method or, if IDP provider type and HTTP Redirect,
566
671
* then remove assertion */
567
if ( response_method == LASSO_HTTP_METHOD_SOAP ||
672
if (response_method == LASSO_HTTP_METHOD_SOAP ||
568
673
(remote_provider->role == LASSO_PROVIDER_ROLE_SP &&
569
674
response_method == LASSO_HTTP_METHOD_REDIRECT) ) {
570
675
lasso_session_remove_assertion(profile->session, profile->remote_providerID);