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

« back to all changes in this revision

Viewing changes to lasso/saml-2.0/name_id_management.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: name_id_management.c,v 1.19 2007/01/08 13:36:00 fpeters Exp $ 
 
2
 *
 
3
 * Lasso - A free implementation of the Liberty Alliance specifications.
 
4
 *
 
5
 * Copyright (C) 2004, 2005 Entr'ouvert
 
6
 * http://lasso.entrouvert.org
 
7
 * 
 
8
 * Authors: See AUTHORS file in top-level directory.
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 * 
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
 
 
25
#include <lasso/saml-2.0/name_id_management.h>
 
26
#include <lasso/saml-2.0/providerprivate.h>
 
27
#include <lasso/saml-2.0/profileprivate.h>
 
28
#include <lasso/id-ff/providerprivate.h>
 
29
#include <lasso/id-ff/identityprivate.h>
 
30
#include <lasso/id-ff/serverprivate.h>
 
31
#include <lasso/xml/xml_enc.h>
 
32
 
 
33
/*****************************************************************************/
 
34
/* public methods                                                            */
 
35
/*****************************************************************************/
 
36
 
 
37
/**
 
38
 * lasso_name_id_management_init_request:
 
39
 * @name_id_management: a #LassoNameIdManagement
 
40
 * @remote_provider_id: the providerID of the remote provider.
 
41
 * @new_name_id: the new NameId or NULL to terminate a federation
 
42
 * @http_method: if set, then it get the protocol profile in metadata
 
43
 *     corresponding of this HTTP request method.
 
44
 *
 
45
 * Initializes a new Name Id Management Request.
 
46
 *
 
47
 * Return value: 0 on success; or a negative value otherwise.
 
48
 **/
 
49
gint
 
50
lasso_name_id_management_init_request(LassoNameIdManagement *name_id_management,
 
51
                char *remote_provider_id,
 
52
                char *new_name_id,
 
53
                LassoHttpMethod http_method)
 
54
{
 
55
        LassoProfile *profile;
 
56
        LassoProvider *remote_provider;
 
57
        LassoFederation *federation;
 
58
        LassoSaml2NameID *name_id, *name_id_n;
 
59
        LassoSamlp2RequestAbstract *request;
 
60
 
 
61
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
62
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
63
        g_return_val_if_fail(remote_provider_id != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
 
64
 
 
65
        profile = LASSO_PROFILE(name_id_management);
 
66
 
 
67
        /* verify if the identity */
 
68
        if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
 
69
                return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
 
70
        }
 
71
 
 
72
        /* set the remote provider id */
 
73
        profile->remote_providerID = g_strdup(remote_provider_id);
 
74
 
 
75
        remote_provider = g_hash_table_lookup(profile->server->providers,
 
76
                        profile->remote_providerID);
 
77
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
 
78
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
79
        }
 
80
 
 
81
        /* Get federation */
 
82
        federation = g_hash_table_lookup(profile->identity->federations,
 
83
                        profile->remote_providerID);
 
84
        if (LASSO_IS_FEDERATION(federation) == FALSE) {
 
85
                return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
 
86
        }
 
87
 
 
88
        /* get the current NameID */
 
89
        name_id_n = LASSO_SAML2_NAME_ID(lasso_profile_get_nameIdentifier(profile));
 
90
 
 
91
        name_id = LASSO_SAML2_NAME_ID(name_id_n);
 
92
 
 
93
        if (federation->local_nameIdentifier) {
 
94
                profile->nameIdentifier = g_object_ref(federation->local_nameIdentifier);
 
95
        } else {
 
96
                profile->nameIdentifier = g_object_ref(name_id_n);
 
97
        }
 
98
 
 
99
        /* XXX: check HTTP method is supported */
 
100
 
 
101
        profile->request = lasso_samlp2_manage_name_id_request_new();
 
102
 
 
103
        request = LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request);
 
104
        request->ID = lasso_build_unique_id(32);
 
105
        request->Version = g_strdup("2.0");
 
106
        request->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
 
107
                        LASSO_PROVIDER(profile->server)->ProviderID));
 
108
        request->IssueInstant = lasso_get_current_time();
 
109
 
 
110
        LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(request)->NameID = g_object_ref( \
 
111
                        profile->nameIdentifier);
 
112
 
 
113
        if (new_name_id) {
 
114
                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(request)->NewID = g_strdup(new_name_id);
 
115
        } else {
 
116
                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(request)->Terminate = \
 
117
                                LASSO_SAMLP2_TERMINATE(lasso_samlp2_terminate_new());
 
118
        }
 
119
        
 
120
        profile->http_request_method = http_method;
 
121
 
 
122
        return 0;
 
123
}
 
124
 
 
125
 
 
126
/**
 
127
 * lasso_name_id_management_build_request_msg:
 
128
 * @name_id_management: a #LassoNameIdManagement
 
129
 *
 
130
 * Builds the Name Id Management request message.
 
131
 * 
 
132
 * Return value: 0 on success; or a negative value otherwise.
 
133
 **/
 
134
gint
 
135
lasso_name_id_management_build_request_msg(LassoNameIdManagement *name_id_management)
 
136
{
 
137
        LassoProfile *profile;
 
138
        LassoProvider *remote_provider;
 
139
 
 
140
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
141
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
142
 
 
143
        profile = LASSO_PROFILE(name_id_management);
 
144
        lasso_profile_clean_msg_info(profile);
 
145
 
 
146
        remote_provider = g_hash_table_lookup(profile->server->providers,
 
147
                        profile->remote_providerID);
 
148
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
 
149
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
150
        }
 
151
 
 
152
        if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
 
153
                profile->msg_url = lasso_provider_get_metadata_one(remote_provider,
 
154
                                "ManageNameIDService SOAP");
 
155
                /* XXX set private key so message is signed */
 
156
                profile->msg_body = lasso_node_export_to_soap(profile->request);
 
157
                return 0;
 
158
        }
 
159
 
 
160
        if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) {
 
161
                char *url, *query;
 
162
                url = lasso_provider_get_metadata_one(remote_provider,
 
163
                                "ManageNameIDService HTTP-Redirect");
 
164
                if (url == NULL) {
 
165
                        return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
 
166
                }
 
167
                query = lasso_node_export_to_query(LASSO_NODE(profile->request),
 
168
                                profile->server->signature_method,
 
169
                                profile->server->private_key);
 
170
                if (query == NULL) {
 
171
                        g_free(url);
 
172
                        return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
 
173
                }
 
174
                profile->msg_url = lasso_concat_url_query(url, query);
 
175
                profile->msg_body = NULL;
 
176
                g_free(url);
 
177
                g_free(query);
 
178
                return 0;
 
179
        }
 
180
 
 
181
        /* XXX: Artifact profile support */
 
182
 
 
183
        return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD);
 
184
}
 
185
 
 
186
 
 
187
/**
 
188
 * lasso_name_id_management_process_request_msg:
 
189
 * @name_id_management: a #LassoNameIdManagement
 
190
 * @request_msg: the Name Id Management request message
 
191
 * 
 
192
 * Processes a Name Id Management request message.  Rebuilds a request object
 
193
 * from the message and check its signature.
 
194
 *
 
195
 * Return value: 0 on success; or a negative value otherwise.
 
196
 **/
 
197
gint
 
198
lasso_name_id_management_process_request_msg(LassoNameIdManagement *name_id_management,
 
199
                char *request_msg)
 
200
{
 
201
        LassoProfile *profile;
 
202
        LassoProvider *remote_provider;
 
203
        LassoMessageFormat format;
 
204
        LassoSaml2NameID *name_id;
 
205
        LassoSaml2EncryptedElement *encrypted_id;
 
206
        LassoSaml2EncryptedElement* encrypted_element = NULL;
 
207
        xmlSecKey *encryption_private_key = NULL;
 
208
 
 
209
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
210
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
211
        
 
212
        profile = LASSO_PROFILE(name_id_management);
 
213
        profile->request = lasso_samlp2_manage_name_id_request_new();
 
214
        format = lasso_node_init_from_message(LASSO_NODE(profile->request), request_msg);
 
215
        if (format == LASSO_MESSAGE_FORMAT_UNKNOWN || format == LASSO_MESSAGE_FORMAT_ERROR) {
 
216
                return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
 
217
        }
 
218
 
 
219
        if (profile->remote_providerID) {
 
220
                g_free(profile->remote_providerID);
 
221
        }
 
222
 
 
223
        profile->remote_providerID = g_strdup(
 
224
                        LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
 
225
        remote_provider = g_hash_table_lookup(profile->server->providers,
 
226
                        profile->remote_providerID);
 
227
 
 
228
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
 
229
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
230
        }
 
231
 
 
232
        /* verify signatures */
 
233
        profile->signature_status = lasso_provider_verify_signature(
 
234
                        remote_provider, request_msg, "ID", format);
 
235
        profile->signature_status = 0; /* XXX: signature check disabled for zxid */
 
236
 
 
237
        if (format == LASSO_MESSAGE_FORMAT_SOAP)
 
238
                profile->http_request_method = LASSO_HTTP_METHOD_SOAP;
 
239
        if (format == LASSO_MESSAGE_FORMAT_QUERY)
 
240
                profile->http_request_method = LASSO_HTTP_METHOD_REDIRECT;
 
241
 
 
242
        name_id = LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NameID;
 
243
        encrypted_id = LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->EncryptedID;
 
244
 
 
245
        if (name_id == NULL && encrypted_id != NULL) {
 
246
                encryption_private_key = profile->server->private_data->encryption_private_key;
 
247
                encrypted_element = LASSO_SAML2_ENCRYPTED_ELEMENT(encrypted_id);
 
248
                if (encrypted_element != NULL && encryption_private_key == NULL) {
 
249
                        return LASSO_PROFILE_ERROR_MISSING_ENCRYPTION_PRIVATE_KEY;
 
250
                }
 
251
                if (encrypted_element != NULL && encryption_private_key != NULL) {
 
252
                        profile->nameIdentifier = LASSO_NODE(lasso_node_decrypt(
 
253
                                encrypted_id, encryption_private_key));
 
254
                        LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NameID = \
 
255
                                LASSO_SAML2_NAME_ID(profile->nameIdentifier);
 
256
                        LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->EncryptedID = NULL;
 
257
 
 
258
                }
 
259
        } else {
 
260
                profile->nameIdentifier = g_object_ref(name_id);
 
261
        }
 
262
 
 
263
        return profile->signature_status;
 
264
}
 
265
 
 
266
 
 
267
/**
 
268
 * lasso_name_id_management_validate_request:
 
269
 * @name_id_management: a #LassoNameIdManagement
 
270
 * 
 
271
 * Processes a Name Id Management request, performing requested actions against
 
272
 * principal federations.  Profile identity may have to be saved afterwards.
 
273
 *
 
274
 * Return value: 0 on success; or a negative value otherwise.
 
275
 **/
 
276
int
 
277
lasso_name_id_management_validate_request(LassoNameIdManagement *name_id_management)
 
278
{
 
279
        LassoProfile *profile;
 
280
        LassoProvider *remote_provider;
 
281
        LassoFederation *federation;
 
282
        LassoSamlp2StatusResponse *response;
 
283
        LassoSaml2NameID *name_id;
 
284
 
 
285
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
286
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
287
        profile = LASSO_PROFILE(name_id_management);
 
288
 
 
289
        if (LASSO_IS_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request) == FALSE)
 
290
                return LASSO_PROFILE_ERROR_MISSING_REQUEST;
 
291
 
 
292
        if (profile->identity == NULL) {
 
293
                return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
 
294
        }
 
295
        
 
296
        if (profile->remote_providerID) {
 
297
                g_free(profile->remote_providerID);
 
298
        }
 
299
 
 
300
        profile->remote_providerID = g_strdup(
 
301
                        LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->Issuer->content);
 
302
 
 
303
        /* get the provider */
 
304
        remote_provider = g_hash_table_lookup(profile->server->providers,
 
305
                        profile->remote_providerID);
 
306
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
 
307
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
308
        }
 
309
 
 
310
        federation = g_hash_table_lookup(profile->identity->federations,
 
311
                        profile->remote_providerID);
 
312
        if (LASSO_IS_FEDERATION(federation) == FALSE) {
 
313
                return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
 
314
        }
 
315
 
 
316
        if (profile->response) {
 
317
                lasso_node_destroy(profile->response);
 
318
        }
 
319
 
 
320
        profile->response = lasso_samlp2_manage_name_id_response_new();
 
321
        response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response);
 
322
        response->ID = lasso_build_unique_id(32);
 
323
        response->Version = g_strdup("2.0");
 
324
        response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
 
325
                        LASSO_PROVIDER(profile->server)->ProviderID));
 
326
        response->IssueInstant = lasso_get_current_time();
 
327
        response->InResponseTo = g_strdup(LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
 
328
        lasso_saml20_profile_set_response_status(profile, LASSO_SAML2_STATUS_CODE_SUCCESS);
 
329
 
 
330
        response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
 
331
        if (profile->server->certificate) {
 
332
                response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
 
333
        } else {
 
334
                response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE;
 
335
        }
 
336
        response->private_key_file = g_strdup(profile->server->private_key);
 
337
        response->certificate_file = g_strdup(profile->server->certificate);
 
338
 
 
339
        /* verify signature status */
 
340
        if (profile->signature_status != 0) {
 
341
                /* XXX: which SAML2 Status Code ? */
 
342
                lasso_saml20_profile_set_response_status(profile, 
 
343
                                LASSO_LIB_STATUS_CODE_INVALID_SIGNATURE);
 
344
                return profile->signature_status;
 
345
        }
 
346
 
 
347
        /* Get the name identifier */
 
348
        name_id = LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NameID;
 
349
        if (name_id == NULL) {
 
350
                message(G_LOG_LEVEL_CRITICAL,
 
351
                                "Name identifier not found in name id management request");
 
352
                /* XXX: which status code in SAML 2.0 ? */
 
353
                lasso_saml20_profile_set_response_status(
 
354
                                profile, LASSO_SAML2_STATUS_CODE_UNKNOWN_PRINCIPAL);
 
355
                return LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND;
 
356
        }
 
357
 
 
358
        if (LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->Terminate) {
 
359
                /* defederation */
 
360
                lasso_identity_remove_federation(profile->identity, profile->remote_providerID);
 
361
        } else {
 
362
                /* name registration */
 
363
                LassoSaml2NameID *new_name_id;
 
364
                new_name_id = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new());
 
365
                new_name_id->Format = g_strdup(name_id->Format);
 
366
                new_name_id->NameQualifier = g_strdup(name_id->NameQualifier);
 
367
                new_name_id->SPNameQualifier = g_strdup(name_id->SPNameQualifier);
 
368
                if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) {
 
369
                        /* if the requester is the service provider, the new
 
370
                         * identifier MUST appear in subsequent <NameID>
 
371
                         * elements in the SPProvidedID attribute
 
372
                         *  -- saml-core-2.0-os.pdf, page 58
 
373
                         */
 
374
                        new_name_id->SPProvidedID = g_strdup(
 
375
                                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NewID);
 
376
                        new_name_id->content = g_strdup(name_id->content);
 
377
                } else {
 
378
                        /* If the requester is the identity provider, the new
 
379
                         * value will appear in subsequent <NameID> elements as
 
380
                         * the element's content.
 
381
                         * -- saml-core-2.0-os.pdf, page 58
 
382
                         */
 
383
                        new_name_id->content = g_strdup(
 
384
                                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NewID);
 
385
                }
 
386
 
 
387
                if (federation->local_nameIdentifier)
 
388
                        lasso_node_destroy(LASSO_NODE(federation->local_nameIdentifier));
 
389
                federation->local_nameIdentifier = g_object_ref(new_name_id);
 
390
                profile->identity->is_dirty = TRUE;
 
391
        }
 
392
 
 
393
        return 0;
 
394
}
 
395
 
 
396
/**
 
397
 * lasso_name_id_management_build_response_msg:
 
398
 * @name_id_management: a #LassoNameIdManagement
 
399
 * 
 
400
 * Builds the Name Id Management response message.
 
401
 * 
 
402
 * Return value: 0 on success; or a negative value otherwise.
 
403
 **/
 
404
int
 
405
lasso_name_id_management_build_response_msg(LassoNameIdManagement *name_id_management)
 
406
{
 
407
        LassoProfile *profile;
 
408
        LassoSamlp2StatusResponse *response;
 
409
        LassoProvider *provider;
 
410
        char *url, *query;
 
411
 
 
412
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
413
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
414
        profile = LASSO_PROFILE(name_id_management);
 
415
        lasso_profile_clean_msg_info(profile);
 
416
 
 
417
        if (profile->response == NULL) {
 
418
                /* no response set here means request denied */
 
419
                profile->response = lasso_samlp2_manage_name_id_response_new();
 
420
                response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response);
 
421
                response->ID = lasso_build_unique_id(32);
 
422
                response->Version = g_strdup("2.0");
 
423
                response->Issuer = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new_with_string(
 
424
                                LASSO_PROVIDER(profile->server)->ProviderID));
 
425
                response->IssueInstant = lasso_get_current_time();
 
426
                response->InResponseTo = g_strdup(
 
427
                                LASSO_SAMLP2_REQUEST_ABSTRACT(profile->request)->ID);
 
428
                lasso_saml20_profile_set_response_status(profile, 
 
429
                                LASSO_SAML2_STATUS_CODE_REQUEST_DENIED);
 
430
 
 
431
                response->sign_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
 
432
                if (profile->server->certificate) {
 
433
                        response->sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
 
434
                } else {
 
435
                        response->sign_type = LASSO_SIGNATURE_TYPE_SIMPLE;
 
436
                }
 
437
                response->private_key_file = g_strdup(profile->server->private_key);
 
438
                response->certificate_file = g_strdup(profile->server->certificate);
 
439
                return 0;
 
440
        }
 
441
 
 
442
        if (profile->remote_providerID == NULL || profile->response == NULL) {
 
443
                /* no remote provider id set or no response set, this means
 
444
                 * this function got called before validate_request, probably
 
445
                 * because there were no identity or federation */
 
446
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
447
        }
 
448
 
 
449
        /* build logout response message */
 
450
        if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
 
451
                profile->msg_url = NULL;
 
452
                profile->msg_body = lasso_node_export_to_soap(profile->response);
 
453
                return 0;
 
454
        }
 
455
 
 
456
        if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) {
 
457
                /* get the provider */
 
458
                provider = g_hash_table_lookup(profile->server->providers,
 
459
                                profile->remote_providerID);
 
460
                if (provider == NULL) {
 
461
                        return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
462
                }
 
463
 
 
464
                url = lasso_provider_get_metadata_one(provider,
 
465
                                "ManageNameIDService HTTP-Redirect ResponseLocation");
 
466
                if (url == NULL) {
 
467
                        url = lasso_provider_get_metadata_one(provider,
 
468
                                        "ManageNameIDService HTTP-Redirect");
 
469
                        if (url == NULL) {
 
470
                                return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
 
471
                        }
 
472
                }
 
473
                query = lasso_node_export_to_query(LASSO_NODE(profile->response),
 
474
                                profile->server->signature_method,
 
475
                                profile->server->private_key);
 
476
                if (query == NULL) {
 
477
                        g_free(url);
 
478
                        return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
 
479
                }
 
480
                profile->msg_url = lasso_concat_url_query(url, query);
 
481
                profile->msg_body = NULL;
 
482
                g_free(url);
 
483
                g_free(query);
 
484
                return 0;
 
485
        }
 
486
 
 
487
        return LASSO_PROFILE_ERROR_MISSING_REQUEST;
 
488
}
 
489
 
 
490
 
 
491
/**
 
492
 * lasso_name_id_management_process_response_msg:
 
493
 * @name_id_management: a #LassoNameIdManagement
 
494
 * @response_msg: the response message
 
495
 * 
 
496
 * Parses the response message and builds the corresponding response object.
 
497
 * Performs requested actions against principal federations.  Profile identity
 
498
 * may have to be saved afterwards.
 
499
 *
 
500
 * Return value: 0 on success; or a negative value otherwise.
 
501
 **/
 
502
gint
 
503
lasso_name_id_management_process_response_msg(
 
504
                LassoNameIdManagement *name_id_management,
 
505
                gchar *response_msg)
 
506
{
 
507
        LassoProfile *profile;
 
508
        LassoHttpMethod response_method;
 
509
        LassoProvider *remote_provider;
 
510
        LassoSamlp2StatusResponse *response;
 
511
        LassoMessageFormat format;
 
512
        char *status_code_value;
 
513
        int rc;
 
514
 
 
515
        g_return_val_if_fail(LASSO_IS_NAME_ID_MANAGEMENT(name_id_management),
 
516
                        LASSO_PARAM_ERROR_INVALID_VALUE);
 
517
        g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
 
518
 
 
519
        profile = LASSO_PROFILE(name_id_management);
 
520
 
 
521
        if (LASSO_IS_SAMLP2_MANAGE_NAME_ID_RESPONSE(profile->response) == TRUE) {
 
522
                lasso_node_destroy(profile->response);
 
523
                profile->response = NULL;
 
524
        }
 
525
 
 
526
        profile->response = lasso_samlp2_manage_name_id_response_new();
 
527
        format = lasso_node_init_from_message(LASSO_NODE(profile->response), response_msg);
 
528
 
 
529
        switch (format) {
 
530
                case LASSO_MESSAGE_FORMAT_SOAP:
 
531
                        response_method = LASSO_HTTP_METHOD_SOAP;
 
532
                        break;
 
533
                case LASSO_MESSAGE_FORMAT_QUERY:
 
534
                        response_method = LASSO_HTTP_METHOD_REDIRECT;
 
535
                        break;
 
536
                default:
 
537
                        return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
 
538
        }
 
539
 
 
540
        profile->remote_providerID = g_strdup(
 
541
                        LASSO_SAMLP2_STATUS_RESPONSE(profile->response)->Issuer->content);
 
542
 
 
543
        /* get the provider */
 
544
        remote_provider = g_hash_table_lookup(profile->server->providers,
 
545
                        profile->remote_providerID);
 
546
        if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
 
547
                return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
 
548
        }
 
549
 
 
550
        /* verify signature */
 
551
        rc = lasso_provider_verify_signature(remote_provider, response_msg, "ID", format);
 
552
        if (rc == LASSO_DS_ERROR_SIGNATURE_NOT_FOUND) {
 
553
                /* XXX: is signature mandatory ? */
 
554
                message(G_LOG_LEVEL_WARNING, "No signature on response");
 
555
                rc = 0;
 
556
        }
 
557
 
 
558
        response = LASSO_SAMLP2_STATUS_RESPONSE(profile->response);
 
559
 
 
560
        if (response->Status == NULL || response->Status->StatusCode == NULL
 
561
                        || response->Status->StatusCode->Value == NULL) {
 
562
                message(G_LOG_LEVEL_CRITICAL, "No Status in ManageNameIDResponse !");
 
563
                return LASSO_PROFILE_ERROR_MISSING_STATUS_CODE;
 
564
        }
 
565
        status_code_value = response->Status->StatusCode->Value;
 
566
 
 
567
        if (strcmp(status_code_value, LASSO_SAML2_STATUS_CODE_SUCCESS) != 0) {
 
568
                message(G_LOG_LEVEL_CRITICAL, "Status code is not success: %s", status_code_value);
 
569
                return LASSO_PROFILE_ERROR_STATUS_NOT_SUCCESS;
 
570
        }
 
571
 
 
572
        if (LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->Terminate) {
 
573
                lasso_identity_remove_federation(profile->identity, profile->remote_providerID);
 
574
        } else {
 
575
                LassoSaml2NameID *new_name_id, *name_id;
 
576
                LassoFederation *federation;
 
577
 
 
578
                name_id = LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NameID;
 
579
 
 
580
                new_name_id = LASSO_SAML2_NAME_ID(lasso_saml2_name_id_new());
 
581
                new_name_id->Format = g_strdup(name_id->Format);
 
582
                new_name_id->NameQualifier = g_strdup(name_id->NameQualifier);
 
583
                new_name_id->SPNameQualifier = g_strdup(name_id->SPNameQualifier);
 
584
                if (LASSO_PROVIDER(profile->server)->role == LASSO_PROVIDER_ROLE_SP) {
 
585
                        /* if the requester is the service provider, the new
 
586
                         * identifier MUST appear in subsequent <NameID>
 
587
                         * elements in the SPProvidedID attribute
 
588
                         *  -- saml-core-2.0-os.pdf, page 58
 
589
                         */
 
590
                        new_name_id->SPProvidedID = g_strdup(
 
591
                                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NewID);
 
592
                        new_name_id->content = g_strdup(name_id->content);
 
593
                } else {
 
594
                        /* If the requester is the identity provider, the new
 
595
                         * value will appear in subsequent <NameID> elements as
 
596
                         * the element's content.
 
597
                         * -- saml-core-2.0-os.pdf, page 58
 
598
                         */
 
599
                        new_name_id->content = g_strdup(
 
600
                                LASSO_SAMLP2_MANAGE_NAME_ID_REQUEST(profile->request)->NewID);
 
601
                }
 
602
 
 
603
                /* Get federation */
 
604
                federation = g_hash_table_lookup(profile->identity->federations,
 
605
                                profile->remote_providerID);
 
606
                if (LASSO_IS_FEDERATION(federation) == FALSE) {
 
607
                        return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
 
608
                }
 
609
 
 
610
                if (federation->local_nameIdentifier)
 
611
                        lasso_node_destroy(LASSO_NODE(federation->local_nameIdentifier));
 
612
                federation->local_nameIdentifier = g_object_ref(new_name_id);
 
613
                profile->identity->is_dirty = TRUE;
 
614
 
 
615
        }
 
616
 
 
617
        return 0;
 
618
}
 
619
 
 
620
 
 
621
/*****************************************************************************/
 
622
/* private methods                                                           */
 
623
/*****************************************************************************/
 
624
 
 
625
static struct XmlSnippet schema_snippets[] = {
 
626
        { NULL, 0, 0}
 
627
};
 
628
 
 
629
static LassoNodeClass *parent_class = NULL;
 
630
 
 
631
static xmlNode*
 
632
get_xmlNode(LassoNode *node, gboolean lasso_dump)
 
633
{
 
634
        xmlNode *xmlnode;
 
635
 
 
636
        xmlnode = parent_class->get_xmlNode(node, lasso_dump);
 
637
        xmlNodeSetName(xmlnode, (xmlChar*)"NameIdManagement");
 
638
        xmlSetProp(xmlnode, (xmlChar*)"NameIdManagementDumpVersion", (xmlChar*)"1");
 
639
 
 
640
        return xmlnode;
 
641
}
 
642
 
 
643
static int
 
644
init_from_xml(LassoNode *node, xmlNode *xmlnode)
 
645
{
 
646
        return parent_class->init_from_xml(node, xmlnode);
 
647
}
 
648
 
 
649
/*****************************************************************************/
 
650
/* overridden parent class methods                                           */
 
651
/*****************************************************************************/
 
652
 
 
653
static void
 
654
dispose(GObject *object)
 
655
{
 
656
        G_OBJECT_CLASS(parent_class)->dispose(object);
 
657
}
 
658
 
 
659
static void
 
660
finalize(GObject *object)
 
661
{  
 
662
        G_OBJECT_CLASS(parent_class)->finalize(object);
 
663
}
 
664
 
 
665
 
 
666
 
 
667
/*****************************************************************************/
 
668
/* instance and class init functions                                         */
 
669
/*****************************************************************************/
 
670
 
 
671
static void
 
672
instance_init(LassoNameIdManagement *name_id_management)
 
673
{
 
674
}
 
675
 
 
676
static void
 
677
class_init(LassoNameIdManagementClass *klass)
 
678
{
 
679
        LassoNodeClass *nclass = LASSO_NODE_CLASS(klass);
 
680
 
 
681
        parent_class = g_type_class_peek_parent(klass);
 
682
        nclass->get_xmlNode = get_xmlNode;
 
683
        nclass->init_from_xml = init_from_xml;
 
684
        nclass->node_data = g_new0(LassoNodeClassData, 1);
 
685
        lasso_node_class_set_nodename(nclass, "NameIdManagement");
 
686
        lasso_node_class_add_snippets(nclass, schema_snippets);
 
687
 
 
688
        G_OBJECT_CLASS(klass)->dispose = dispose;
 
689
        G_OBJECT_CLASS(klass)->finalize = finalize;
 
690
}
 
691
 
 
692
 
 
693
 
 
694
GType
 
695
lasso_name_id_management_get_type()
 
696
{
 
697
        static GType this_type = 0;
 
698
 
 
699
        if (!this_type) {
 
700
                static const GTypeInfo this_info = {
 
701
                        sizeof (LassoNameIdManagementClass),
 
702
                        NULL, NULL, 
 
703
                        (GClassInitFunc) class_init,
 
704
                        NULL, NULL,
 
705
                        sizeof(LassoNameIdManagement),
 
706
                        0,
 
707
                        (GInstanceInitFunc) instance_init,
 
708
                };
 
709
 
 
710
                this_type = g_type_register_static(LASSO_TYPE_PROFILE,
 
711
                                "LassoNameIdManagement", &this_info, 0);
 
712
        }
 
713
        return this_type;
 
714
}
 
715
 
 
716
/**
 
717
 * lasso_name_id_management_new:
 
718
 * @server: the #LassoServer
 
719
 * 
 
720
 * Creates a new #LassoNameIdManagement.
 
721
 *
 
722
 * Return value: a newly created #LassoNameIdManagement object; or NULL if an error
 
723
 *     occured
 
724
 **/
 
725
LassoNameIdManagement*
 
726
lasso_name_id_management_new(LassoServer *server)
 
727
{
 
728
        LassoNameIdManagement *name_id_management;
 
729
 
 
730
        g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
 
731
 
 
732
        name_id_management = g_object_new(LASSO_TYPE_NAME_ID_MANAGEMENT, NULL);
 
733
        LASSO_PROFILE(name_id_management)->server = g_object_ref(server);
 
734
 
 
735
        return name_id_management;
 
736
}
 
737
 
 
738
/**
 
739
 * lasso_name_id_management_destroy:
 
740
 * @name_id_management: a #LassoNameIdManagement
 
741
 * 
 
742
 * Destroys a #LassoNameIdManagement object.
 
743
 **/
 
744
void
 
745
lasso_name_id_management_destroy(LassoNameIdManagement *name_id_management)
 
746
{
 
747
        lasso_node_destroy(LASSO_NODE(name_id_management));
 
748
}
 
749
 
 
750
/**
 
751
 * lasso_name_id_management_new_from_dump:
 
752
 * @server: the #LassoServer
 
753
 * @dump: XML name_id_management dump
 
754
 *
 
755
 * Restores the @dump to a new #LassoLogout.
 
756
 *
 
757
 * Return value: a newly created #LassoLogout; or NULL if an error occured
 
758
 **/
 
759
LassoNameIdManagement*
 
760
lasso_name_id_management_new_from_dump(LassoServer *server, const char *dump)
 
761
{
 
762
        LassoNameIdManagement *name_id_management;
 
763
        xmlDoc *doc;
 
764
 
 
765
        if (dump == NULL)
 
766
                return NULL;
 
767
 
 
768
        name_id_management = lasso_name_id_management_new(g_object_ref(server));
 
769
        doc = xmlParseMemory(dump, strlen(dump));
 
770
        init_from_xml(LASSO_NODE(name_id_management), xmlDocGetRootElement(doc)); 
 
771
        xmlFreeDoc(doc);
 
772
 
 
773
        return name_id_management;
 
774
}
 
775
 
 
776
/**
 
777
 * lasso_name_id_management_dump:
 
778
 * @name_id_management: a #LassoLogout
 
779
 *
 
780
 * Dumps @name_id_management content to an XML string.
 
781
 *
 
782
 * Return value: the dump string.  It must be freed by the caller.
 
783
 **/
 
784
gchar*
 
785
lasso_name_id_management_dump(LassoNameIdManagement *name_id_management)
 
786
{
 
787
        return lasso_node_dump(LASSO_NODE(name_id_management));
 
788
}