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