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:federation
26  * @short_description: Principal federation between two providers
27  *
28  * A #LassoFederation represents the an identifier shared by two provider, usually an identity
29  * provider and a service provider. Instance of this class are usually never accessed directly.
30  **/
31 
32 #include "../utils.h"
33 #include "../xml/private.h"
34 #include "federation.h"
35 #include "provider.h"
36 
37 #include "../xml/saml-2.0/saml2_name_id.h"
38 
39 struct _LassoFederationPrivate
40 {
41 	gboolean dispose_has_run;
42 };
43 
44 /*****************************************************************************/
45 /* static methods/functions                                                  */
46 /*****************************************************************************/
47 
48 static LassoNode*
lasso_federation_build_name_identifier(const gchar * nameQualifier,const gchar * format,const gchar * content)49 lasso_federation_build_name_identifier(const gchar *nameQualifier,
50 		const gchar *format, const gchar *content)
51 {
52 	LassoSamlNameIdentifier *nameIdentifier;
53 
54 	nameIdentifier = LASSO_SAML_NAME_IDENTIFIER(lasso_saml_name_identifier_new());
55 	if (content == NULL) {
56 		nameIdentifier->content = lasso_build_unique_id(32);
57 	} else {
58 		nameIdentifier->content = g_strdup(content);
59 	}
60 	nameIdentifier->NameQualifier = g_strdup(nameQualifier);
61 	nameIdentifier->Format = g_strdup(format);
62 
63 	return LASSO_NODE(nameIdentifier);
64 }
65 
66 /*****************************************************************************/
67 /* public methods                                                            */
68 /*****************************************************************************/
69 
70 /**
71  * lasso_federation_build_local_name_identifier:
72  * @federation: a #LassoFederation
73  * @nameQualifier: the name identifier qualifier
74  * @format: the name identifier format
75  * @content: the name identifier content
76  *
77  * Builds federation local name identifier.
78  **/
79 void
lasso_federation_build_local_name_identifier(LassoFederation * federation,const gchar * nameQualifier,const gchar * format,const gchar * content)80 lasso_federation_build_local_name_identifier(LassoFederation *federation,
81 		const gchar     *nameQualifier,
82 		const gchar     *format,
83 		const gchar     *content)
84 {
85 	federation->local_nameIdentifier = lasso_federation_build_name_identifier(
86 			nameQualifier, format, content);
87 }
88 
89 /**
90  * lasso_federation_destroy:
91  * @federation: a #LassoFederation
92  *
93  * Destroys a federation.
94  **/
95 void
lasso_federation_destroy(LassoFederation * federation)96 lasso_federation_destroy(LassoFederation *federation)
97 {
98 	lasso_node_destroy(LASSO_NODE(federation));
99 }
100 
101 /**
102  * lasso_federation_verify_name_identifier:
103  * @federation: a #LassoFederation
104  * @name_identifier: the #LassoSamlNameIdentifier
105  *
106  * Checks whether federation is for @name_identifier.
107  *
108  * Return value: %TRUE if the federation is for @name_identifier.
109  **/
110 gboolean
lasso_federation_verify_name_identifier(LassoFederation * federation,LassoNode * name_identifier)111 lasso_federation_verify_name_identifier(LassoFederation *federation,
112 		LassoNode *name_identifier)
113 {
114 	LassoProtocolConformance conformance;
115 	char *s, *content;
116 
117 	g_return_val_if_fail(LASSO_IS_FEDERATION(federation), FALSE);
118 	g_return_val_if_fail(LASSO_IS_NODE(name_identifier), FALSE);
119 
120 	if (LASSO_IS_SAML_NAME_IDENTIFIER(name_identifier)) {
121 		conformance = LASSO_PROTOCOL_LIBERTY_1_2;
122 		content = LASSO_SAML_NAME_IDENTIFIER(name_identifier)->content;
123 	} else if (LASSO_IS_SAML2_NAME_ID(name_identifier)) {
124 		conformance = LASSO_PROTOCOL_SAML_2_0;
125 		content = LASSO_SAML2_NAME_ID(name_identifier)->content;
126 	} else {
127 		return FALSE;
128 	}
129 
130 	/* verify local name identifier */
131 	if (federation->local_nameIdentifier != NULL) {
132 		if (conformance == LASSO_PROTOCOL_LIBERTY_1_2) {
133 			s = LASSO_SAML_NAME_IDENTIFIER(federation->local_nameIdentifier)->content;
134 		} else {
135 			s = LASSO_SAML2_NAME_ID(federation->local_nameIdentifier)->content;
136 		}
137 		if (strcmp(s, content) == 0) {
138 			return TRUE;
139 		}
140 	}
141 
142 	/* verify remote name identifier */
143 	if (federation->remote_nameIdentifier != NULL) {
144 		if (conformance == LASSO_PROTOCOL_LIBERTY_1_2) {
145 			s = LASSO_SAML_NAME_IDENTIFIER(federation->remote_nameIdentifier)->content;
146 		} else {
147 			s = LASSO_SAML2_NAME_ID(federation->remote_nameIdentifier)->content;
148 		}
149 		if (strcmp(s, content) == 0) {
150 			return TRUE;
151 		}
152 	}
153 
154 	return FALSE;
155 }
156 
157 
158 /*****************************************************************************/
159 /* private methods                                                           */
160 /*****************************************************************************/
161 
162 static struct XmlSnippet schema_snippets[] = {
163 	{ "LocalNameIdentifier", SNIPPET_NODE_IN_CHILD,
164 		G_STRUCT_OFFSET(LassoFederation, local_nameIdentifier), NULL, NULL, NULL},
165 	{ "RemoteNameIdentifier", SNIPPET_NODE_IN_CHILD,
166 		G_STRUCT_OFFSET(LassoFederation, remote_nameIdentifier), NULL, NULL, NULL},
167 	{ "RemoteProviderID", SNIPPET_ATTRIBUTE,
168 		G_STRUCT_OFFSET(LassoFederation, remote_providerID), NULL, NULL, NULL},
169 	{ "FederationDumpVersion", SNIPPET_ATTRIBUTE, 0, NULL, NULL, NULL },
170 	{NULL, 0, 0, NULL, NULL, NULL}
171 };
172 
173 static LassoNodeClass *parent_class = NULL;
174 
175 static xmlNode*
get_xmlNode(LassoNode * node,gboolean lasso_dump)176 get_xmlNode(LassoNode *node, gboolean lasso_dump)
177 {
178 	xmlNode *xmlnode;
179 
180 	xmlnode = parent_class->get_xmlNode(node, lasso_dump);
181 	xmlSetProp(xmlnode, (xmlChar*)"FederationDumpVersion", (xmlChar*)"2");
182 
183 	return xmlnode;
184 }
185 
186 static int
init_from_xml(LassoNode * node,xmlNode * xmlnode)187 init_from_xml(LassoNode *node, xmlNode *xmlnode)
188 {
189 	return parent_class->init_from_xml(node, xmlnode);
190 }
191 
192 /*****************************************************************************/
193 /* overridden parent class methods                                           */
194 /*****************************************************************************/
195 
196 static void
dispose(GObject * object)197 dispose(GObject *object)
198 {
199 	LassoFederation *federation = LASSO_FEDERATION(object);
200 	if (federation->private_data->dispose_has_run) {
201 		return;
202 	}
203 	federation->private_data->dispose_has_run = TRUE;
204 
205 	G_OBJECT_CLASS(parent_class)->dispose(object);
206 }
207 
208 static void
finalize(GObject * object)209 finalize(GObject *object)
210 {
211 	LassoFederation *federation = LASSO_FEDERATION(object);
212 	lasso_release(federation->private_data);
213 	G_OBJECT_CLASS(parent_class)->finalize(object);
214 }
215 
216 /*****************************************************************************/
217 /* instance and class init functions                                         */
218 /*****************************************************************************/
219 
220 static void
instance_init(LassoFederation * federation)221 instance_init(LassoFederation *federation)
222 {
223 	federation->private_data = g_new0(LassoFederationPrivate, 1);
224 	federation->private_data->dispose_has_run = FALSE;
225 
226 	federation->remote_providerID  = NULL;
227 	federation->local_nameIdentifier  = NULL;
228 	federation->remote_nameIdentifier = NULL;
229 }
230 
231 static void
class_init(LassoFederationClass * klass,void * unused G_GNUC_UNUSED)232 class_init(LassoFederationClass *klass, void *unused G_GNUC_UNUSED)
233 {
234 	LassoNodeClass *nclass = LASSO_NODE_CLASS(klass);
235 
236 	parent_class = g_type_class_peek_parent(klass);
237 	nclass->get_xmlNode = get_xmlNode;
238 	nclass->init_from_xml = init_from_xml;
239 	nclass->node_data = g_new0(LassoNodeClassData, 1);
240 	lasso_node_class_set_nodename(nclass, "Federation");
241 	lasso_node_class_set_ns(nclass, LASSO_LASSO_HREF, LASSO_LASSO_PREFIX);
242 	lasso_node_class_add_snippets(nclass, schema_snippets);
243 
244 	G_OBJECT_CLASS(klass)->dispose = dispose;
245 	G_OBJECT_CLASS(klass)->finalize = finalize;
246 }
247 
248 GType
lasso_federation_get_type()249 lasso_federation_get_type()
250 {
251 	static GType this_type = 0;
252 
253 	if (!this_type) {
254 		static const GTypeInfo this_info = {
255 			sizeof (LassoFederationClass),
256 			NULL,
257 			NULL,
258 			(GClassInitFunc) class_init,
259 			NULL,
260 			NULL,
261 			sizeof(LassoFederation),
262 			0,
263 			(GInstanceInitFunc) instance_init,
264 			NULL
265 		};
266 
267 		this_type = g_type_register_static(LASSO_TYPE_NODE,
268 				"LassoFederation", &this_info, 0);
269 	}
270 	return this_type;
271 }
272 
273 /**
274  * lasso_federation_new:
275  * @remote_providerID: remote Provider ID
276  *
277  * Creates a new #LassoFederation with the remote provider.
278  *
279  * Return value: a newly created #LassoFederation
280  **/
281 LassoFederation*
lasso_federation_new(const gchar * remote_providerID)282 lasso_federation_new(const gchar *remote_providerID)
283 {
284 	LassoFederation *federation;
285 
286 	g_return_val_if_fail(remote_providerID != NULL, NULL);
287 
288 	federation = LASSO_FEDERATION(g_object_new(LASSO_TYPE_FEDERATION, NULL));
289 	federation->remote_providerID = g_strdup(remote_providerID);
290 
291 	return federation;
292 }
293