~ubuntu-branches/ubuntu/hardy/lasso/hardy

« back to all changes in this revision

Viewing changes to lasso/saml-2.0/logout.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Bienia
  • Date: 2007-07-31 21:35:26 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070731213526-oc6jw5mprcd5tjyy
Tags: 2.0.0-1ubuntu1
* Merge from debian unstable. Remaining changes:
  + debian/control:
    - Modify Maintainer value to match DebianMaintainerField spec.
* debian/rules:
  + Add CC=gcc-4.2 to the configure call else configure won't find jni.h
    from libgcj8-dev.
* configure{,.ac}:
  + Add missing quotes around the value for PHP[45]_LIBS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: logout.c,v 1.2 2005/11/22 21:24:12 fpeters Exp $
 
1
/* $Id: logout.c,v 1.24 2007/01/03 23:35:17 fpeters Exp $
2
2
 *
3
3
 * Lasso - A free implementation of the Liberty Alliance specifications.
4
4
 *
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>
 
37
 
 
38
#include <lasso/xml/xml_enc.h>
36
39
 
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;
54
58
 
55
59
        /* session existence has been checked in id-ff/ */
56
60
        session = lasso_profile_get_session(profile);
57
61
 
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);
62
65
        }
63
66
 
64
67
        assertion = LASSO_SAML2_ASSERTION(assertion_n);
65
68
 
66
69
        if (assertion->Subject == NULL) {
67
 
                return LASSO_ERROR_UNDEFINED;
 
70
                return LASSO_PROFILE_ERROR_MISSING_SUBJECT;
 
71
        }
 
72
 
 
73
        if (assertion->Subject->NameID == NULL) {
 
74
                return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
68
75
        }
69
76
 
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;
 
81
 
73
82
                if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
74
83
                        return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
75
84
                }
 
85
 
 
86
                if (remote_provider->private_data->affiliation_id) {
 
87
                        name_id_sp_name_qualifier = remote_provider->private_data->affiliation_id;
 
88
                } else {
 
89
                        name_id_sp_name_qualifier = profile->remote_providerID;
 
90
                }
 
91
                
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);
80
96
                }
145
161
 
146
162
        LASSO_SAMLP2_LOGOUT_REQUEST(request)->NameID = g_object_ref(profile->nameIdentifier);
147
163
 
148
 
        /* XXX: SessionIndex */
 
164
        /* Encrypt NameID */
 
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;
 
175
                }
 
176
        }
149
177
 
150
178
        logout->initial_http_request_method = http_method;
151
179
 
158
186
{
159
187
        LassoProfile *profile = LASSO_PROFILE(logout);
160
188
 
 
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;
 
194
        } else {
 
195
                LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->sign_type =
 
196
                        LASSO_SIGNATURE_TYPE_SIMPLE;
 
197
        }
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(
 
207
                                profile->msg_url);
169
208
                profile->msg_body = lasso_node_export_to_soap(profile->request);
170
209
                return 0;
171
210
        }
177
216
                if (url == NULL) {
178
217
                        return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
179
218
                }
 
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);
184
224
                        g_free(url);
185
225
                        return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
186
226
                }
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;
 
229
                g_free(url);
 
230
                g_free(query);
188
231
                return 0;
189
232
        }
190
233
        
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;
202
249
 
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);
207
254
        }
208
255
 
209
 
 
 
256
        if (profile->remote_providerID) {
 
257
                g_free(profile->remote_providerID);
 
258
        }
 
259
 
 
260
        if (LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->relayState) {
 
261
                profile->msg_relayState = g_strdup(
 
262
                                LASSO_SAMLP2_LOGOUT_REQUEST(profile->request)->relayState);
 
263
        }
 
264
 
 
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);
 
269
 
212
270
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
213
271
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
214
272
        }
222
280
        if (format == LASSO_MESSAGE_FORMAT_QUERY)
223
281
                profile->http_request_method = LASSO_HTTP_METHOD_REDIRECT;
224
282
 
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;
 
285
 
 
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;
 
291
                }
 
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;
 
298
 
 
299
                }
 
300
        } else {
 
301
                profile->nameIdentifier = g_object_ref(name_id);
 
302
        }
 
303
 
227
304
 
228
305
        return profile->signature_status;
229
306
}
242
319
        if (LASSO_IS_SAMLP2_LOGOUT_REQUEST(profile->request) == FALSE)
243
320
                return LASSO_PROFILE_ERROR_MISSING_REQUEST;
244
321
 
 
322
        if (profile->remote_providerID) {
 
323
                g_free(profile->remote_providerID);
 
324
        }
 
325
 
245
326
        profile->remote_providerID = g_strdup(
246
327
                        LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
247
328
 
284
365
        }
285
366
 
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 ? */
301
382
 
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;
309
390
        }
310
391
 
311
392
        assertion = LASSO_SAML2_ASSERTION(assertion_n);
312
393
 
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);
320
402
                }
 
403
 
 
404
                if (remote_provider->private_data->affiliation_id) {
 
405
                        name_id_sp_name_qualifier = remote_provider->private_data->affiliation_id;
 
406
                } else {
 
407
                        name_id_sp_name_qualifier = profile->remote_providerID;
 
408
                }
 
409
 
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;
337
426
                }
338
427
        }
339
428
 
388
477
                return; /* original service provider (initiated logout) */
389
478
 
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 */
 
482
        }
 
483
 
393
484
        assertion = LASSO_SAML2_ASSERTION(assertion_n);
394
485
 
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);
 
515
                }
423
516
                lasso_saml20_profile_set_response_status(profile, 
424
517
                                LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
425
518
 
464
557
                                return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
465
558
                        }
466
559
                }
 
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);
471
566
                        g_free(url);
472
567
                        return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
473
568
                }
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;
476
571
                g_free(url);
477
572
                g_free(query);
479
574
        }
480
575
 
481
576
        return LASSO_PROFILE_ERROR_MISSING_REQUEST;
482
 
 
483
 
 
484
577
}
485
578
 
486
579
int
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)
488
581
{
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;
543
636
        }
544
637
        status_code_value = response->Status->StatusCode->Value;
545
638
 
548
641
                 * rebuild the request message with HTTP method */
549
642
                /* XXX is this still what to do for SAML 2.0? */
550
643
 
 
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;
 
648
                        }
 
649
                        if (status_code_value == NULL) {
 
650
                                return LASSO_PROFILE_ERROR_MISSING_STATUS_CODE;
 
651
                        }
 
652
                }
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
553
655
                         * too */
555
657
                                        profile->session, profile->remote_providerID);
556
658
                        return LASSO_LOGOUT_ERROR_REQUEST_DENIED;
557
659
                }
 
660
                if (strcmp(status_code_value, LASSO_SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL) == 0) {
 
661
                        return LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL;
 
662
                }
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;
560
665
        }
561
666
        
562
667
        /* LogoutResponse status code value is ok */
564
669
 
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);
599
704
                }
600
705
        }
601
706
 
 
707
        /* if at SP */
 
708
        if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP &&
 
709
                        response_method == LASSO_HTTP_METHOD_REDIRECT) {
 
710
                lasso_session_remove_assertion(profile->session, profile->remote_providerID);
 
711
        }
 
712
 
602
713
        return rc;
603
714
 
604
715
}