lasso/lasso/id-ff/server.c

403 lines
12 KiB
C

/* $Id$
*
* Lasso - A free implementation of the Liberty Alliance specifications.
*
* Copyright (C) 2004 Entr'ouvert
* http://lasso.entrouvert.org
*
* Authors: Nicolas Clapies <nclapies@entrouvert.com>
* Valery Febvre <vfebvre@easter-eggs.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <lasso/environs/server.h>
#define LASSO_SERVER_NODE "LassoServer"
#define LASSO_SERVER_PROVIDERS_NODE "LassoProviders"
#define LASSO_SERVER_PROVIDERID_NODE "ProviderID"
#define LASSO_SERVER_PRIVATE_KEY_NODE "PrivateKey"
#define LASSO_SERVER_CERTIFICATE_NODE "Certificate"
#define LASSO_SERVER_SIGNATURE_METHOD_NODE "SignatureMethod"
static GObjectClass *parent_class = NULL;
/*****************************************************************************/
/* public methods */
/*****************************************************************************/
gchar *
lasso_server_dump(LassoServer *server)
{
LassoProvider *provider;
LassoNode *server_node, *providers_node;
LassoNodeClass *server_class, *providers_class;
xmlChar *signature_method_str, *dump;
gint i;
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
server_node = lasso_node_new();
server_class = LASSO_NODE_GET_CLASS(server_node);
server_class->set_name(server_node, LASSO_SERVER_NODE);
/* signature method */
signature_method_str = g_new(gchar, 6);
sprintf(signature_method_str, "%d", server->signature_method);
server_class->set_prop(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, signature_method_str);
/* providerID */
if(server->providerID)
server_class->set_prop(server_node, LASSO_SERVER_PROVIDERID_NODE, server->providerID);
/* private key */
if(server->private_key)
server_class->set_prop(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, server->private_key);
/* certificate */
if(server->certificate)
server_class->set_prop(server_node, LASSO_SERVER_CERTIFICATE_NODE, server->certificate);
/* metadata */
provider = LASSO_PROVIDER(server);
server_class->add_child(server_node, provider->metadata, FALSE);
/* public key */
if(provider->public_key)
server_class->set_prop(server_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, provider->public_key);
/* ca_certificate */
if(provider->ca_certificate)
server_class->set_prop(server_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, provider->ca_certificate);
/* providers */
providers_node = lasso_node_new();
providers_class = LASSO_NODE_GET_CLASS(providers_node);
providers_class->set_name(providers_node, LASSO_SERVER_PROVIDERS_NODE);
for(i = 0; i<server->providers->len; i++){
dump = lasso_provider_dump(g_ptr_array_index(server->providers, i));
providers_class->add_child(providers_node, lasso_node_new_from_dump(dump), TRUE);
}
server_class->add_child(server_node, providers_node, FALSE);
return(lasso_node_export(server_node));
}
gint
lasso_server_add_lasso_provider(LassoServer *server,
LassoProvider *provider)
{
g_return_val_if_fail(LASSO_IS_SERVER(server), -1);
g_return_val_if_fail(LASSO_IS_PROVIDER(provider), -2);
g_ptr_array_add(server->providers, provider);
return (0);
}
gint
lasso_server_add_provider(LassoServer *server,
gchar *metadata,
gchar *public_key,
gchar *ca_certificate)
{
LassoProvider *provider;
g_return_val_if_fail(LASSO_IS_SERVER(server), -1);
g_return_val_if_fail(metadata!=NULL, -2);
provider = lasso_provider_new(metadata, public_key, ca_certificate);
g_return_val_if_fail(provider!=NULL, -5);
/* debug(INFO, "Add a provider(%s)\n", lasso_provider_get_providerID(provider)); */
g_ptr_array_add(server->providers, provider);
return(0);
}
void
lasso_server_destroy(LassoServer *server)
{
g_object_unref(G_OBJECT(server));
}
LassoProvider*
lasso_server_get_provider(LassoServer *server,
gchar *providerID)
{
LassoProvider *provider;
char *id;
int index, len;
g_return_val_if_fail(LASSO_IS_SERVER(server), NULL);
g_return_val_if_fail(providerID!=NULL, NULL);
/* debug(INFO, "Get information of provider id %s\n", providerID); */
len = server->providers->len;
for(index = 0; index<len; index++) {
provider = g_ptr_array_index(server->providers, index);
id = lasso_provider_get_providerID(provider, NULL);
if (xmlStrEqual(providerID, id)) {
return(provider);
}
}
return(NULL);
}
gchar *
lasso_server_get_providerID_from_hash(LassoServer *server,
gchar *hash)
{
LassoProvider *provider;
gchar *providerID, *hash_providerID;
int index, len;
len = server->providers->len;
for(index = 0; index<len; index++){
provider = g_ptr_array_index(server->providers, index);
providerID = lasso_provider_get_providerID(provider, NULL);
hash_providerID = lasso_str_hash(providerID, server->private_key);
if(xmlStrEqual(hash_providerID, hash)){
return(providerID);
}
else{
g_free(providerID);
g_free(hash_providerID);
}
}
return(NULL);
}
/*****************************************************************************/
/* overrided parent class methods */
/*****************************************************************************/
static void
lasso_server_dispose(LassoServer *server)
{
/* /\* No idea how to access to ->private->dispose_has_run *\/ */
/* if (server->private->dispose_has_run) { */
/* return; */
/* } */
/* server->private->dispose_has_run = TRUE; */
debug(DEBUG, "Server object 0x%x finalized ...\n", server);
/* TODO destroy the providers */
parent_class->dispose(G_OBJECT(server));
}
static void
lasso_server_finalize(LassoServer *server)
{
debug(DEBUG, "Server object 0x%x finalized ...\n", server);
g_free(server->providerID);
g_free(server->private_key);
g_free(server->certificate);
parent_class->finalize(G_OBJECT(server));
}
/*****************************************************************************/
/* instance and class init functions */
/*****************************************************************************/
static void
lasso_server_instance_init(LassoServer *server)
{
server->providers = g_ptr_array_new();
server->providerID = NULL;
server->private_key = NULL;
server->certificate = NULL;
server->signature_method = lassoSignatureMethodRsaSha1;
}
static void
lasso_server_class_init(LassoServerClass *class) {
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
parent_class = g_type_class_peek_parent(class);
/* override parent class methods */
/* object_class->dispose = (void *)lasso_server_dispose; */
gobject_class->finalize = (void *)lasso_server_finalize;
}
GType lasso_server_get_type() {
static GType this_type = 0;
if (!this_type) {
static const GTypeInfo this_info = {
sizeof (LassoServerClass),
NULL,
NULL,
(GClassInitFunc) lasso_server_class_init,
NULL,
NULL,
sizeof(LassoServer),
0,
(GInstanceInitFunc) lasso_server_instance_init,
};
this_type = g_type_register_static(LASSO_TYPE_PROVIDER,
"LassoServer",
&this_info, 0);
}
return this_type;
}
LassoServer *
lasso_server_new(gchar *metadata,
gchar *public_key,
gchar *private_key,
gchar *certificate,
guint signature_method)
{
LassoServer *server;
xmlDocPtr doc;
xmlNodePtr root;
LassoNode *md_node;
gchar *providerID;
GError *err = NULL;
g_return_val_if_fail(metadata != NULL, NULL);
/* put server metadata in a LassoNode */
doc = xmlParseFile(metadata);
root = xmlCopyNode(xmlDocGetRootElement(doc), 1);
xmlFreeDoc(doc);
md_node = lasso_node_new();
LASSO_NODE_GET_CLASS(md_node)->set_xmlNode(md_node, root);
/* md_node = lasso_node_new_from_xmlNode(root); */
/* get ProviderID in metadata */
providerID = lasso_node_get_attr_value(md_node, "ProviderID", &err);
if (providerID == NULL) {
message(G_LOG_LEVEL_ERROR, err->message);
g_error_free(err);
lasso_node_destroy(md_node);
return (NULL);
}
/* Ok, we can create server */
server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL));
LASSO_PROVIDER(server)->metadata = md_node;
server->providerID = providerID;
server->private_key = g_strdup(private_key);
server->certificate = g_strdup(certificate);
server->signature_method = signature_method;
LASSO_PROVIDER(server)->public_key = g_strdup(public_key);
LASSO_PROVIDER(server)->ca_certificate = NULL;
return(server);
}
LassoServer *
lasso_server_new_from_dump(gchar *dump)
{
LassoNodeClass *server_class, *providers_class;
LassoNode *server_node, *providers_node, *provider_node, *entity_node, *server_metadata_node;
LassoServer *server;
LassoProvider *provider;
xmlNodePtr providers_xmlNode, provider_xmlNode;
xmlChar *public_key, *ca_certificate;
server = LASSO_SERVER(g_object_new(LASSO_TYPE_SERVER, NULL));
server_node = lasso_node_new_from_dump(dump);
if(server_node==NULL){
message(G_LOG_LEVEL_ERROR, "Error while loading server dump\n");
return(NULL);
}
server_class = LASSO_NODE_GET_CLASS(server_node);
/* providerID */
server->providerID = lasso_node_get_attr_value(server_node, LASSO_SERVER_PROVIDERID_NODE, NULL);
/* private key */
server->private_key = lasso_node_get_attr_value(server_node, LASSO_SERVER_PRIVATE_KEY_NODE, NULL);
/* certificate */
server->certificate = lasso_node_get_attr_value(server_node, LASSO_SERVER_CERTIFICATE_NODE, NULL);
/* signature method */
/* FIXME signature_method should be checked before atoi !!! */
server->signature_method = atoi(lasso_node_get_attr_value(server_node, LASSO_SERVER_SIGNATURE_METHOD_NODE, NULL));
/* metadata */
server_metadata_node = lasso_node_get_child(server_node, "EntityDescriptor", NULL);
LASSO_PROVIDER(server)->metadata = lasso_node_copy(server_metadata_node);
/* public key */
LASSO_PROVIDER(server)->public_key = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL);
/* ca_certificate */
LASSO_PROVIDER(server)->ca_certificate = lasso_node_get_attr_value(server_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, NULL);
/* providers */
providers_node = lasso_node_get_child(server_node, LASSO_SERVER_PROVIDERS_NODE, NULL);
if(providers_node){
providers_class = LASSO_NODE_GET_CLASS(providers_node);
providers_xmlNode = providers_class->get_xmlNode(providers_node);
provider_xmlNode = providers_xmlNode->children;
while(provider_xmlNode != NULL){
if(provider_xmlNode->type==XML_ELEMENT_NODE && xmlStrEqual(provider_xmlNode->name, LASSO_PROVIDER_NODE)){
/* provider node */
provider_node = lasso_node_new_from_xmlNode(provider_xmlNode);
/* metadata */
entity_node = lasso_node_get_child(provider_node, "EntityDescriptor", NULL);
/* public key */
public_key = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_PUBLIC_KEY_NODE, NULL);
/* ca certificate */
ca_certificate = lasso_node_get_attr_value(provider_node, LASSO_PROVIDER_CA_CERTIFICATE_NODE, NULL);
/* add provider */
provider = lasso_provider_new_from_metadata_node(entity_node);
lasso_node_destroy(entity_node);
if(public_key){
lasso_provider_set_public_key(provider, public_key);
}
if(ca_certificate){
lasso_provider_set_ca_certificate(provider, ca_certificate);
}
lasso_server_add_lasso_provider(server, provider);
lasso_node_destroy(provider_node);
}
provider_xmlNode = provider_xmlNode->next;
}
lasso_node_destroy(providers_node);
}
lasso_node_destroy(server_metadata_node);
lasso_node_destroy(server_node);
return(server);
}