1 /* $Id$
2 *
3 * Lasso - A free implementation of the Liberty Alliance specifications.
4 *
5 * Copyright (C) 2004-2007 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 /**
25 * SECTION:name_registration
26 * @short_description: Name Registration Profile (ID-FF)
27 *
28 **/
29
30 #include "../xml/private.h"
31 #include "name_registration.h"
32 #include "profileprivate.h"
33 #include "providerprivate.h"
34 #include "../utils.h"
35
36 /*****************************************************************************/
37 /* public methods */
38 /*****************************************************************************/
39
40 /**
41 * lasso_name_registration_build_request_msg:
42 * @name_registration: a #LassoNameRegistration
43 *
44 * Builds a register name identifier request message.
45 *
46 * It gets the register name identifier protocol profile and:
47 * <itemizedlist>
48 * <listitem><para>
49 * if it is a SOAP method, then it builds the register name identifier
50 * request SOAP message, optionally signs his node, sets @msg_body,
51 * gets the SoapEndpoint url and sets @msg_url.
52 * </para></listitem>
53 * <listitem><para>
54 * if it is a HTTP-Redirect method, then it builds the register name
55 * identifier request QUERY message (optionally signs the request message),
56 * builds the request url with register name identifier url with register
57 * name identifier service url, sets @msg_url in the register name
58 * identifier object, sets @msg_body to NULL.
59 * </para></listitem>
60 * </itemizedlist>
61 *
62 * Return value: 0 on success; or a negative value otherwise.
63 **/
64 gint
lasso_name_registration_build_request_msg(LassoNameRegistration * name_registration)65 lasso_name_registration_build_request_msg(LassoNameRegistration *name_registration)
66 {
67 LassoProfile *profile;
68 LassoProvider *remote_provider;
69 char *url, *query;
70
71 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
72 LASSO_PARAM_ERROR_INVALID_VALUE);
73
74 profile = LASSO_PROFILE(name_registration);
75 lasso_profile_clean_msg_info(profile);
76
77 if (profile->remote_providerID == NULL) {
78 /* this means lasso_logout_init_request was not called before */
79 return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID);
80 }
81
82 remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
83 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
84 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
85 }
86
87 if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
88 profile->msg_url = lasso_provider_get_metadata_one(
89 remote_provider, "SoapEndpoint");
90 LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->private_key_file =
91 profile->server->private_key;
92 LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->certificate_file =
93 profile->server->certificate;
94 profile->msg_body = lasso_node_export_to_soap(profile->request);
95 return 0;
96 }
97
98 if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) {
99 /* build and optionally sign the query message and build the
100 * register name identifier request url */
101 url = lasso_provider_get_metadata_one(remote_provider,
102 "RegisterNameIdentifierServiceURL");
103 if (url == NULL) {
104 return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
105 }
106 query = lasso_node_export_to_query_with_password(LASSO_NODE(profile->request),
107 profile->server->signature_method,
108 profile->server->private_key,
109 profile->server->private_key_password);
110 if (query == NULL) {
111 lasso_release(url);
112 return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
113 }
114 /* build the msg_url */
115 profile->msg_url = lasso_concat_url_query(url, query);
116 profile->msg_body = NULL;
117 lasso_release(url);
118 lasso_release(query);
119 return 0;
120 }
121
122 return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD);
123 }
124
125
126 /**
127 * lasso_name_registration_build_response_msg:
128 * @name_registration: a #LassoNameRegistration
129 *
130 * Builds the register name idendifier response message.
131 *
132 * It gets the request message method and:
133 * <itemizedlist>
134 * <listitem><para>
135 * if it is a SOAP method, then it builds the response SOAP message, sets
136 * the msg_body attribute, gets the register name identifier service return
137 * url and sets @msg_url of the object.
138 * </para></listitem>
139 * <listitem><para>
140 * if it is a HTTP-Redirect method, then it builds the response QUERY
141 * message, builds the response url, sets @msg_url with the response url
142 * and sets the msg_body with NULL
143 * </para></listitem>
144 * </itemizedlist>
145 *
146 * If private key and certificate are set in server object it will also signs
147 * the message (either with X509 if SOAP or with a simple signature for query
148 * strings).
149 *
150 * Return value: 0 on success; or a negative value otherwise.
151 **/
152 gint
lasso_name_registration_build_response_msg(LassoNameRegistration * name_registration)153 lasso_name_registration_build_response_msg(LassoNameRegistration *name_registration)
154 {
155 LassoProfile *profile;
156 LassoProvider *remote_provider;
157 char *url, *query;
158
159 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
160 LASSO_PARAM_ERROR_INVALID_VALUE);
161
162 profile = LASSO_PROFILE(name_registration);
163 lasso_profile_clean_msg_info(profile);
164
165 if (profile->remote_providerID == NULL) {
166 /* this means lasso_logout_init_request was not called before */
167 return critical_error(LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID);
168 }
169
170 remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
171 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
172 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
173 }
174
175 if (profile->http_request_method == LASSO_HTTP_METHOD_SOAP) {
176 profile->msg_url = NULL;
177 LASSO_SAMLP_RESPONSE_ABSTRACT(profile->response)->private_key_file =
178 profile->server->private_key;
179 LASSO_SAMLP_RESPONSE_ABSTRACT(profile->response)->certificate_file =
180 profile->server->certificate;
181 profile->msg_body = lasso_node_export_to_soap(profile->response);
182 return 0;
183 }
184
185 if (profile->http_request_method == LASSO_HTTP_METHOD_REDIRECT) {
186 url = lasso_provider_get_metadata_one(remote_provider,
187 "RegisterNameIdentifierServiceReturnURL");
188 if (url == NULL) {
189 return critical_error(LASSO_PROFILE_ERROR_UNKNOWN_PROFILE_URL);
190 }
191 query = lasso_node_export_to_query_with_password(LASSO_NODE(profile->response),
192 profile->server->signature_method,
193 profile->server->private_key,
194 profile->server->private_key_password);
195 if (query == NULL) {
196 lasso_release(url);
197 return critical_error(LASSO_PROFILE_ERROR_BUILDING_QUERY_FAILED);
198 }
199 /* build the msg_url */
200 profile->msg_url = lasso_concat_url_query(url, query);
201 lasso_release(url);
202 lasso_release(query);
203 profile->msg_body = NULL;
204
205 return 0;
206 }
207
208 return critical_error(LASSO_PROFILE_ERROR_INVALID_HTTP_METHOD);
209 }
210
211 /**
212 * lasso_name_registration_destroy:
213 * @name_registration: a #LassoNameRegistration
214 *
215 * Destroys a #LassoNameRegistration object.
216 **/
217 void
lasso_name_registration_destroy(LassoNameRegistration * name_registration)218 lasso_name_registration_destroy(LassoNameRegistration *name_registration)
219 {
220 lasso_node_destroy(LASSO_NODE(name_registration));
221 }
222
223
224 /**
225 * lasso_name_registration_init_request:
226 * @name_registration: a #LassoNameRegistration
227 * @remote_providerID: the providerID of the identity provider.
228 * @http_method: if set, then it get the protocol profile in metadata
229 * corresponding of this HTTP request method.
230 *
231 * Initializes a new lib:RegisterNameIdentifierRequest request; it sets
232 * @name_registration->nameIdentifier to the new name identifier and
233 * @name_registration->oldNameIdentifier to the old one.
234 *
235 * Return value: 0 on success; or a negative value otherwise.
236 **/
237 gint
lasso_name_registration_init_request(LassoNameRegistration * name_registration,char * remote_providerID,LassoHttpMethod http_method)238 lasso_name_registration_init_request(LassoNameRegistration *name_registration,
239 char *remote_providerID, LassoHttpMethod http_method)
240 {
241 LassoProfile *profile;
242 LassoProvider *remote_provider;
243 LassoFederation *federation;
244 LassoSamlNameIdentifier *spNameIdentifier, *idpNameIdentifier, *oldNameIdentifier = NULL;
245
246 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
247 LASSO_PARAM_ERROR_INVALID_VALUE);
248 g_return_val_if_fail(remote_providerID != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
249
250 profile = LASSO_PROFILE(name_registration);
251
252 /* verify if the identity and session exist */
253 if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
254 return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
255 }
256
257 /* set the remote provider id */
258 profile->remote_providerID = g_strdup(remote_providerID);
259
260 remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
261 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
262 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
263 }
264
265 /* Get federation */
266 federation = g_hash_table_lookup(profile->identity->federations,
267 profile->remote_providerID);
268 if (LASSO_IS_FEDERATION(federation) == FALSE) {
269 return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
270 }
271
272 /* FIXME : depending on the requester provider type, verify the format
273 * of the old name identifier is only federated type */
274
275 if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) {
276 /* Initiating it, from a SP */
277 spNameIdentifier = lasso_saml_name_identifier_new();
278 spNameIdentifier->content = lasso_build_unique_id(32);
279 spNameIdentifier->NameQualifier = g_strdup(profile->remote_providerID);
280 spNameIdentifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED);
281
282 idpNameIdentifier = LASSO_SAML_NAME_IDENTIFIER(g_object_ref(federation->remote_nameIdentifier));
283
284 if (federation->local_nameIdentifier) {
285 /* old name identifier is from SP,
286 * name_registration->oldNameIdentifier must be from SP */
287 oldNameIdentifier = LASSO_SAML_NAME_IDENTIFIER(g_object_ref(federation->local_nameIdentifier));
288 } else {
289 /* oldNameIdentifier is none, no local name identifier at SP, old is IDP */
290 oldNameIdentifier = LASSO_SAML_NAME_IDENTIFIER(g_object_ref(idpNameIdentifier));
291 }
292
293 profile->nameIdentifier = LASSO_NODE(g_object_ref(spNameIdentifier));
294 name_registration->oldNameIdentifier = g_object_ref(oldNameIdentifier);
295 } else { /* if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) { */
296 /* Initiating it, from an IdP */
297 if (federation->local_nameIdentifier == NULL) {
298 return LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND;
299 }
300
301 oldNameIdentifier = LASSO_SAML_NAME_IDENTIFIER(g_object_ref(federation->local_nameIdentifier));
302
303 spNameIdentifier = NULL;
304 if (federation->remote_nameIdentifier) {
305 spNameIdentifier = LASSO_SAML_NAME_IDENTIFIER(g_object_ref(federation->remote_nameIdentifier));
306 }
307
308 idpNameIdentifier = lasso_saml_name_identifier_new();
309 idpNameIdentifier->content = lasso_build_unique_id(32);
310 idpNameIdentifier->NameQualifier = g_strdup(profile->remote_providerID);
311 idpNameIdentifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED);
312
313 profile->nameIdentifier = LASSO_NODE(g_object_ref(idpNameIdentifier));
314 name_registration->oldNameIdentifier = g_object_ref(oldNameIdentifier);
315 }
316
317 if (oldNameIdentifier == NULL) {
318 message(G_LOG_LEVEL_CRITICAL, "Invalid provider type"); /* ??? */
319 return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
320 }
321
322 if (http_method == LASSO_HTTP_METHOD_ANY) {
323 http_method = lasso_provider_get_first_http_method(
324 LASSO_PROVIDER(profile->server),
325 remote_provider,
326 LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER);
327 } else {
328 if (lasso_provider_accept_http_method(LASSO_PROVIDER(profile->server),
329 remote_provider,
330 LASSO_MD_PROTOCOL_TYPE_REGISTER_NAME_IDENTIFIER,
331 http_method,
332 TRUE) == FALSE) {
333 return critical_error(LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE);
334 }
335 }
336
337 profile->request = lasso_lib_register_name_identifier_request_new_full(
338 LASSO_PROVIDER(profile->server)->ProviderID,
339 idpNameIdentifier, spNameIdentifier, oldNameIdentifier,
340 profile->server->certificate ?
341 LASSO_SIGNATURE_TYPE_WITHX509 : LASSO_SIGNATURE_TYPE_SIMPLE,
342 LASSO_SIGNATURE_METHOD_RSA_SHA1);
343 if (profile->request == NULL) {
344 return critical_error(LASSO_PROFILE_ERROR_BUILDING_REQUEST_FAILED);
345 }
346 LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request)->RelayState =
347 g_strdup(profile->msg_relayState);
348
349 if (lasso_provider_get_protocol_conformance(remote_provider) < LASSO_PROTOCOL_LIBERTY_1_2) {
350 LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->MajorVersion = 1;
351 LASSO_SAMLP_REQUEST_ABSTRACT(profile->request)->MinorVersion = 1;
352 }
353
354 profile->http_request_method = http_method;
355
356 return 0;
357 }
358
359
360 /**
361 * lasso_name_registration_process_request_msg:
362 * @name_registration: a #LassoNameRegistration
363 * @request_msg: the register name identifier request message
364 *
365 * Processes a lib:RegisterNameIdentifierRequest message. Rebuilds a request
366 * object from the message and optionally verifies its signature. Sets
367 * profile->nameIdentifier to local name identifier. If it changed (when this
368 * is IdP-initiated and there was no previously defined local name identifier)
369 * profile->nameIdentifier will be the new one and profile->oldNameIdentiifer
370 * the old one.
371 *
372 * Return value: 0 on success; or a negative value otherwise.
373 **/
lasso_name_registration_process_request_msg(LassoNameRegistration * name_registration,char * request_msg)374 gint lasso_name_registration_process_request_msg(LassoNameRegistration *name_registration,
375 char *request_msg)
376 {
377 LassoProfile *profile;
378 LassoProvider *remote_provider;
379 LassoMessageFormat format;
380 LassoLibRegisterNameIdentifierRequest *request;
381
382 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
383 LASSO_PARAM_ERROR_INVALID_VALUE);
384 g_return_val_if_fail(request_msg != NULL,
385 LASSO_PARAM_ERROR_INVALID_VALUE);
386
387 profile = LASSO_PROFILE(name_registration);
388
389 profile->request = lasso_lib_register_name_identifier_request_new();
390 format = lasso_node_init_from_message(LASSO_NODE(profile->request), request_msg);
391 if (format == LASSO_MESSAGE_FORMAT_UNKNOWN || format == LASSO_MESSAGE_FORMAT_ERROR) {
392 return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
393 }
394
395 remote_provider = lasso_server_get_provider(profile->server,
396 LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request)->ProviderID);
397 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
398 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
399 }
400
401 /* verify signatures */
402 profile->signature_status = lasso_provider_verify_signature(
403 remote_provider, request_msg, "RequestID", format);
404
405 if (format == LASSO_MESSAGE_FORMAT_SOAP)
406 profile->http_request_method = LASSO_HTTP_METHOD_SOAP;
407 if (format == LASSO_MESSAGE_FORMAT_QUERY)
408 profile->http_request_method = LASSO_HTTP_METHOD_REDIRECT;
409
410 request = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request);
411
412 name_registration->oldNameIdentifier = NULL;
413 if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) {
414 /* IdP initiated */
415 if (request->SPProvidedNameIdentifier) {
416 profile->nameIdentifier = LASSO_NODE(g_object_ref(request->SPProvidedNameIdentifier));
417 } else {
418 profile->nameIdentifier = LASSO_NODE(g_object_ref(request->IDPProvidedNameIdentifier));
419 name_registration->oldNameIdentifier = g_object_ref(
420 request->OldProvidedNameIdentifier);
421 }
422 } else if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) {
423 /* SP initiated, profile->name */
424 profile->nameIdentifier = LASSO_NODE(g_object_ref(request->IDPProvidedNameIdentifier));
425 }
426
427 return profile->signature_status;
428 }
429
430
431 /**
432 * lasso_name_registration_process_response_msg:
433 * @name_registration: a #LassoNameRegistration
434 * @response_msg: the register name identifier response message
435 *
436 * Processes a lib:RegisterNameIdentifierResponse message. Rebuilds a response
437 * object from the message and optionally verifies its signature.
438 *
439 * If the response depicts Success it will also update Principal federation.
440 *
441 * Return value: 0 on success; or a negative value otherwise.
442 **/
443 gint
lasso_name_registration_process_response_msg(LassoNameRegistration * name_registration,char * response_msg)444 lasso_name_registration_process_response_msg(LassoNameRegistration *name_registration,
445 char *response_msg)
446 {
447 LassoProfile *profile;
448 LassoProvider *remote_provider;
449 LassoFederation *federation;
450 LassoSamlNameIdentifier *nameIdentifier = NULL;
451 LassoLibStatusResponse *response;
452 LassoMessageFormat format;
453 int rc = 0;
454 char *statusCodeValue;
455
456 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
457 LASSO_PARAM_ERROR_INVALID_VALUE);
458 g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
459
460 profile = LASSO_PROFILE(name_registration);
461
462 /* build register name identifier response from message */
463 profile->response = lasso_lib_register_name_identifier_response_new();
464 format = lasso_node_init_from_message(LASSO_NODE(profile->response), response_msg);
465 if (format == LASSO_MESSAGE_FORMAT_UNKNOWN || format == LASSO_MESSAGE_FORMAT_ERROR) {
466 return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG);
467 }
468
469 remote_provider = lasso_server_get_provider(profile->server,
470 LASSO_LIB_STATUS_RESPONSE(profile->response)->ProviderID);
471 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
472 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
473 }
474
475 /* verify signature */
476 rc = lasso_provider_verify_signature(remote_provider, response_msg, "ResponseID", format);
477
478 response = LASSO_LIB_STATUS_RESPONSE(profile->response);
479 if (response->Status == NULL || response->Status->StatusCode == NULL
480 || response->Status->StatusCode->Value == NULL) {
481 return critical_error(LASSO_PROFILE_ERROR_MISSING_STATUS_CODE);
482 }
483 statusCodeValue = response->Status->StatusCode->Value;
484
485 if (strcmp(statusCodeValue, LASSO_SAML_STATUS_CODE_SUCCESS) != 0) {
486 message(G_LOG_LEVEL_CRITICAL, "Status code not success: %s", statusCodeValue);
487 return LASSO_PROFILE_ERROR_STATUS_NOT_SUCCESS;
488 }
489
490 /* Update federation with the nameIdentifier attribute. NameQualifier
491 * is local ProviderID and format is Federated type */
492 if (LASSO_IS_IDENTITY(profile->identity) == FALSE) {
493 return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
494 }
495
496 federation = g_hash_table_lookup(profile->identity->federations,
497 profile->remote_providerID);
498 if (LASSO_IS_FEDERATION(federation) == FALSE) {
499 return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
500 }
501
502 remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
503 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
504 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
505 }
506
507 if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) {
508 nameIdentifier = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(
509 profile->request)->IDPProvidedNameIdentifier;
510 }
511 if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) {
512 nameIdentifier = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(
513 profile->request)->SPProvidedNameIdentifier;
514 }
515 if (nameIdentifier == NULL) {
516 message(G_LOG_LEVEL_CRITICAL, "Invalid provider role"); /* ??? */
517 return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
518 }
519
520 if (federation->local_nameIdentifier)
521 lasso_node_destroy(LASSO_NODE(federation->local_nameIdentifier));
522 federation->local_nameIdentifier = LASSO_NODE(g_object_ref(nameIdentifier));
523 profile->identity->is_dirty = TRUE;
524
525 /* set the relay state */
526 profile->msg_relayState = g_strdup(
527 LASSO_LIB_STATUS_RESPONSE(profile->response)->RelayState);
528
529 return rc;
530 }
531
532
533 /**
534 * lasso_name_registration_validate_request:
535 * @name_registration: a #LassoNameRegistration
536 *
537 * Checks profile request with regards to message status and principal
538 * federations, update them accordingly and prepares a
539 * lib:RegisterNameIdentifierResponse accordingly.
540 *
541 * Return value: 0 on success; or a negative value otherwise.
542 **/
543 gint
lasso_name_registration_validate_request(LassoNameRegistration * name_registration)544 lasso_name_registration_validate_request(LassoNameRegistration *name_registration)
545 {
546 LassoProfile *profile;
547 LassoProvider *remote_provider;
548 LassoFederation *federation;
549 LassoLibRegisterNameIdentifierRequest *request;
550 LassoSamlNameIdentifier *providedNameIdentifier = NULL;
551
552 g_return_val_if_fail(LASSO_IS_NAME_REGISTRATION(name_registration),
553 LASSO_PARAM_ERROR_INVALID_VALUE);
554
555 profile = LASSO_PROFILE(name_registration);
556
557 /* verify the register name identifier request */
558 if (LASSO_IS_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request) == FALSE) {
559 message(G_LOG_LEVEL_CRITICAL, "Register Name Identifier request not found");
560 return LASSO_PROFILE_ERROR_MISSING_REQUEST;
561 }
562
563 request = LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request);
564
565 /* set the remote provider id from the request */
566 profile->remote_providerID = g_strdup(request->ProviderID);
567 if (profile->remote_providerID == NULL) {
568 return LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID;
569 }
570
571 /* set register name identifier response */
572 profile->response = lasso_lib_register_name_identifier_response_new_full(
573 LASSO_PROVIDER(profile->server)->ProviderID,
574 LASSO_SAML_STATUS_CODE_SUCCESS,
575 LASSO_LIB_REGISTER_NAME_IDENTIFIER_REQUEST(profile->request),
576 profile->server->certificate ?
577 LASSO_SIGNATURE_TYPE_WITHX509 : LASSO_SIGNATURE_TYPE_SIMPLE,
578 LASSO_SIGNATURE_METHOD_RSA_SHA1);
579 if (LASSO_IS_LIB_REGISTER_NAME_IDENTIFIER_RESPONSE(profile->response) == FALSE) {
580 return critical_error(LASSO_PROFILE_ERROR_BUILDING_RESPONSE_FAILED);
581 }
582
583 /* verify federation */
584 if (profile->identity == NULL) {
585 return critical_error(LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND);
586 }
587
588 federation = g_hash_table_lookup(profile->identity->federations,
589 profile->remote_providerID);
590 if (LASSO_IS_FEDERATION(federation) == FALSE) {
591 return critical_error(LASSO_PROFILE_ERROR_FEDERATION_NOT_FOUND);
592 }
593
594 if (request->OldProvidedNameIdentifier == NULL) {
595 message(G_LOG_LEVEL_CRITICAL, "Old provided name identifier not found");
596 return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
597 }
598
599 if (lasso_federation_verify_name_identifier(federation, LASSO_NODE(
600 request->OldProvidedNameIdentifier)) == FALSE) {
601 message(G_LOG_LEVEL_CRITICAL, "No name identifier");
602 return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
603 }
604
605 remote_provider = lasso_server_get_provider(profile->server, profile->remote_providerID);
606 if (LASSO_IS_PROVIDER(remote_provider) == FALSE) {
607 return critical_error(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND);
608 }
609
610 /* update name identifier in federation */
611 if (remote_provider->role == LASSO_PROVIDER_ROLE_SP) {
612 providedNameIdentifier = request->SPProvidedNameIdentifier;
613 }
614 if (remote_provider->role == LASSO_PROVIDER_ROLE_IDP) {
615 providedNameIdentifier = request->IDPProvidedNameIdentifier;
616 }
617 if (providedNameIdentifier == NULL) {
618 message(G_LOG_LEVEL_CRITICAL, "Sp provided name identifier not found");
619 return LASSO_PROFILE_ERROR_MISSING_NAME_IDENTIFIER;
620 }
621
622 if (federation->remote_nameIdentifier)
623 lasso_node_destroy(LASSO_NODE(federation->remote_nameIdentifier));
624 federation->remote_nameIdentifier = LASSO_NODE(g_object_ref(providedNameIdentifier));
625 profile->identity->is_dirty = TRUE;
626
627 return 0;
628 }
629
630
631
632 /*****************************************************************************/
633 /* private methods */
634 /*****************************************************************************/
635
636 static struct XmlSnippet schema_snippets[] = {
637 { "OldNameIdentifier", SNIPPET_NODE_IN_CHILD,
638 G_STRUCT_OFFSET(LassoNameRegistration, oldNameIdentifier), NULL, NULL, NULL},
639 { "NameRegistrationDumpVersion", SNIPPET_ATTRIBUTE, 0, NULL, NULL, NULL},
640 {NULL, 0, 0, NULL, NULL, NULL}
641 };
642
643 static LassoNodeClass *parent_class = NULL;
644
645 static xmlNode*
get_xmlNode(LassoNode * node,gboolean lasso_dump)646 get_xmlNode(LassoNode *node, gboolean lasso_dump)
647 {
648 xmlNode *xmlnode;
649
650 xmlnode = parent_class->get_xmlNode(node, lasso_dump);
651 xmlSetProp(xmlnode, (xmlChar*)"NameRegistrationDumpVersion", (xmlChar*)"2");
652
653 return xmlnode;
654 }
655
656 static int
init_from_xml(LassoNode * node,xmlNode * xmlnode)657 init_from_xml(LassoNode *node, xmlNode *xmlnode)
658 {
659 return parent_class->init_from_xml(node, xmlnode);
660 }
661
662 /*****************************************************************************/
663 /* instance and class init functions */
664 /*****************************************************************************/
665
666 static void
instance_init(LassoNameRegistration * name_registration)667 instance_init(LassoNameRegistration *name_registration)
668 {
669 name_registration->oldNameIdentifier = NULL;
670 }
671
672 static void
class_init(LassoNameRegistrationClass * klass,void * unused G_GNUC_UNUSED)673 class_init(LassoNameRegistrationClass *klass, void *unused G_GNUC_UNUSED)
674 {
675 LassoNodeClass *nclass = LASSO_NODE_CLASS(klass);
676
677 parent_class = g_type_class_peek_parent(klass);
678 nclass->get_xmlNode = get_xmlNode;
679 nclass->init_from_xml = init_from_xml;
680 nclass->node_data = g_new0(LassoNodeClassData, 1);
681 lasso_node_class_set_nodename(nclass, "NameRegistration");
682 lasso_node_class_set_ns(nclass, LASSO_LASSO_HREF, LASSO_LASSO_PREFIX);
683 lasso_node_class_add_snippets(nclass, schema_snippets);
684 }
685
686 GType
lasso_name_registration_get_type()687 lasso_name_registration_get_type()
688 {
689 static GType this_type = 0;
690
691 if (!this_type) {
692 static const GTypeInfo this_info = {
693 sizeof (LassoNameRegistrationClass),
694 NULL,
695 NULL,
696 (GClassInitFunc) class_init,
697 NULL,
698 NULL,
699 sizeof(LassoNameRegistration),
700 0,
701 (GInstanceInitFunc) instance_init,
702 NULL
703 };
704
705 this_type = g_type_register_static(LASSO_TYPE_PROFILE,
706 "LassoNameRegistration", &this_info, 0);
707 }
708 return this_type;
709 }
710
711 /**
712 * lasso_name_registration_new:
713 * @server: the #LassoServer
714 *
715 * Creates a new #LassoNameRegistration.
716 *
717 * Return value: a newly created #LassoNameRegistration object; or NULL if
718 * an error occured
719 **/
720 LassoNameRegistration *
lasso_name_registration_new(LassoServer * server)721 lasso_name_registration_new(LassoServer *server)
722 {
723 LassoNameRegistration *name_registration;
724
725 g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
726
727 name_registration = g_object_new(LASSO_TYPE_NAME_REGISTRATION, NULL);
728 LASSO_PROFILE(name_registration)->server = g_object_ref(server);
729
730 return name_registration;
731 }
732
733 /**
734 * lasso_name_registration_new_from_dump:
735 * @server: the #LassoServer
736 * @dump: XML logout dump
737 *
738 * Restores the @dump to a new #LassoNameRegistration.
739 *
740 * Return value: a newly created #LassoNameRegistration; or NULL if an error
741 * occured
742 **/
743 LassoNameRegistration*
lasso_name_registration_new_from_dump(LassoServer * server,const char * dump)744 lasso_name_registration_new_from_dump(LassoServer *server, const char *dump)
745 {
746 LassoNameRegistration *name_registration;
747 xmlDoc *doc;
748
749 if (dump == NULL)
750 return NULL;
751
752 name_registration = lasso_name_registration_new(server);
753 doc = xmlParseMemory(dump, strlen(dump));
754 init_from_xml(LASSO_NODE(name_registration), xmlDocGetRootElement(doc));
755 lasso_release_doc(doc);
756
757 return name_registration;
758 }
759
760 /**
761 * lasso_name_registration_dump:
762 * @name_registration: a #LassoNameRegistration
763 *
764 * Dumps @name_registration content to an XML string.
765 *
766 * Return value:(transfer full): the dump string. It must be freed by the caller.
767 **/
768 gchar *
lasso_name_registration_dump(LassoNameRegistration * name_registration)769 lasso_name_registration_dump(LassoNameRegistration *name_registration)
770 {
771 return lasso_node_dump(LASSO_NODE(name_registration));
772 }
773