1
/* $Id: server.c,v 1.61 2004/09/06 12:36:47 nclapies Exp $
3
* Lasso - A free implementation of the Liberty Alliance specifications.
5
* Copyright (C) 2004 Entr'ouvert
6
* http://lasso.entrouvert.org
8
* Authors: Nicolas Clapies <nclapies@entrouvert.com>
9
* Valery Febvre <vfebvre@easter-eggs.com>
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
#include <xmlsec/base64.h>
30
#include <lasso/xml/errors.h>
31
#include <lasso/environs/server.h>
33
#include <lasso/lasso_config.h>
35
#define LASSO_SERVER_NODE "Server"
36
#define LASSO_SERVER_METADATA_NODE "ServerMetadata"
37
#define LASSO_SERVER_PROVIDERS_NODE "Providers"
38
#define LASSO_SERVER_PROVIDERID_NODE "ProviderID"
39
#define LASSO_SERVER_PRIVATE_KEY_NODE "PrivateKey"
40
#define LASSO_SERVER_CERTIFICATE_NODE "Certificate"
41
#define LASSO_SERVER_SIGNATURE_METHOD_NODE "SignatureMethod"
43
struct _LassoServerPrivate
45
gboolean dispose_has_run;
48
static GObjectClass *parent_class = NULL;
50
/*****************************************************************************/
52
/*****************************************************************************/
55
lasso_server_add_lasso_provider(LassoServer *server,
56
LassoProvider *provider)
58
g_return_val_if_fail(LASSO_IS_SERVER(server), -1);
59
g_return_val_if_fail(LASSO_IS_PROVIDER(provider), -2);
61
g_ptr_array_add(server->providers, provider);
66
/*****************************************************************************/
68
/*****************************************************************************/
71
lasso_server_add_provider(LassoServer *server,
74
gchar *ca_certificate)
76
LassoProvider *provider;
78
g_return_val_if_fail(LASSO_IS_SERVER(server), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
79
g_return_val_if_fail(metadata != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
81
provider = lasso_provider_new(metadata, public_key, ca_certificate);
82
if (provider != NULL) {
83
g_ptr_array_add(server->providers, provider);
86
message(G_LOG_LEVEL_CRITICAL, "Failed to add new provider.\n");
87
return LASSO_SERVER_ERROR_ADD_PROVIDER_FAILED;
94
lasso_server_copy(LassoServer *server)
100
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
102
copy = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL));
104
/* herited provider attrs */
105
LASSO_PROVIDER(copy)->metadata = lasso_node_copy(LASSO_PROVIDER(server)->metadata);
106
LASSO_PROVIDER(copy)->public_key = g_strdup(LASSO_PROVIDER(server)->public_key);
107
LASSO_PROVIDER(copy)->ca_certificate = g_strdup(LASSO_PROVIDER(server)->ca_certificate);
109
copy->providers = g_ptr_array_new();
110
for (i=0; i<server->providers->len; i++) {
111
p = g_ptr_array_index(server->providers, i);
112
g_ptr_array_add(copy->providers, lasso_provider_copy(p));
114
copy->providerID = g_strdup(server->providerID);
115
copy->private_key = g_strdup(server->private_key);
116
copy->certificate = g_strdup(server->certificate);
117
copy->signature_method = server->signature_method;
123
lasso_server_destroy(LassoServer *server)
125
g_object_unref(G_OBJECT(server));
129
lasso_server_dump(LassoServer *server)
131
LassoProvider *provider;
132
LassoNode *server_node, *providers_node, *provider_node, *metadata_copy, *metadata_node;
133
LassoNodeClass *metadata_class, *server_class, *providers_class;
134
xmlChar *signature_method_str, *dump;
137
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
139
server_node = lasso_node_new();
140
server_class = LASSO_NODE_GET_CLASS(server_node);
141
server_class->set_name(server_node, LASSO_SERVER_NODE);
142
server_class->set_ns(server_node, lassoLassoHRef, NULL);
144
/* Add lasso version in the xml node */
145
server_class->set_prop(LASSO_NODE(server_node), "version", PACKAGE_VERSION);
147
/* signature method */
148
signature_method_str = g_new(gchar, 6);
149
sprintf(signature_method_str, "%d", server->signature_method);
150
server_class->set_prop(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, signature_method_str);
151
g_free(signature_method_str);
154
if (server->providerID != NULL) {
155
server_class->set_prop(server_node, LASSO_SERVER_PROVIDERID_NODE, server->providerID);
158
if (server->private_key != NULL) {
159
server_class->set_prop(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, server->private_key);
162
if (server->certificate != NULL) {
163
server_class->set_prop(server_node, LASSO_SERVER_CERTIFICATE_NODE, server->certificate);
166
provider = LASSO_PROVIDER(server);
167
if (provider->metadata != NULL) {
168
metadata_node = lasso_node_new();
169
metadata_class = LASSO_NODE_GET_CLASS(metadata_node);
170
metadata_class->set_name(metadata_node, LASSO_SERVER_METADATA_NODE);
171
metadata_class->set_ns(metadata_node, lassoLassoHRef, NULL);
173
metadata_copy = lasso_node_copy(provider->metadata);
174
metadata_class->add_child(metadata_node, metadata_copy, FALSE);
175
lasso_node_destroy(metadata_copy);
176
server_class->add_child(server_node, metadata_node, FALSE);
180
if (provider->public_key != NULL) {
181
server_class->set_prop(server_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, provider->public_key);
184
if (provider->ca_certificate != NULL) {
185
server_class->set_prop(server_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, provider->ca_certificate);
188
providers_node = lasso_node_new();
189
providers_class = LASSO_NODE_GET_CLASS(providers_node);
190
providers_class->set_name(providers_node, LASSO_SERVER_PROVIDERS_NODE);
191
for (i = 0; i<server->providers->len; i++) {
192
dump = lasso_provider_dump(g_ptr_array_index(server->providers, i));
193
provider_node = lasso_node_new_from_dump(dump);
195
providers_class->add_child(providers_node, provider_node, TRUE);
196
lasso_node_destroy(provider_node);
198
server_class->add_child(server_node, providers_node, FALSE);
199
lasso_node_destroy(providers_node);
201
dump = lasso_node_export(server_node);
202
lasso_node_destroy(server_node);
208
lasso_server_get_provider(LassoServer *server,
212
LassoProvider *provider;
213
GError *tmp_err = NULL;
215
if (err != NULL && *err != NULL) {
216
g_set_error(err, g_quark_from_string("Lasso"),
217
LASSO_PARAM_ERROR_CHECK_FAILED,
218
lasso_strerror(LASSO_PARAM_ERROR_CHECK_FAILED));
219
g_return_val_if_fail (err == NULL || *err == NULL, NULL);
222
provider = lasso_server_get_provider_ref(server, providerID, &tmp_err);
224
if (provider != NULL) {
225
return lasso_provider_copy(provider);
228
g_propagate_error (err, tmp_err);
235
lasso_server_get_provider_ref(LassoServer *server,
239
LassoProvider *provider;
243
if (err != NULL && *err != NULL) {
244
g_set_error(err, g_quark_from_string("Lasso"),
245
LASSO_PARAM_ERROR_CHECK_FAILED,
246
lasso_strerror(LASSO_PARAM_ERROR_CHECK_FAILED));
247
g_return_val_if_fail (err == NULL || *err == NULL, NULL);
249
if (LASSO_IS_SERVER(server) == FALSE) {
250
g_set_error(err, g_quark_from_string("Lasso"),
251
LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ,
252
lasso_strerror(LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ));
253
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
255
if (providerID == NULL) {
256
g_set_error(err, g_quark_from_string("Lasso"),
257
LASSO_PARAM_ERROR_INVALID_VALUE,
258
lasso_strerror(LASSO_PARAM_ERROR_INVALID_VALUE));
259
g_return_val_if_fail(providerID != NULL, NULL);
262
len = server->providers->len;
263
for (index = 0; index<len; index++) {
264
provider = g_ptr_array_index(server->providers, index);
266
id = lasso_provider_get_providerID(provider);
268
if (xmlStrEqual(providerID, id)) {
276
/* no provider was found */
277
g_set_error(err, g_quark_from_string("Lasso"),
278
LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND,
279
lasso_strerror(LASSO_SERVER_ERROR_PROVIDER_NOT_FOUND),
281
/* print error msg here so that caller just check err->code */
282
message(G_LOG_LEVEL_CRITICAL, err[0]->message);
288
lasso_server_get_providerID_from_hash(LassoServer *server,
291
LassoProvider *provider;
292
xmlChar *providerID, *hash_providerID;
293
xmlChar *b64_hash_providerID;
296
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
297
g_return_val_if_fail(b64_hash != NULL, NULL);
299
for (i=0; i<server->providers->len; i++) {
300
provider = g_ptr_array_index(server->providers, i);
301
providerID = lasso_provider_get_providerID(provider);
302
if (providerID != NULL) {
303
hash_providerID = lasso_sha1(providerID);
304
b64_hash_providerID = xmlSecBase64Encode(hash_providerID, 20, 0);
305
xmlFree(hash_providerID);
306
if (xmlStrEqual(b64_hash_providerID, b64_hash)) {
307
xmlFree(b64_hash_providerID);
311
xmlFree(b64_hash_providerID);
317
/* failed to get the providerID */
318
message(G_LOG_LEVEL_CRITICAL,
319
"Failed to get a providerID corresponding to the hash.\n")
324
/*****************************************************************************/
325
/* overrided parent class methods */
326
/*****************************************************************************/
329
lasso_server_dispose(LassoServer *server)
333
if (server->private->dispose_has_run == TRUE) {
336
server->private->dispose_has_run = TRUE;
338
debug("Server object 0x%x disposed ...\n", server);
340
/* free allocated memory for providers array */
341
for (i=0; i<server->providers->len; i++) {
342
lasso_provider_destroy(server->providers->pdata[i]);
344
g_ptr_array_free(server->providers, TRUE);
346
parent_class->dispose(G_OBJECT(server));
350
lasso_server_finalize(LassoServer *server)
352
debug("Server object 0x%x finalized ...\n", server);
354
g_free(server->providerID);
355
g_free(server->private_key);
356
g_free(server->certificate);
358
g_free(server->private);
360
parent_class->finalize(G_OBJECT(server));
363
/*****************************************************************************/
364
/* instance and class init functions */
365
/*****************************************************************************/
368
lasso_server_instance_init(LassoServer *server)
370
server->private = g_new (LassoServerPrivate, 1);
371
server->private->dispose_has_run = FALSE;
373
server->providers = g_ptr_array_new();
374
server->providerID = NULL;
375
server->private_key = NULL;
376
server->certificate = NULL;
377
server->signature_method = lassoSignatureMethodRsaSha1;
381
lasso_server_class_init(LassoServerClass *class) {
382
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
384
parent_class = g_type_class_peek_parent(class);
385
/* override parent class methods */
386
gobject_class->dispose = (void *)lasso_server_dispose;
387
gobject_class->finalize = (void *)lasso_server_finalize;
390
GType lasso_server_get_type() {
391
static GType this_type = 0;
394
static const GTypeInfo this_info = {
395
sizeof (LassoServerClass),
398
(GClassInitFunc) lasso_server_class_init,
403
(GInstanceInitFunc) lasso_server_instance_init,
406
this_type = g_type_register_static(LASSO_TYPE_PROVIDER,
414
lasso_server_new(gchar *metadata,
418
lassoSignatureMethod signature_method)
423
LassoNode *md_node = NULL;
424
gchar *providerID = NULL;
427
/* metadata can be NULL (if server is a LECP) */
429
/* put server metadata in a LassoNode */
431
doc = xmlParseFile(metadata);
432
root = xmlCopyNode(xmlDocGetRootElement(doc), 1);
434
md_node = lasso_node_new();
435
LASSO_NODE_GET_CLASS(md_node)->set_xmlNode(md_node, root);
437
/* get ProviderID in metadata */
438
providerID = lasso_node_get_attr_value(md_node, "providerID", &err);
439
if (providerID == NULL) {
440
message(G_LOG_LEVEL_WARNING, err->message);
442
lasso_node_destroy(md_node);
447
/* Ok, we can create server */
448
server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL));
450
if (md_node != NULL) {
451
LASSO_PROVIDER(server)->metadata = md_node;
453
if (providerID != NULL) {
454
server->providerID = providerID;
456
server->private_key = g_strdup(private_key);
457
server->certificate = g_strdup(certificate);
458
server->signature_method = signature_method;
460
LASSO_PROVIDER(server)->public_key = g_strdup(public_key);
461
LASSO_PROVIDER(server)->ca_certificate = NULL;
467
lasso_server_new_from_dump(gchar *dump)
469
LassoNodeClass *server_class, *providers_class;
470
LassoNode *server_node, *providers_node, *provider_node, *entity_node, *server_metadata_node;
472
LassoProvider *provider;
473
xmlNodePtr providers_xmlNode, provider_xmlNode;
474
xmlChar *public_key, *ca_certificate, *signature_method;
476
server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL));
478
server_node = lasso_node_new_from_dump(dump);
479
if (server_node == NULL) {
480
message(G_LOG_LEVEL_WARNING, "Error while loading server dump\n");
483
server_class = LASSO_NODE_GET_CLASS(server_node);
484
if (strcmp(server_class->get_name(server_node), LASSO_SERVER_NODE) != 0) {
485
message(G_LOG_LEVEL_WARNING, "XML is not a server dump\n");
486
lasso_node_destroy(server_node);
491
server->providerID = lasso_node_get_attr_value(server_node, LASSO_SERVER_PROVIDERID_NODE, NULL);
494
server->private_key = lasso_node_get_attr_value(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, NULL);
497
server->certificate = lasso_node_get_attr_value(server_node, LASSO_SERVER_CERTIFICATE_NODE, NULL);
499
/* signature method */
500
signature_method = lasso_node_get_attr_value(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, NULL);
501
if (signature_method != NULL) {
502
server->signature_method = atoi(signature_method);
503
xmlFree(signature_method);
507
server_metadata_node = lasso_node_get_child(server_node, LASSO_SERVER_METADATA_NODE, NULL, NULL);
508
if (server_metadata_node != NULL) {
509
entity_node = lasso_node_get_child(server_metadata_node, "EntityDescriptor", NULL, NULL);
510
LASSO_PROVIDER(server)->metadata = lasso_node_copy(entity_node);
511
lasso_node_destroy(entity_node);
515
LASSO_PROVIDER(server)->public_key = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL);
518
LASSO_PROVIDER(server)->ca_certificate = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, NULL);
521
providers_node = lasso_node_get_child(server_node, LASSO_SERVER_PROVIDERS_NODE, lassoLassoHRef, NULL);
522
if (providers_node != NULL) {
523
providers_class = LASSO_NODE_GET_CLASS(providers_node);
524
providers_xmlNode = providers_class->get_xmlNode(providers_node);
525
provider_xmlNode = providers_xmlNode->children;
527
while (provider_xmlNode != NULL) {
528
if (provider_xmlNode->type == XML_ELEMENT_NODE && \
529
xmlStrEqual(provider_xmlNode->name, LASSO_PROVIDER_NODE)) {
531
provider_node = lasso_node_new_from_xmlNode(provider_xmlNode);
534
entity_node = lasso_node_get_child(provider_node, "EntityDescriptor", NULL, NULL);
537
public_key = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL);
540
ca_certificate = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, NULL);
543
provider = lasso_provider_new_from_metadata_node(entity_node);
544
lasso_node_destroy(entity_node);
545
if (public_key != NULL) {
546
lasso_provider_set_public_key(provider, public_key);
549
if (ca_certificate != NULL) {
550
lasso_provider_set_ca_certificate(provider, ca_certificate);
551
xmlFree(ca_certificate);
553
lasso_server_add_lasso_provider(server, provider);
555
lasso_node_destroy(provider_node);
558
provider_xmlNode = provider_xmlNode->next;
561
lasso_node_destroy(providers_node);
564
lasso_node_destroy(server_node);