~ubuntu-branches/ubuntu/trusty/lasso/trusty

« back to all changes in this revision

Viewing changes to lasso/xml/xml.c

  • Committer: Package Import Robot
  • Author(s): Frederic Peters
  • Date: 2014-01-07 13:22:21 UTC
  • mfrom: (1.1.11) (7.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20140107132221-htp0go0s9z5lqvj8
Tags: 2.4.0-1
* New upstream version.
* debian/control, debian/rules: use autoreconf
* debian/source/version: switch to 3.0 (quilt)

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * GNU General Public License for more details.
19
19
 *
20
20
 * You should have received a copy of the GNU General Public License
21
 
 * along with this program; if not, write to the Free Software
22
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
21
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23
22
 */
24
23
 
25
24
/**
31
30
 *
32
31
 */
33
32
 
34
 
#define _GNU_SOURCE /* for use of strndup */
35
 
 
36
33
#include "private.h"
37
34
#include <ctype.h>
38
35
#include <errno.h>
45
42
#include <xmlsec/crypto.h>
46
43
#include <xmlsec/xmlenc.h>
47
44
#include <xmlsec/openssl/crypto.h>
 
45
#include <xmlsec/openssl/x509.h>
48
46
 
49
47
#include "xml.h"
50
48
#include "xml_enc.h"
52
50
#include "../utils.h"
53
51
#include "../registry.h"
54
52
#include "../debug.h"
55
 
#include "./soap-1.1/soap_envelope.h"
56
 
#include "./soap-1.1/soap_body.h"
 
53
#include "soap-1.1/soap_envelope.h"
 
54
#include "soap-1.1/soap_body.h"
 
55
#include "misc_text_node.h"
57
56
#include "../lasso_config.h"
58
57
#ifdef LASSO_WSF_ENABLED
59
 
#include "./idwsf_strings.h"
60
 
#include "./id-wsf-2.0/idwsf2_strings.h"
 
58
#include "idwsf_strings.h"
 
59
#include "id-wsf-2.0/idwsf2_strings.h"
61
60
#endif
62
61
 
63
 
static void lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode,
 
62
#include "../key.h"
 
63
 
 
64
static void lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, xmlNode *xmlnode,
64
65
                struct XmlSnippet *snippets, gboolean lasso_dump);
65
 
static struct XmlSnippet* find_xml_snippet_by_name(LassoNode *node, char *name);
 
66
static struct XmlSnippet* find_xml_snippet_by_name(LassoNode *node, char *name, LassoNodeClass **class_p);
66
67
static gboolean set_value_at_path(LassoNode *node, char *path, char *query_value);
67
68
static char* get_value_by_path(LassoNode *node, char *path, struct XmlSnippet *xml_snippet);
68
69
static gboolean find_path(LassoNode *node, char *path, LassoNode **value_node,
69
 
                struct XmlSnippet **snippet);
 
70
                LassoNodeClass **class_p, struct XmlSnippet **snippet);
70
71
 
71
72
static void lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
72
73
                struct XmlSnippet *snippet_signature);
74
75
 
75
76
static LassoNode* lasso_node_new_from_xmlNode_with_type(xmlNode *xmlnode, char *typename);
76
77
static void lasso_node_remove_original_xmlnode(LassoNode *node, SnippetType type);
77
 
static xmlNs * get_or_define_ns(xmlNode *xmlnode, xmlChar *ns_uri);
78
78
 
79
79
GHashTable *dst_services_by_href = NULL; /* ID-WSF 1 extra DST services, indexed on href */
80
80
GHashTable *dst_services_by_prefix = NULL; /* ID-WSF 1 extra DST services, indexed on prefix */
86
86
/* global methods                                                            */
87
87
/*****************************************************************************/
88
88
 
89
 
 
90
89
/**
91
90
 * lasso_register_dst_service:
92
91
 * @prefix: prefix of DST service
380
379
 *      caller.
381
380
 **/
382
381
char*
383
 
lasso_node_export_to_query(LassoNode *node,
384
 
                LassoSignatureMethod sign_method, const char *private_key_file)
 
382
lasso_node_export_to_query(LassoNode *node, LassoSignatureMethod sign_method,
 
383
                const char *private_key_file)
385
384
{
386
 
        char *unsigned_query, *query = NULL;
387
 
 
388
 
        g_return_val_if_fail(LASSO_IS_NODE(node), NULL);
389
 
 
390
 
        unsigned_query = lasso_node_build_query(node);
391
 
        if (unsigned_query == NULL) {
392
 
                return NULL;
393
 
        }
394
 
        if (private_key_file) {
395
 
                query = lasso_query_sign(unsigned_query, sign_method, private_key_file, NULL);
396
 
        } else {
397
 
                lasso_transfer_string(query, unsigned_query);
398
 
        }
399
 
        lasso_release(unsigned_query);
400
 
 
401
 
        return query;
 
385
        return lasso_node_export_to_query_with_password(node, sign_method, private_key_file, NULL);
402
386
}
403
387
 
404
388
/**
420
404
                const char *private_key_file_password)
421
405
{
422
406
        char *unsigned_query, *query = NULL;
 
407
        LassoSignatureContext context = LASSO_SIGNATURE_CONTEXT_NONE;
423
408
 
424
409
        g_return_val_if_fail(LASSO_IS_NODE(node), NULL);
425
410
 
 
411
        context.signature_method = sign_method;
 
412
        context.signature_key = lasso_xmlsec_load_private_key(private_key_file,
 
413
                        private_key_file_password, sign_method, NULL);
 
414
 
 
415
        if (! context.signature_key) {
 
416
                return NULL;
 
417
        }
 
418
 
426
419
        unsigned_query = lasso_node_build_query(node);
427
 
        if (unsigned_query == NULL) {
428
 
                return NULL;
429
 
        }
430
 
        if (private_key_file) {
431
 
                query = lasso_query_sign(unsigned_query, sign_method, private_key_file,
432
 
                                private_key_file_password);
433
 
        } else {
434
 
                lasso_transfer_string(query, unsigned_query);
435
 
        }
436
 
        lasso_release(unsigned_query);
437
 
 
438
 
        return query;
 
420
        if (unsigned_query){
 
421
                query = lasso_query_sign(unsigned_query, context);
 
422
                if (query) {
 
423
                        lasso_release(unsigned_query);
 
424
                        unsigned_query = query;
 
425
                }
 
426
        }
 
427
        lasso_release_sec_key(context.signature_key);
 
428
        return unsigned_query;
439
429
}
440
430
 
441
431
/**
742
732
        return class->build_query(node);
743
733
}
744
734
 
 
735
static LassoNodeClassData*
 
736
lasso_legacy_get_signature_node_data(LassoNode *node, LassoNodeClass **out_klass)
 
737
{
 
738
        LassoNodeClass *klass = NULL;
 
739
        LassoNodeClassData *node_data = NULL;
 
740
 
 
741
        klass = LASSO_NODE_GET_CLASS(node);
 
742
        /* find a klass defining a signature */
 
743
        while (klass && LASSO_IS_NODE_CLASS(klass)) {
 
744
                if (klass->node_data && klass->node_data->sign_type_offset) {
 
745
                        if (out_klass) {
 
746
                                *out_klass = klass;
 
747
                        }
 
748
                        node_data = klass->node_data;
 
749
                        break;
 
750
                }
 
751
                klass = g_type_class_peek_parent(klass);
 
752
        }
 
753
 
 
754
        return node_data;
 
755
}
 
756
 
 
757
static gboolean
 
758
lasso_legacy_extract_and_copy_signature_parameters(LassoNode *node, LassoNodeClassData *node_data)
 
759
{
 
760
        LassoSignatureMethod signature_method = LASSO_SIGNATURE_METHOD_NONE;
 
761
        char *private_key_file = NULL;
 
762
        char *certificate_file = NULL;
 
763
 
 
764
        if (! node_data) {
 
765
                return FALSE;
 
766
        }
 
767
        signature_method = G_STRUCT_MEMBER(LassoSignatureMethod, node,
 
768
                        node_data->sign_method_offset);
 
769
        private_key_file = G_STRUCT_MEMBER(char *, node, node_data->private_key_file_offset);
 
770
        certificate_file = G_STRUCT_MEMBER(char *, node, node_data->certificate_file_offset);
 
771
        if (! lasso_validate_signature_method(signature_method)) {
 
772
                return FALSE;
 
773
        }
 
774
        if (lasso_node_set_signature(node,
 
775
                        lasso_make_signature_context_from_path_or_string(private_key_file, NULL,
 
776
                                signature_method, certificate_file)) != 0) {
 
777
                return FALSE;
 
778
        }
 
779
        return TRUE;
 
780
}
745
781
 
746
782
/**
747
783
 * lasso_node_get_xmlNode:
755
791
xmlNode*
756
792
lasso_node_get_xmlNode(LassoNode *node, gboolean lasso_dump)
757
793
{
758
 
        LassoNodeClass *class;
759
 
        xmlNode *xmlnode;
760
 
        LassoNodeClassData *node_data = NULL;
 
794
        xmlNode *xmlnode = NULL;
 
795
        LassoSignatureContext context = LASSO_SIGNATURE_CONTEXT_NONE;
 
796
        LassoNodeClassData *node_data;
761
797
 
762
798
        g_return_val_if_fail (LASSO_IS_NODE(node), NULL);
763
 
        class = LASSO_NODE_GET_CLASS(node);
764
 
        xmlnode = class->get_xmlNode(node, lasso_dump);
 
799
        xmlnode = LASSO_NODE_GET_CLASS(node)->get_xmlNode(node, lasso_dump);
 
800
        node_data = lasso_legacy_get_signature_node_data(node, NULL);
 
801
        context = lasso_node_get_signature(node);
 
802
        /* support for legacy way to put a signature on a node */
 
803
        if (! lasso_validate_signature_context(context)) {
 
804
                if (lasso_legacy_extract_and_copy_signature_parameters(node, node_data))
 
805
                        context = lasso_node_get_signature(node);
 
806
        }
 
807
        if (! lasso_dump && node_data && xmlnode && lasso_validate_signature_context(context)) {
 
808
                int rc;
 
809
                char *id_attribute = G_STRUCT_MEMBER(char*, node,
 
810
                                node_data->id_attribute_offset);
765
811
 
766
 
        /* find a class defining a signature */
767
 
        while (class && LASSO_IS_NODE_CLASS(class)) {
768
 
                if (class->node_data && class->node_data->sign_type_offset) {
769
 
                        node_data = class->node_data;
770
 
                        break;
 
812
                rc = lasso_sign_node(xmlnode, context, node_data->id_attribute_name,
 
813
                                id_attribute);
 
814
                if (rc != 0) {
 
815
                        warning("Signing of %s:%s failed: %s", xmlnode->ns->prefix,
 
816
                                        xmlnode->name, lasso_strerror(rc));
 
817
                        lasso_release_xml_node(xmlnode);
771
818
                }
772
 
                class = g_type_class_peek_parent(class);
773
 
        }
774
 
 
775
 
        /* add signature */
776
 
        if (xmlnode && node_data && node_data->sign_type_offset) {
777
 
                LassoSignatureType sign_type = G_STRUCT_MEMBER(LassoSignatureType, node,
778
 
                                node_data->sign_type_offset);
779
 
                char *id_attribute = G_STRUCT_MEMBER(char*, node,  node_data->id_attribute_offset);
780
 
                char *private_key_file = G_STRUCT_MEMBER(char*, node,
781
 
                                node_data->private_key_file_offset);
782
 
                char *certificate_file = G_STRUCT_MEMBER(char*, node,
783
 
                                node_data->certificate_file_offset);
784
 
 
785
 
                lasso_apply_signature(node, lasso_dump, &xmlnode, node_data->id_attribute_name,
786
 
                                id_attribute, sign_type, private_key_file, certificate_file);
787
819
        }
788
820
 
789
821
        return xmlnode;
813
845
 *
814
846
 * Retrieve the original xmlNode eventually associated to this #LassoNode.
815
847
 *
816
 
 * Return value: an #xmlNodePtr or NULL.
 
848
 * Return value:(transfer none): an #xmlNodePtr or NULL.
817
849
 */
818
850
xmlNodePtr
819
851
lasso_node_get_original_xmlnode(LassoNode *node)
891
923
        char *href;
892
924
        char *nodename;
893
925
        GHashTable *namespaces;
894
 
        LassoSignatureType signature_type;
895
 
        LassoSignatureMethod signature_method;
896
 
        char *private_key;
897
 
        char *private_key_password;
898
 
        char *certificate;
 
926
        LassoSignatureContext signature_context;
899
927
        xmlSecKey *encryption_public_key;
900
928
        LassoEncryptionSymKeyType encryption_sym_key_type;
901
929
};
916
944
                lasso_release_string(custom_element->href);
917
945
                lasso_release_string(custom_element->nodename);
918
946
                lasso_release_ghashtable(custom_element->namespaces);
919
 
                lasso_release_string(custom_element->private_key);
920
 
                lasso_release_string(custom_element->private_key_password);
921
 
                lasso_release_string(custom_element->certificate);
 
947
                lasso_release_sec_key(custom_element->encryption_public_key);
 
948
                lasso_release_sec_key(custom_element->signature_context.signature_key);
922
949
        }
923
950
        lasso_release(custom_element);
924
951
}
982
1009
/**
983
1010
 * lasso_node_set_signature:
984
1011
 * @node: a #LassoNode object
985
 
 * @signature_type: a #LassoSignatureType enum
986
 
 * @signature_method: a #LassoSignatureMethod enum
987
 
 * @private_key: a private key as file path or a PEM string
988
 
 * @private_key_password: the password for the private key
989
 
 * @certificate: an eventual certificate to bind with the signature
 
1012
 * @signature_context: a #LassoSignatureContext structure
990
1013
 *
991
1014
 * Setup a signature on @node.
992
1015
 *
993
1016
 * Return value: 0 if successful, an error code otherwise.
994
1017
 */
995
1018
int
996
 
lasso_node_set_signature(LassoNode *node, LassoSignatureType type, LassoSignatureMethod method,
997
 
                const char *private_key, const char *private_key_password, const char *certificate)
 
1019
lasso_node_set_signature(LassoNode *node, LassoSignatureContext context)
998
1020
{
999
1021
        struct _CustomElement *custom_element;
1000
1022
        int rc = 0;
1002
1024
        lasso_bad_param(NODE, node);
1003
1025
        custom_element = _lasso_node_get_custom_element_or_create(node);
1004
1026
        g_return_val_if_fail (custom_element != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
1005
 
        custom_element->signature_type = type;
1006
 
        custom_element->signature_method = method;
1007
 
        lasso_assign_string(custom_element->private_key, private_key);
1008
 
        lasso_assign_string(custom_element->private_key_password, private_key_password);
1009
 
        lasso_assign_string(custom_element->certificate, certificate);
 
1027
 
 
1028
        if (custom_element->signature_context.signature_key) {
 
1029
                lasso_release_sec_key(custom_element->signature_context.signature_key);
 
1030
        }
 
1031
        custom_element->signature_context.signature_method = context.signature_method;
 
1032
        lasso_assign_new_sec_key(custom_element->signature_context.signature_key,
 
1033
                        context.signature_key);
1010
1034
        return rc;
1011
1035
}
1012
1036
 
1021
1045
 *
1022
1046
 * Return signature parameters stored with this node.
1023
1047
 */
1024
 
void
1025
 
lasso_node_get_signature(LassoNode *node, LassoSignatureType *type, LassoSignatureMethod *method,
1026
 
                char **private_key, char **private_key_password, char **certificate)
 
1048
LassoSignatureContext
 
1049
lasso_node_get_signature(LassoNode *node)
1027
1050
{
1028
1051
        struct _CustomElement *custom_element;
1029
1052
 
1030
 
        g_return_if_fail (LASSO_IS_NODE(node));
 
1053
        g_return_val_if_fail (LASSO_IS_NODE(node), LASSO_SIGNATURE_CONTEXT_NONE);
1031
1054
        custom_element = _lasso_node_get_custom_element(node);
1032
1055
        if (! custom_element) {
1033
 
                if (type)
1034
 
                        *type = 0;
1035
 
                if (method)
1036
 
                        *method = 0;
1037
 
                if (private_key)
1038
 
                        lasso_assign_string(*private_key, NULL);
1039
 
                if (private_key_password)
1040
 
                        lasso_assign_string(*private_key_password, NULL);
1041
 
                if (certificate)
1042
 
                        lasso_assign_string(*certificate, NULL);
1043
 
                return;
 
1056
                return LASSO_SIGNATURE_CONTEXT_NONE;
1044
1057
        }
1045
 
        if (type)
1046
 
                *type = custom_element->signature_type;
1047
 
        if (method)
1048
 
                *method = custom_element->signature_method;
1049
 
        if (private_key)
1050
 
                *private_key = custom_element->private_key;
1051
 
        if (private_key_password)
1052
 
                *private_key_password = custom_element->private_key_password;
1053
 
        if (certificate)
1054
 
                *certificate = custom_element->certificate;
 
1058
        return custom_element->signature_context;
1055
1059
}
1056
1060
 
1057
1061
/**
1173
1177
        LassoNodeClass *class;
1174
1178
        struct XmlSnippet *snippet;
1175
1179
 
1176
 
        if (node == NULL) {
 
1180
        if (node == NULL || do_to_node == NULL) {
1177
1181
                return;
1178
1182
        }
1179
1183
        class = LASSO_NODE_GET_CLASS(node);
1180
 
        if (class == NULL || class->node_data == NULL || do_to_node == NULL) {
1181
 
                return;
1182
 
        }
1183
1184
        do_to_node(node, type);
1184
1185
 
1185
 
        snippet = class->node_data->snippets;
1186
 
        while (snippet->name != NULL) {
1187
 
                SnippetType type;
1188
 
                void **value = G_STRUCT_MEMBER_P(node, snippet->offset);
 
1186
        while (class && LASSO_IS_NODE_CLASS(class) && class->node_data) {
 
1187
                GType g_type = G_TYPE_FROM_CLASS(class);
 
1188
                snippet = class->node_data->snippets;
 
1189
                while (snippet->name != NULL) {
 
1190
                        SnippetType type;
 
1191
                        void **value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
1189
1192
 
1190
 
                type = snippet->type & 0xff;
1191
 
                switch (type) {
1192
 
                        case SNIPPET_NODE:
1193
 
                        case SNIPPET_NAME_IDENTIFIER:
1194
 
                        case SNIPPET_NODE_IN_CHILD:
1195
 
                                lasso_node_traversal(*value, do_to_node, snippet->type);
1196
 
                                break;
1197
 
                        case SNIPPET_LIST_NODES:
1198
 
                                {
1199
 
                                        GList *list = *value;
1200
 
                                        while (list != NULL) {
1201
 
                                                if (list->data) {
1202
 
                                                        lasso_node_traversal(LASSO_NODE(list->data), do_to_node, snippet->type);
 
1193
                        type = snippet->type & 0xff;
 
1194
                        switch (type) {
 
1195
                                case SNIPPET_NODE:
 
1196
                                case SNIPPET_NODE_IN_CHILD:
 
1197
                                        lasso_node_traversal(*value, do_to_node, snippet->type);
 
1198
                                        break;
 
1199
                                case SNIPPET_LIST_NODES:
 
1200
                                        {
 
1201
                                                GList *list = *value;
 
1202
                                                while (list != NULL) {
 
1203
                                                        if (list->data) {
 
1204
                                                                lasso_node_traversal(LASSO_NODE(list->data), do_to_node, snippet->type);
 
1205
                                                        }
 
1206
                                                        list = g_list_next(list);
1203
1207
                                                }
1204
 
                                                list = g_list_next(list);
1205
1208
                                        }
1206
 
                                }
1207
 
                                break;
1208
 
                        default:
1209
 
                                break;
 
1209
                                        break;
 
1210
                                case SNIPPET_UNUSED1:
 
1211
                                        g_assert_not_reached();
 
1212
                                default:
 
1213
                                        break;
 
1214
                        }
 
1215
                        snippet++;
1210
1216
                }
1211
 
                snippet++;
 
1217
                class = g_type_class_peek_parent(class);
1212
1218
        }
1213
1219
}
1214
1220
 
1270
1276
        return rc;
1271
1277
}
1272
1278
 
 
1279
static inline gboolean
 
1280
lasso_equal_namespace(xmlNs *t1, xmlNs *t2) {
 
1281
        return t1 && t2 && (t1 == t2 ||
 
1282
                        lasso_strisequal((char*)t1->href, (char*)t2->href));
 
1283
}
 
1284
 
 
1285
static void
 
1286
snippet_set_value(LassoNode *node, LassoNodeClass *class, struct XmlSnippet *snippet, xmlChar *content) {
 
1287
        void *value;
 
1288
        GType g_type = G_TYPE_FROM_CLASS(class);
 
1289
 
 
1290
        /* If not offset, it means it is handled by an adhoc init_from_xml */
 
1291
        if (! snippet->offset && ! (snippet->type & SNIPPET_PRIVATE)) {
 
1292
                return;
 
1293
        }
 
1294
        value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
 
1295
        if (snippet->type & SNIPPET_INTEGER) {
 
1296
                int val = strtol((char*)content, NULL, 10);
 
1297
                if (((val == INT_MIN || val == INT_MAX) && errno == ERANGE)
 
1298
                                || errno == EINVAL || val < 0) {
 
1299
                        if (snippet->type & SNIPPET_OPTIONAL_NEG) {
 
1300
                                val = -1;
 
1301
                        } else {
 
1302
                                val = 0;
 
1303
                        }
 
1304
                }
 
1305
                (*(int*)value) = val;
 
1306
        } else if (snippet->type & SNIPPET_BOOLEAN) {
 
1307
                int val = 0;
 
1308
                if (strcmp((char*)content, "true") == 0) {
 
1309
                        val = 1;
 
1310
                } else if (strcmp((char*)content, "1") == 0) {
 
1311
                        val = 1;
 
1312
                }
 
1313
                (*(int*)value) = val;
 
1314
        } else {
 
1315
                lasso_assign_string((*(char**)value), (char*)content);
 
1316
                if (lasso_flag_memory_debug == TRUE) {
 
1317
                        fprintf(stderr, "   setting prop %s/%s to value %p: %s\n",
 
1318
                                        G_OBJECT_TYPE_NAME(node), snippet->name, *(void**)value, (char*)content);
 
1319
                }
 
1320
        }
 
1321
}
 
1322
 
 
1323
gboolean
 
1324
next_node_snippet(GSList **class_iter_p, struct XmlSnippet **snippet_p)
 
1325
{
 
1326
        while (*class_iter_p) {
 
1327
                if (*snippet_p) {
 
1328
                        if ((*snippet_p)->name) {
 
1329
                                SnippetType type = (*snippet_p)->type;
 
1330
                                /* special case for ArtifactResponse */
 
1331
                                if (type & SNIPPET_ANY && (type & 0xff) == SNIPPET_NODE)
 
1332
                                        return TRUE;
 
1333
                                if (! (type & SNIPPET_ANY) && (*snippet_p)->name[0] != '\0') {
 
1334
                                        switch (type & 0xff) {
 
1335
                                                case SNIPPET_NODE:
 
1336
                                                case SNIPPET_NODE_IN_CHILD:
 
1337
                                                case SNIPPET_LIST_XMLNODES:
 
1338
                                                case SNIPPET_LIST_CONTENT:
 
1339
                                                case SNIPPET_LIST_NODES:
 
1340
                                                case SNIPPET_EXTENSION:
 
1341
                                                case SNIPPET_XMLNODE:
 
1342
                                                case SNIPPET_CONTENT:
 
1343
                                                case SNIPPET_SIGNATURE:
 
1344
                                                        return TRUE;
 
1345
                                                default:
 
1346
                                                        break;
 
1347
                                        }
 
1348
                                }
 
1349
                                ++*snippet_p;
 
1350
                        } else {
 
1351
                                *class_iter_p = g_slist_next(*class_iter_p);
 
1352
                                *snippet_p = NULL;
 
1353
                        }
 
1354
                } else {
 
1355
                        *snippet_p = ((LassoNodeClass*)(*class_iter_p)->data)
 
1356
                                                ->node_data->snippets;
 
1357
                }
 
1358
        }
 
1359
        return FALSE;
 
1360
}
 
1361
 
 
1362
static inline gboolean
 
1363
is_snippet_type(struct XmlSnippet *snippet, SnippetType simple_type) {
 
1364
        return (snippet->type & 0xff) == simple_type;
 
1365
}
 
1366
 
 
1367
static inline gboolean
 
1368
is_snippet_mandatory(struct XmlSnippet *snippet)
 
1369
{
 
1370
        return snippet->type & SNIPPET_MANDATORY ? TRUE : FALSE;
 
1371
}
 
1372
 
 
1373
static inline gboolean
 
1374
is_snippet_multiple(struct XmlSnippet *snippet)
 
1375
{
 
1376
        switch (snippet->type & 0xff) {
 
1377
                case SNIPPET_LIST_XMLNODES:
 
1378
                case SNIPPET_LIST_CONTENT:
 
1379
                case SNIPPET_LIST_NODES:
 
1380
                case SNIPPET_EXTENSION:
 
1381
                        return TRUE;
 
1382
                default:
 
1383
                        return FALSE;
 
1384
        }
 
1385
}
 
1386
 
 
1387
static inline gboolean
 
1388
node_match_snippet(xmlNode *parent, xmlNode *node, struct XmlSnippet *snippet)
 
1389
{
 
1390
        gboolean rc = TRUE;
 
1391
 
 
1392
        /* special case of ArtifactResponse */
 
1393
        if (snippet->type & SNIPPET_ANY) {
 
1394
                return TRUE;
 
1395
        } else {
 
1396
                rc = rc && lasso_strisequal(snippet->name, (char*)node->name);
 
1397
                rc = rc &&
 
1398
                    ((!snippet->ns_uri &&
 
1399
                        lasso_equal_namespace(parent->ns, node->ns)) ||
 
1400
                    (node->ns &&
 
1401
                           lasso_strisequal((char*)node->ns->href, snippet->ns_uri)));
 
1402
                return rc;
 
1403
        }
 
1404
}
 
1405
 
1273
1406
/** FIXME: return a real error code */
1274
1407
static int
1275
1408
lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
1281
1414
        SnippetType type;
1282
1415
        struct XmlSnippet *snippet_any = NULL;
1283
1416
        struct XmlSnippet *snippet_any_attribute = NULL;
 
1417
        GType g_type_collect_namespaces, g_type_any, g_type_any_attribute;
1284
1418
        struct XmlSnippet *snippet_collect_namespaces = NULL;
1285
1419
        struct XmlSnippet *snippet_signature = NULL;
1286
 
        GSList *unknown_nodes = NULL;
1287
 
        GSList *known_attributes = NULL;
1288
1420
        gboolean keep_xmlnode = FALSE;
1289
 
 
1290
 
        class = LASSO_NODE_GET_CLASS(node);
1291
 
 
1292
 
        /* What do you want me to initialize ? */
1293
 
        if (! xmlnode)
1294
 
                return 1;
1295
 
 
 
1421
        GSList *class_list = NULL;
 
1422
        GSList *class_iter = NULL;
 
1423
        xmlAttr *attr = NULL;
 
1424
        GType g_type = 0;
 
1425
        LassoNodeClass *node_class;
 
1426
        gint rc = 0;
 
1427
 
 
1428
        if (! xmlnode) {
 
1429
                rc = 1;
 
1430
                goto cleanup;
 
1431
        }
 
1432
 
 
1433
        node_class = class = LASSO_NODE_GET_CLASS(node);
1296
1434
        /* No node_data no initialization possible */
1297
1435
        if (! class->node_data) {
1298
 
                message(G_LOG_LEVEL_WARNING, "Class %s has no node_data so no initialization is possible", G_OBJECT_CLASS_NAME(class));
1299
 
                return 0;
1300
 
        }
1301
 
 
1302
 
        if (lasso_flag_memory_debug == TRUE) {
1303
 
                fprintf(stderr, "Initializing %s (at %p)\n", G_OBJECT_TYPE_NAME(node), node);
1304
 
        }
1305
 
 
1306
 
        while (class && LASSO_IS_NODE_CLASS(class) && class->node_data) {
1307
 
                lasso_trace(" initializing %s\n", G_OBJECT_CLASS_NAME(class));
1308
 
 
1309
 
                /* reduce keep_xmlnode flags */
1310
 
                keep_xmlnode |= class->node_data->keep_xmlnode;
1311
 
 
1312
 
                for (t = xmlnode->children; t; t = t->next) {
1313
 
                        if (t->type == XML_TEXT_NODE) {
1314
 
                                for (snippet = class->node_data->snippets;
1315
 
                                                snippet && snippet->name; snippet++) {
1316
 
                                        GList **location = NULL;
1317
 
 
1318
 
                                        type = snippet->type & 0xff;
1319
 
                                        value = G_STRUCT_MEMBER_P(node, snippet->offset);
1320
 
 
1321
 
                                        if (type == SNIPPET_LIST_XMLNODES) {
1322
 
                                                location = value;
1323
 
                                                *location = g_list_append(
1324
 
                                                                *location, xmlCopyNode(t, 1));
1325
 
                                                trace_snippet("   adding xmlNode %p", g_list_last(*location)->data);
1326
 
                                        } else if (type == SNIPPET_LIST_NODES &&
1327
 
                                                        snippet->type & SNIPPET_ALLOW_TEXT) {
1328
 
                                                LassoNode *text_node;
1329
 
                                                text_node = lasso_node_new_from_xmlNode_with_type(t,
1330
 
                                                                "LassoMiscTextNode");
1331
 
                                                location = value;
1332
 
                                                *location = g_list_append(*location, text_node);
1333
 
                                                trace_snippet("   adding LassoMiscTextNode %p", text_node);
1334
 
                                        }
1335
 
                                        continue;
1336
 
                                }
1337
 
                                continue;
1338
 
                        }
1339
 
 
1340
 
                        if (t->type != XML_ELEMENT_NODE)
1341
 
                                continue;
1342
 
 
1343
 
                        for (snippet = class->node_data->snippets;
1344
 
                                        snippet && snippet->name; snippet++) {
1345
 
                                void *tmp = NULL;
 
1436
                message(G_LOG_LEVEL_WARNING, "Class %s has no node_data so no initialization "
 
1437
                                "is possible", G_OBJECT_CLASS_NAME(class));
 
1438
                rc = 1;
 
1439
                goto cleanup;
 
1440
        }
 
1441
 
 
1442
        /* Collect special snippets like SNIPPET_COLLECT_NAMESPACES, SNIPPET_ANY, SNIPPET_ATTRIBUTE
 
1443
         * or SNIPPET_SIGNATURE, and initialize class_list in reverse. */
 
1444
        while (class && LASSO_IS_NODE_CLASS(class)) {
 
1445
                if (class->node_data) {
 
1446
                        GType g_type = G_TYPE_FROM_CLASS(class);
 
1447
                        keep_xmlnode |= class->node_data->keep_xmlnode;
 
1448
                        if (class->node_data->snippets)
 
1449
                                class_list = g_slist_prepend(class_list, class);
 
1450
                        for (snippet = class->node_data->snippets; snippet && snippet->name; snippet++) {
1346
1451
                                type = snippet->type & 0xff;
1347
 
                                value = G_STRUCT_MEMBER_P(node, snippet->offset);
1348
 
 
1349
 
                                if ((snippet->type & SNIPPET_ANY) && type != SNIPPET_ATTRIBUTE) {
1350
 
                                        snippet_any = snippet;
1351
 
                                }
1352
 
 
1353
 
                                if (strcmp((char*)t->name, snippet->name) != 0 && snippet->name[0])
1354
 
                                        continue;
1355
 
 
1356
 
                                if (type == SNIPPET_NODE) {
1357
 
                                        tmp = lasso_node_new_from_xmlNode_with_type(t,
1358
 
                                                        snippet->class_name);
1359
 
                                } else if (type == SNIPPET_NODE_IN_CHILD) {
1360
 
                                        xmlNode *t2 = t->children;
1361
 
                                        while (t2 && t2->type != XML_ELEMENT_NODE)
1362
 
                                                t2 = t2->next;
1363
 
                                        if (t2) {
1364
 
                                                tmp = lasso_node_new_from_xmlNode_with_type(t2,
1365
 
                                                                snippet->class_name);
1366
 
                                        }
1367
 
                                } else if (type == SNIPPET_CONTENT) {
1368
 
                                        tmp = xmlNodeGetContent(t);
1369
 
                                } else if (type == SNIPPET_NAME_IDENTIFIER) {
1370
 
                                        tmp = lasso_saml_name_identifier_new_from_xmlNode(t);
1371
 
                                } else if (type == SNIPPET_LIST_NODES) {
1372
 
                                        GList **location = value;
1373
 
                                        LassoNode *n;
1374
 
                                        n = lasso_node_new_from_xmlNode_with_type(t,
1375
 
                                                        snippet->class_name);
1376
 
                                        if (n == NULL && snippet_any == snippet &&
1377
 
                                                        t->properties == NULL && t->children &&
1378
 
                                                        t->children->type == XML_TEXT_NODE &&
1379
 
                                                        t->children->next == NULL) {
1380
 
                                                /* unknown, but no attributes, and content
1381
 
                                                 * is text ? -> use generic object */
1382
 
                                                n = lasso_node_new_from_xmlNode_with_type(t,
1383
 
                                                                "LassoMiscTextNode");
1384
 
                                        }
1385
 
                                        if (n && snippet->type & SNIPPET_KEEP_XMLNODE &&
1386
 
                                                        ! LASSO_NODE_GET_CLASS(n)->node_data->keep_xmlnode) {
1387
 
                                                lasso_node_set_original_xmlnode(n, t);
1388
 
                                        }
1389
 
 
1390
 
                                        if (n) {
1391
 
                                                *location = g_list_append(*location, n);
1392
 
                                                trace_snippet("   adding %p of type %s(%s) to ",
1393
 
                                                                n, G_OBJECT_TYPE_NAME(n),
1394
 
                                                                snippet->class_name);
1395
 
                                        } else {
1396
 
                                                /* failed to do sth with */
1397
 
                                                message(G_LOG_LEVEL_WARNING,
1398
 
                                                                "Failed to do sth with %s",
1399
 
                                                                t->name);
1400
 
                                        }
1401
 
                                } else if (type == SNIPPET_LIST_CONTENT) {
1402
 
                                        GList **location = value;
1403
 
                                        xmlChar *s = xmlNodeGetContent(t);
1404
 
                                        lasso_list_add_string(*location, (char*)s);
1405
 
                                        trace_snippet("   adding text %s as content to ", s);
1406
 
                                        lasso_release_xml_string(s);
1407
 
                                } else if (type == SNIPPET_EXTENSION ||
1408
 
                                                type == SNIPPET_LIST_XMLNODES) {
1409
 
                                        GList **location = value;
1410
 
                                        *location = g_list_append(*location, xmlCopyNode(t, 1));
1411
 
                                        trace_snippet("   adding xmlNode %p to ", g_list_last(*location)->data);
1412
 
                                } else if (type == SNIPPET_XMLNODE) {
1413
 
                                        tmp = xmlCopyNode(t, 1);
1414
 
                                } else if (type == SNIPPET_COLLECT_NAMESPACES) {
1415
 
                                        /* Collect namespaces on the children t */
1416
 
                                        _lasso_node_collect_namespaces(value, t);
1417
 
                                }
1418
 
 
1419
 
                                if (tmp == NULL)
1420
 
                                        break;
1421
 
 
1422
 
                                if (type == SNIPPET_XMLNODE || type == SNIPPET_NODE || type == SNIPPET_NODE_IN_CHILD || type ==
1423
 
                                                SNIPPET_NAME_IDENTIFIER) {
1424
 
                                        if (snippet->type & SNIPPET_KEEP_XMLNODE && !
1425
 
                                                        LASSO_NODE_GET_CLASS(tmp)->node_data->keep_xmlnode)
1426
 
                                        {
1427
 
                                                lasso_trace("    setting original xmlNode of %p (%s) to %p", tmp, G_OBJECT_TYPE_NAME(tmp), t)
1428
 
                                                lasso_node_set_original_xmlnode(tmp, t);
1429
 
                                        }
1430
 
                                        if (type == SNIPPET_XMLNODE) {
1431
 
                                                trace_snippet("   setting xmlNode %p as ", tmp);
1432
 
                                        } else {
1433
 
                                                trace_snippet("   setting %p of type %s (wanted %s) as ", tmp,
1434
 
                                                                G_OBJECT_TYPE_NAME(tmp),
1435
 
                                                                snippet->class_name);
1436
 
                                        }
1437
 
                                        *(void**)value = tmp;
1438
 
                                        tmp = NULL;
1439
 
                                } else if (snippet->type & SNIPPET_INTEGER) {
1440
 
                                        int val = strtol(tmp, NULL, 10);
1441
 
                                        if (((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE)
1442
 
                                                        || errno == EINVAL || val < 0) {
1443
 
                                                if (snippet->type & SNIPPET_OPTIONAL_NEG) {
1444
 
                                                        val = -1;
1445
 
                                                } else {
1446
 
                                                        val = 0;
1447
 
                                                }
1448
 
                                        }
1449
 
                                        (*(int*)value) = val;
1450
 
                                        trace_snippet("   setting integer %i for ", val);
1451
 
                                        xmlFree(tmp);
1452
 
                                        tmp = NULL;
1453
 
                                } else if (snippet->type & SNIPPET_BOOLEAN) {
1454
 
                                        int val = 0;
1455
 
                                        if (strcmp((char*)tmp, "true") == 0) {
1456
 
                                                val = 1;
1457
 
                                        } else if (strcmp((char*)tmp, "1") == 0) {
1458
 
                                                val = 1;
1459
 
                                        }
1460
 
                                        trace_snippet("   setting bool %s for ", val ? "TRUE" : "FALSE");
1461
 
                                        (*(int*)value) = val;
1462
 
                                        xmlFree(tmp);
1463
 
                                        tmp = NULL;
1464
 
                                } else {
1465
 
                                        lasso_release_string(*(char**)value);
1466
 
                                        *(char**)value = g_strdup(tmp);
1467
 
                                        trace_snippet("   setting text %s as value for ", (char*)tmp);
1468
 
                                        if (lasso_flag_memory_debug == TRUE) {
1469
 
                                                fprintf(stderr, "   setting field %s/%s to value %p: %s\n", G_OBJECT_TYPE_NAME(node), snippet->name, *(void**)value, (char*)tmp);
1470
 
                                        }
1471
 
                                        lasso_release_xml_string((*(xmlChar**)&tmp));
1472
 
                                        tmp = NULL;
1473
 
                                }
1474
 
 
1475
 
                                break;
1476
 
                        }
1477
 
                        if ((snippet == NULL || snippet->name == NULL) && snippet_any) {
1478
 
                                if (g_slist_find(unknown_nodes, t) == NULL)
1479
 
                                        unknown_nodes = g_slist_append(unknown_nodes, t);
1480
 
                        } else {
1481
 
                                unknown_nodes = g_slist_remove(unknown_nodes, t);
1482
 
                        }
1483
 
                }
1484
 
 
1485
 
                for (snippet = class->node_data->snippets; snippet && snippet->name; snippet++) {
1486
 
                        void *tmp = NULL;
1487
 
                        type = snippet->type & 0xff;
1488
 
 
1489
 
                        value = G_STRUCT_MEMBER_P(node, snippet->offset);
1490
 
                        if (snippet->name && snippet->name[0] == '\0' && type ==
1491
 
                                        SNIPPET_COLLECT_NAMESPACES) {
1492
 
                                snippet_collect_namespaces = snippet;
1493
 
                        }
1494
 
 
1495
 
                        if (type == SNIPPET_SIGNATURE) {
1496
 
                                snippet_signature = snippet;
1497
 
                        }
1498
 
 
1499
 
                        if (type == SNIPPET_ATTRIBUTE) {
1500
 
                                if (snippet->type & SNIPPET_ANY) {
 
1452
 
 
1453
                                if (snippet->name && snippet->name[0] == '\0' && type ==
 
1454
                                                SNIPPET_COLLECT_NAMESPACES) {
 
1455
                                        snippet_collect_namespaces = snippet;
 
1456
                                        g_type_collect_namespaces = g_type;
 
1457
                                } else if (type == SNIPPET_SIGNATURE) {
 
1458
                                        snippet_signature = snippet;
 
1459
                                } else if (type == SNIPPET_ATTRIBUTE && snippet->type & SNIPPET_ANY) {
 
1460
                                        g_type_any_attribute = g_type;
1501
1461
                                        snippet_any_attribute = snippet;
1502
 
                                        continue;
1503
 
                                }
1504
 
                                tmp = xmlGetProp(xmlnode, (xmlChar*)snippet->name);
1505
 
                                known_attributes = g_slist_append(known_attributes, snippet->name);
1506
 
                        }
1507
 
                        if (type == SNIPPET_TEXT_CHILD)
1508
 
                                tmp = xmlNodeGetContent(xmlnode);
1509
 
                        if (tmp == NULL)
1510
 
                                continue;
1511
 
 
1512
 
                        if (snippet->type & SNIPPET_INTEGER) {
1513
 
                                int val = strtol(tmp, NULL, 10);
1514
 
                                if (((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE)
1515
 
                                                || errno == EINVAL || val < 0) {
1516
 
                                        if (snippet->type & SNIPPET_OPTIONAL_NEG) {
1517
 
                                                val = -1;
 
1462
                                } else if (type == SNIPPET_TEXT_CHILD) {
 
1463
                                        xmlChar *tmp = xmlNodeGetContent(xmlnode);
 
1464
                                        snippet_set_value(node, class, snippet, tmp);
 
1465
                                        lasso_release_xml_string(tmp);
 
1466
                                } else if (type != SNIPPET_ATTRIBUTE && type != SNIPPET_NODE && snippet->type & SNIPPET_ANY) {
 
1467
                                        if (! snippet_any) {
 
1468
                                                g_type_any = g_type;
 
1469
                                                snippet_any = snippet;
1518
1470
                                        } else {
1519
 
                                                val = 0;
 
1471
                                                critical("Two any node snippet for class %s",
 
1472
                                                                g_type_name(G_TYPE_FROM_INSTANCE(node)));
1520
1473
                                        }
1521
1474
                                }
1522
 
                                (*(int*)value) = val;
1523
 
                        } else if (snippet->type & SNIPPET_BOOLEAN) {
1524
 
                                int val = 0;
1525
 
                                if (strcmp((char*)tmp, "true") == 0) {
1526
 
                                        val = 1;
1527
 
                                } else if (strcmp((char*)tmp, "1") == 0) {
1528
 
                                        val = 1;
1529
 
                                }
1530
 
                                (*(int*)value) = val;
1531
 
                        } else {
1532
 
                                lasso_assign_string((*(char**)value), tmp);
1533
 
                                if (lasso_flag_memory_debug == TRUE) {
1534
 
                                        fprintf(stderr, "   setting prop %s/%s to value %p: %s\n",
1535
 
                                                        G_OBJECT_TYPE_NAME(node), snippet->name, *(void**)value, (char*)tmp);
1536
 
                                }
1537
1475
                        }
1538
 
                        xmlFree(tmp);
1539
1476
                }
1540
 
 
1541
1477
                class = g_type_class_peek_parent(class);
1542
1478
        }
1543
1479
 
1544
 
        /* If any parent asked for keeping the current xmlnode, keep it around */
 
1480
        /* If any class asked for keeping the xmlNode, keep it around */
1545
1481
        if (keep_xmlnode) {
1546
1482
                lasso_node_set_original_xmlnode(node, xmlnode);
1547
1483
        }
1548
1484
 
 
1485
        /** Collect attributes */
 
1486
        for (attr = xmlnode->properties; attr; attr = attr->next) {
 
1487
                xmlChar *content;
 
1488
                content = xmlNodeGetContent((xmlNode*)attr);
 
1489
                int ok = 0;
 
1490
 
 
1491
                /* Skip xsi:type if it was used to find the node class */
 
1492
                if (attr->ns && lasso_strisequal((char*)attr->name, "type") &&
 
1493
                                lasso_strisequal((char*)attr->ns->href, LASSO_XSI_HREF)) {
 
1494
                        char *colon = strchr((char*)content, ':');
 
1495
                        if (colon) {
 
1496
                                xmlNs *ns;
 
1497
                                *colon = '\0';
 
1498
                                ns = xmlSearchNs(NULL, xmlnode, content);
 
1499
                                *colon = ':';
 
1500
                                if (ns && lasso_strisequal((char*)ns->href, (char*)node_class->node_data->ns->href)
 
1501
                                                && lasso_strisequal(&colon[1], node_class->node_data->node_name)) {
 
1502
                                        lasso_release_xml_string(content);
 
1503
                                        continue;
 
1504
                                }
 
1505
                        }
 
1506
                }
 
1507
 
 
1508
                for (class_iter = class_list; class_iter; class_iter = class_iter->next) {
 
1509
                        class = class_iter->data;
 
1510
                        for (snippet = class->node_data->snippets;
 
1511
                                        snippet && snippet->name; snippet++) {
 
1512
                                type = snippet->type & 0xff;
 
1513
                                /* assign attribute content if attribute has the same name as the
 
1514
                                 * snippet and:
 
1515
                                 * - the snippet and the attribute have no namespace
 
1516
                                 * - the snippet has no namespace but the attribute has the same
 
1517
                                 *   namespace as the node
 
1518
                                 * - the snippet and the node have a namespace, which are equal.
 
1519
                                 */
 
1520
                                if (type != SNIPPET_ATTRIBUTE)
 
1521
                                        continue;
 
1522
                                if (! lasso_strisequal((char*)attr->name, (char*)snippet->name))
 
1523
                                        continue;
 
1524
                                if (attr->ns) {
 
1525
                                        gboolean same_namespace, given_namespace;
 
1526
 
 
1527
                                        same_namespace = lasso_equal_namespace(attr->ns,
 
1528
                                                        xmlnode->ns) && ! snippet->ns_uri;
 
1529
                                        given_namespace = snippet->ns_uri &&
 
1530
                                                lasso_strisequal((char*)attr->ns->href,
 
1531
                                                                snippet->ns_uri);
 
1532
                                        if (! same_namespace && ! given_namespace)
 
1533
                                                break;
 
1534
                                }
 
1535
                                snippet_set_value(node, class, snippet, content);
 
1536
                                ok = 1;
 
1537
                                break;
 
1538
                        }
 
1539
                }
 
1540
                if (! ok && attr->ns && snippet_any_attribute) {
 
1541
                        GHashTable **any_attribute;
 
1542
                        gchar *key;
 
1543
 
 
1544
                        any_attribute = SNIPPET_STRUCT_MEMBER_P(node, g_type_any_attribute,
 
1545
                                        snippet_any_attribute);
 
1546
                        if (*any_attribute == NULL) {
 
1547
                                *any_attribute = g_hash_table_new_full(g_str_hash, g_str_equal,
 
1548
                                                g_free, g_free);
 
1549
                        }
 
1550
                        if (lasso_equal_namespace(attr->ns, xmlnode->ns)) {
 
1551
                                key = g_strdup((char*)attr->name);
 
1552
                        } else {
 
1553
                                key = g_strdup_printf("{%s}%s", attr->ns->href, attr->name);
 
1554
                        }
 
1555
                        g_hash_table_insert(*any_attribute, key, g_strdup((char*)content));
 
1556
                        lasso_release_xml_string(content);
 
1557
                } else if (! ok) {
 
1558
                        warning("lasso_node_impl_init_from_xml: Unexpected attribute: {%s}%s = %s",
 
1559
                                        attr->ns ? attr->ns->href : NULL, attr->name, content);
 
1560
                }
 
1561
                lasso_release_xml_string(content);
 
1562
        }
 
1563
 
 
1564
        /* Collect children nodes in reverse order of class parents (older parent first), skip non
 
1565
         * node and ANY snippets) */
 
1566
        class_iter = class_list;
 
1567
        snippet = ((LassoNodeClass*)class_iter->data)->node_data->snippets;
 
1568
        next_node_snippet(&class_iter, &snippet);
 
1569
        for (t = xmlnode->children; t && class_iter && snippet; t = t->next) {
 
1570
                /* Only collect text node if:
 
1571
                 * - there is a LIST_XMLNODES any snippet
 
1572
                 * - there is a LIST_NODES any snippet with the ALLOW_TEXT modifier
 
1573
                 */
 
1574
                if (t->type == XML_TEXT_NODE && snippet_any &&
 
1575
                                (is_snippet_type(snippet_any, SNIPPET_LIST_XMLNODES)
 
1576
                                 || (is_snippet_type(snippet_any, SNIPPET_LIST_NODES) &&
 
1577
                                         (snippet_any->type & SNIPPET_ALLOW_TEXT)))) {
 
1578
                        GList **location = SNIPPET_STRUCT_MEMBER_P(node, g_type_any, snippet_any);
 
1579
                        if (is_snippet_type(snippet_any, SNIPPET_LIST_XMLNODES)) {
 
1580
                                lasso_list_add_xml_node(*location, t);
 
1581
                        } else {
 
1582
                                lasso_list_add_new_gobject(*location,
 
1583
                                                lasso_node_new_from_xmlNode_with_type(t,
 
1584
                                                        "LassoMiscTextNode"));
 
1585
                        }
 
1586
                } else if (t->type == XML_COMMENT_NODE || t->type == XML_PI_NODE || t->type == XML_TEXT_NODE) {
 
1587
                        /* ignore comments */
 
1588
                        continue;
 
1589
                } else if (t->type == XML_ELEMENT_NODE) {
 
1590
                        LassoNode *subnode = NULL;
 
1591
                        xmlNode *first_child = NULL;
 
1592
                        GList **list = NULL;
 
1593
                        xmlChar *content = NULL;
 
1594
                        gboolean match = FALSE;
 
1595
                        struct XmlSnippet *matched_snippet = NULL;
 
1596
 
 
1597
#define ADVANCE \
 
1598
                                snippet++; \
 
1599
                                next_node_snippet(&class_iter, &snippet);
 
1600
#define ERROR \
 
1601
                                error("Element %s:%s cannot be parsed", \
 
1602
                                                t->ns != NULL ? (char*)t->ns->prefix : "<noprefix>", \
 
1603
                                                t->name); \
 
1604
                                rc = 1; \
 
1605
                                goto cleanup;
 
1606
                        /* Find a matching snippet */
 
1607
                        while (class_iter && snippet) {
 
1608
                                gboolean mandatory = is_snippet_mandatory(snippet);
 
1609
                                gboolean multiple = is_snippet_multiple(snippet);
 
1610
 
 
1611
                                if ((match = node_match_snippet(xmlnode, t, snippet))) {
 
1612
                                        matched_snippet = snippet;
 
1613
                                        class = class_iter->data;
 
1614
                                        g_type = G_TYPE_FROM_CLASS(class);
 
1615
                                        value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
 
1616
                                        list = value;
 
1617
                                        if (! multiple) {
 
1618
                                                ADVANCE;
 
1619
                                        }
 
1620
                                        break;
 
1621
                                } else {
 
1622
                                        if (mandatory) {
 
1623
                                                break;
 
1624
                                        } else {
 
1625
                                                ADVANCE;
 
1626
                                        }
 
1627
                                }
 
1628
                        }
 
1629
                        if (! match) {
 
1630
                                ERROR;
 
1631
                        }
 
1632
#undef ADVANCE
 
1633
#undef ERROR
 
1634
 
 
1635
                        if (matched_snippet->offset || (matched_snippet->type & SNIPPET_PRIVATE)) {
 
1636
                                switch (matched_snippet->type & 0xff) {
 
1637
                                        case SNIPPET_LIST_NODES:
 
1638
                                        case SNIPPET_NODE:
 
1639
                                                subnode = lasso_node_new_from_xmlNode_with_type(t,
 
1640
                                                                matched_snippet->class_name);
 
1641
                                                if (is_snippet_type(matched_snippet, SNIPPET_NODE)) {
 
1642
                                                        lasso_assign_new_gobject(*(LassoNode**)value, subnode);
 
1643
                                                } else {
 
1644
                                                        lasso_list_add_new_gobject(*list, subnode);
 
1645
                                                }
 
1646
                                                break;
 
1647
                                        case SNIPPET_NODE_IN_CHILD:
 
1648
                                                first_child = xmlSecGetNextElementNode(t->children);
 
1649
                                                if (first_child) {
 
1650
                                                        subnode = lasso_node_new_from_xmlNode_with_type(first_child,
 
1651
                                                                                matched_snippet->class_name);
 
1652
                                                        lasso_assign_new_gobject(*(LassoNode**)value, subnode);
 
1653
                                                }
 
1654
                                                break;
 
1655
                                        case SNIPPET_XMLNODE:
 
1656
                                                lasso_assign_xml_node(*(xmlNode**)value, t);
 
1657
                                                break;
 
1658
                                        case SNIPPET_LIST_XMLNODES:
 
1659
                                        case SNIPPET_EXTENSION:
 
1660
                                                lasso_list_add_xml_node(*list, t);
 
1661
                                                break;
 
1662
                                        case SNIPPET_CONTENT:
 
1663
                                        case SNIPPET_LIST_CONTENT:
 
1664
                                                content = xmlNodeGetContent(t);
 
1665
                                                if (is_snippet_type(matched_snippet, SNIPPET_CONTENT)) {
 
1666
                                                        snippet_set_value(node, class, matched_snippet, content);
 
1667
                                                } else { /* only list of string-like xsd:type supported */
 
1668
                                                        lasso_list_add_string(*list, (char*)content);
 
1669
                                                }
 
1670
                                                lasso_release_xml_string(content);
 
1671
                                                break;
 
1672
                                        case SNIPPET_SIGNATURE:
 
1673
                                                /* We ignore it */
 
1674
                                                break;
 
1675
                                        default:
 
1676
                                                g_assert_not_reached();
 
1677
 
 
1678
                                }
 
1679
                        }
 
1680
                        /* When creating a new LassoNode and option KEEP_XMLNODE is present,
 
1681
                         * we attached the xmlNode to the LassoNode */
 
1682
                        if (subnode && (matched_snippet->type & SNIPPET_KEEP_XMLNODE)) {
 
1683
                                lasso_node_set_original_xmlnode(subnode, t);
 
1684
                        }
 
1685
                } else {
 
1686
                        g_assert_not_reached();
 
1687
                }
 
1688
        }
 
1689
        if (t) { /* t is an ELEMENT that dont match any snippet, when taken in order */
 
1690
                if (snippet_any && is_snippet_type(snippet_any, SNIPPET_LIST_XMLNODES)) {
 
1691
                        value = SNIPPET_STRUCT_MEMBER_P(node, g_type_any, snippet_any);
 
1692
                        GList **list = value;
 
1693
                        for (; t; t = t->next) {
 
1694
                                lasso_list_add_xml_node(*list, t);
 
1695
                        }
 
1696
                } else if (snippet_any && is_snippet_type(snippet_any, SNIPPET_LIST_NODES)) {
 
1697
                        value = SNIPPET_STRUCT_MEMBER_P(node, g_type_any, snippet_any);
 
1698
                        GList **list = value;
 
1699
                        for (; t; t = t->next) {
 
1700
                                LassoNode *subnode = NULL;
 
1701
 
 
1702
                                if (t->type == XML_TEXT_NODE && (snippet_any->type &
 
1703
                                                        SNIPPET_ALLOW_TEXT)) {
 
1704
                                        lasso_list_add_new_gobject(*list,
 
1705
                                                        lasso_node_new_from_xmlNode_with_type(t,
 
1706
                                                                "LassoMiscTextNode"));
 
1707
                                } else if (t->type == XML_ELEMENT_NODE) {
 
1708
                                        subnode = lasso_node_new_from_xmlNode_with_type(t,
 
1709
                                                        snippet_any->class_name);
 
1710
                                        if (subnode && (snippet_any->type & SNIPPET_KEEP_XMLNODE)) {
 
1711
                                                lasso_node_set_original_xmlnode(subnode, t);
 
1712
                                        }
 
1713
                                        if (! subnode) {
 
1714
                                                subnode = (LassoNode*)
 
1715
                                                        lasso_misc_text_node_new_with_xml_node(t);
 
1716
                                        }
 
1717
                                        lasso_list_add_new_gobject(*list, subnode);
 
1718
                                }
 
1719
                        }
 
1720
                } else if (snippet_any) {
 
1721
                        g_assert_not_reached();
 
1722
                } else {
 
1723
                        for (; t; t = t->next) {
 
1724
                                if (t->type == XML_ELEMENT_NODE) {
 
1725
                                        critical("lasso_node_impl_init_from_xml: Cannot match "
 
1726
                                                        "element {%s}%s with a snippet of "
 
1727
                                                        "class %s",
 
1728
                                                        t->ns ?  t->ns->href : NULL, t->name,
 
1729
                                                        g_type_name(G_TYPE_FROM_INSTANCE(node)));
 
1730
                                        rc = 1;
 
1731
                                        goto cleanup;
 
1732
                                }
 
1733
                        }
 
1734
                }
 
1735
        }
 
1736
 
1549
1737
        /* Collect namespaces on the current node */
1550
1738
        if (snippet_collect_namespaces) {
1551
 
                void *value = G_STRUCT_MEMBER_P(node, snippet_collect_namespaces->offset);
 
1739
                void *value = SNIPPET_STRUCT_MEMBER_P(node, g_type_collect_namespaces,
 
1740
                                snippet_collect_namespaces);
1552
1741
                _lasso_node_collect_namespaces(value, xmlnode);
1553
1742
        }
1554
1743
 
1555
1744
        /* Collect signature parameters */
1556
1745
        {
1557
 
                        LassoSignatureMethod method;
1558
 
                        LassoSignatureType type;
 
1746
                        LassoSignatureMethod method = 0;
1559
1747
                        xmlChar *private_key = NULL;
1560
1748
                        xmlChar *private_key_password = NULL;
1561
1749
                        xmlChar *certificate = NULL;
 
1750
                        LassoSignatureContext signature_context = LASSO_SIGNATURE_CONTEXT_NONE;
1562
1751
 
1563
1752
                while (snippet_signature) {
1564
1753
                        int what;
1573
1762
                                        LASSO_SIGNATURE_TYPE_LAST))
1574
1763
                                break;
1575
1764
                        type = what;
1576
 
                        private_key = xmlGetNsProp(xmlnode, LASSO_PRIVATE_KEY_PASSWORD_ATTRIBUTE,
 
1765
                        private_key_password = xmlGetNsProp(xmlnode, LASSO_PRIVATE_KEY_PASSWORD_ATTRIBUTE,
1577
1766
                                BAD_CAST LASSO_LIB_HREF);
1578
1767
                        if (! private_key)
1579
1768
                                break;
1581
1770
                                LASSO_LIB_HREF);
1582
1771
                        certificate = xmlGetNsProp(xmlnode, LASSO_CERTIFICATE_ATTRIBUTE, BAD_CAST
1583
1772
                                LASSO_LIB_HREF);
1584
 
                        lasso_node_set_signature(node, type,
1585
 
                                method, (char*) private_key, (char*) private_key_password, (char*) certificate);
 
1773
 
 
1774
                        signature_context.signature_method = method;
 
1775
                        signature_context.signature_key = lasso_xmlsec_load_private_key((char*) private_key,
 
1776
                                        (char*) private_key_password, method, (char*) certificate);
 
1777
                        lasso_node_set_signature(node, signature_context);
 
1778
                        break;
1586
1779
                }
1587
1780
                lasso_release_xml_string(private_key);
1588
1781
                lasso_release_xml_string(private_key_password);
1589
1782
                lasso_release_xml_string(certificate);
1590
1783
        }
1591
 
 
1592
 
        /* Collect other children */
1593
 
        if (unknown_nodes && snippet_any) {
1594
 
                xmlNode *t = unknown_nodes->data;
1595
 
                void *tmp;
1596
 
                value = G_STRUCT_MEMBER_P(node, snippet_any->offset);
1597
 
                tmp = lasso_node_new_from_xmlNode_with_type(t, snippet_any->class_name);
1598
 
                (*(char**)value) = tmp;
1599
 
        }
1600
 
 
1601
 
        /* Collect other attributes */
1602
 
        if (snippet_any_attribute) {
1603
 
                GHashTable **any_attribute;
1604
 
                GSList *tmp_attr;
1605
 
                xmlAttr *node_attr;
1606
 
 
1607
 
 
1608
 
                any_attribute = G_STRUCT_MEMBER_P(node, snippet_any_attribute->offset);
1609
 
                if (*any_attribute == NULL) {
1610
 
                        *any_attribute = g_hash_table_new_full(
1611
 
                                        g_str_hash, g_str_equal, g_free, g_free);
1612
 
                }
1613
 
 
1614
 
                for (node_attr = xmlnode->properties; node_attr; node_attr = node_attr->next) {
1615
 
                        xmlChar *attr_name = (xmlChar*)node_attr->name;
1616
 
                        gboolean known_attr = FALSE;
1617
 
                        for (tmp_attr = known_attributes; tmp_attr;
1618
 
                                        tmp_attr = g_slist_next(tmp_attr)) {
1619
 
                                if (strcmp(tmp_attr->data, (char*)attr_name) == 0) {
1620
 
                                        known_attr = TRUE;
1621
 
                                        break;
1622
 
                                }
1623
 
                        }
1624
 
                        if (known_attr == FALSE) {
1625
 
                                xmlChar *tmp = xmlGetProp(xmlnode, attr_name);
1626
 
                                g_hash_table_insert(*any_attribute,
1627
 
                                                g_strdup((char*)attr_name), g_strdup((char*)tmp));
1628
 
                                xmlFree(tmp);
1629
 
                        }
1630
 
                }
1631
 
 
1632
 
        }
1633
 
 
1634
 
        if (unknown_nodes) {
1635
 
                g_slist_free(unknown_nodes);
1636
 
        }
1637
 
 
1638
 
        if (known_attributes) {
1639
 
                g_slist_free(known_attributes);
1640
 
        }
1641
 
 
1642
 
        return 0;
 
1784
cleanup:
 
1785
        lasso_release_slist(class_list);
 
1786
        return rc;
1643
1787
}
1644
1788
#undef trace_snippet
1645
1789
 
1664
1808
               }
1665
1809
               klass = g_type_class_peek_parent(klass);
1666
1810
       }
1667
 
       lasso_node_set_signature(node, LASSO_SIGNATURE_TYPE_NONE, LASSO_SIGNATURE_METHOD_RSA_SHA1,
1668
 
                        NULL, NULL, NULL);
 
1811
       lasso_node_set_signature(node, LASSO_SIGNATURE_CONTEXT_NONE);
1669
1812
}
1670
1813
 
1671
1814
/*****************************************************************************/
1699
1842
lasso_node_impl_get_xmlNode(LassoNode *node, gboolean lasso_dump)
1700
1843
{
1701
1844
        LassoNodeClass *class = LASSO_NODE_GET_CLASS(node);
 
1845
        LassoNodeClass *version_class = NULL;
1702
1846
        xmlNode *xmlnode;
1703
 
        xmlNs *ns;
1704
 
        GList *list_ns = NULL, *list_classes = NULL, *t;
 
1847
        xmlNs *ns = NULL;
 
1848
        GSList *list_classes = NULL, *iter_classes = NULL;
1705
1849
        LassoNode *value_node;
1706
1850
        struct XmlSnippet *version_snippet;
1707
1851
        struct _CustomElement *custom_element;
1708
 
 
1709
 
        if (class->node_data == NULL)
1710
 
                return NULL;
1711
 
 
1712
 
        xmlnode = xmlNewNode(NULL, (xmlChar*)class->node_data->node_name);
 
1852
        LassoNodeClass *xsi_sub_type_data_class = NULL;
 
1853
        LassoNodeClass *node_name_class = class;
 
1854
 
 
1855
        while (node_name_class->node_data->xsi_sub_type) {
 
1856
                node_name_class= g_type_class_peek_parent(node_name_class);
 
1857
        }
 
1858
        if (node_name_class != class) {
 
1859
                xsi_sub_type_data_class = class;
 
1860
        }
 
1861
        g_assert(node_name_class && node_name_class->node_data &&
 
1862
                        node_name_class->node_data->node_name);
 
1863
 
 
1864
        /* Create node in its namespace */
 
1865
        xmlnode = xmlNewNode(NULL, (xmlChar*)node_name_class->node_data->node_name);
 
1866
        if (node_name_class->node_data->ns) {
 
1867
                ns = get_or_define_ns(xmlnode, node_name_class->node_data->ns->href,
 
1868
                                node_name_class->node_data->ns->prefix);
 
1869
                xmlSetNs(xmlnode, ns);
 
1870
        }
 
1871
        /* If subtype, set an xsi:type attribute */
 
1872
        if (xsi_sub_type_data_class) {
 
1873
                set_xsi_type(xmlnode,
 
1874
                                xsi_sub_type_data_class->node_data->ns->prefix,
 
1875
                                xsi_sub_type_data_class->node_data->ns->href,
 
1876
                                BAD_CAST xsi_sub_type_data_class->node_data->node_name);
 
1877
        }
1713
1878
        custom_element = _lasso_node_get_custom_element(node);
1714
 
        /* collect namespaces in the order of ancestor classes, nearer first */
1715
 
        while (class && LASSO_IS_NODE_CLASS(class) && class->node_data) {
1716
 
                if (class->node_data->ns && (! custom_element || ! custom_element->href || class != LASSO_NODE_GET_CLASS(node)))
1717
 
                        list_ns = g_list_append(list_ns, class->node_data->ns);
1718
 
                list_classes = g_list_append(list_classes, class);
 
1879
 
 
1880
        /* collect all classes in reverse order */
 
1881
        while (class && LASSO_IS_NODE_CLASS(class)) {
 
1882
                if (class->node_data && class->node_data->snippets)
 
1883
                        list_classes = g_slist_prepend(list_classes, class);
1719
1884
                class = g_type_class_peek_parent(class);
1720
1885
        }
1721
1886
 
1722
 
        /* create the namespaces */
1723
 
        t = g_list_first(list_ns);
1724
 
        while (t) {
1725
 
                ns = t->data;
1726
 
                xmlNewNs(xmlnode, ns->href, ns->prefix);
1727
 
                t = g_list_next(t);
1728
 
        }
1729
 
        lasso_release_list(list_ns);
1730
 
        /* first NS defined is the namespace of the element */
1731
 
        xmlSetNs(xmlnode, xmlnode->nsDef);
1732
 
 
1733
1887
        /* set a custom namespace if one is found */
1734
1888
        if (custom_element != NULL) {
1735
1889
                if (custom_element->href) {
1769
1923
        }
1770
1924
 
1771
1925
 
1772
 
        t = g_list_last(list_classes);
1773
 
        while (t) {
1774
 
                class = t->data;
1775
 
                lasso_node_build_xmlNode_from_snippets(node, xmlnode,
1776
 
                                class->node_data->snippets, lasso_dump);
1777
 
                t = g_list_previous(t);
 
1926
        for (iter_classes = list_classes; iter_classes; iter_classes = g_slist_next(iter_classes)) {
 
1927
                class = iter_classes->data;
 
1928
                lasso_node_build_xmlNode_from_snippets(node,
 
1929
                                (LassoNodeClass*)class, xmlnode,
 
1930
                                class->node_data->snippets,
 
1931
                                lasso_dump);
1778
1932
        }
1779
 
        lasso_release_list(list_classes);
1780
1933
 
1781
1934
        xmlCleanNs(xmlnode);
1782
1935
 
1783
1936
        /* backward compatibility with Liberty ID-FF 1.1; */
1784
 
        if (find_path(node, "MajorVersion", &value_node, &version_snippet) == TRUE) {
 
1937
        if (find_path(node, "MajorVersion", &value_node, &version_class, &version_snippet) == TRUE) {
1785
1938
                int *value;
1786
1939
                int major_version, minor_version;
1787
1940
 
1788
 
                value = G_STRUCT_MEMBER_P(value_node, version_snippet->offset);
 
1941
                value = SNIPPET_STRUCT_MEMBER_P(value_node, G_TYPE_FROM_CLASS(version_class),
 
1942
                                version_snippet);
1789
1943
                major_version = *value;
1790
1944
 
1791
 
                find_path(node, "MinorVersion", &value_node, &version_snippet);
1792
 
                value = G_STRUCT_MEMBER_P(value_node, version_snippet->offset);
 
1945
                find_path(node, "MinorVersion", &value_node, &version_class, &version_snippet);
 
1946
                value = SNIPPET_STRUCT_MEMBER_P(value_node, G_TYPE_FROM_CLASS(version_class),
 
1947
                                version_snippet);
1793
1948
                minor_version = *value;
1794
1949
 
1795
1950
                if (strcmp((char*)xmlnode->ns->href, LASSO_LIB_HREF) == 0) {
1801
1956
                }
1802
1957
        }
1803
1958
 
1804
 
        /* store signature parameters */
1805
 
        if (lasso_dump)
1806
 
        {
1807
 
                LassoSignatureType type;
1808
 
                LassoSignatureMethod method;
1809
 
                const char *private_key = NULL;
1810
 
                const char *private_key_password = NULL;
1811
 
                const char *certificate = NULL;
1812
 
                xmlNsPtr ns = NULL;
1813
 
                char buffer[64] = { 0 };
1814
 
 
1815
 
                lasso_node_get_signature(node, &type, &method, (char **)&private_key,
1816
 
                                (char **)&private_key_password,
1817
 
                                (char **)&certificate);
1818
 
                if (private_key) {
1819
 
                        ns = get_or_define_ns(xmlnode, BAD_CAST LASSO_LASSO_HREF);
1820
 
                        sprintf(buffer, "%u", type);
1821
 
                        xmlSetNsProp(xmlnode, ns, LASSO_SIGNATURE_TYPE_ATTRIBUTE, BAD_CAST buffer);
1822
 
                        sprintf(buffer, "%u", method);
1823
 
                        xmlSetNsProp(xmlnode, ns, LASSO_SIGNATURE_METHOD_ATTRIBUTE, BAD_CAST buffer);
1824
 
                        xmlSetNsProp(xmlnode, ns, LASSO_PRIVATE_KEY_ATTRIBUTE, BAD_CAST private_key);
1825
 
                        if (private_key_password) {
1826
 
                                xmlSetNsProp(xmlnode, ns, LASSO_PRIVATE_KEY_PASSWORD_ATTRIBUTE, BAD_CAST private_key_password);
1827
 
                        }
1828
 
                        if (certificate) {
1829
 
                                xmlSetNsProp(xmlnode, ns, LASSO_CERTIFICATE_ATTRIBUTE, BAD_CAST certificate);
1830
 
                        }
1831
 
                }
1832
 
        }
1833
 
 
1834
 
 
 
1959
        g_slist_free(list_classes);
1835
1960
        return xmlnode;
1836
1961
}
1837
1962
 
1856
1981
 
1857
1982
        while (class && LASSO_IS_NODE_CLASS(class) && class->node_data) {
1858
1983
                for (snippet = class->node_data->snippets; snippet && snippet->name; snippet++) {
1859
 
                        void **value = G_STRUCT_MEMBER_P(object, snippet->offset);
 
1984
                        void **value = SNIPPET_STRUCT_MEMBER_P(object, G_TYPE_FROM_CLASS(class), snippet);
1860
1985
                        type = snippet->type & 0xff;
1861
1986
 
 
1987
                        if (! snippet->offset && ! (snippet->type & SNIPPET_PRIVATE))
 
1988
                                continue;
1862
1989
                        if (snippet->type & SNIPPET_BOOLEAN)
1863
1990
                                continue;
1864
1991
                        if (snippet->type & SNIPPET_INTEGER)
1873
2000
                        }
1874
2001
                        switch (type) {
1875
2002
                                case SNIPPET_NODE:
1876
 
                                case SNIPPET_NAME_IDENTIFIER:
1877
2003
                                case SNIPPET_NODE_IN_CHILD:
1878
2004
                                        lasso_release_gobject(*value);
1879
2005
                                        break;
2107
2233
                prefix = "Samlp2";
2108
2234
        else if (strcmp((char*)href, LASSO_SOAP_ENV_HREF) == 0)
2109
2235
                prefix = "Soap";
 
2236
        else if (strcmp((char*)href, LASSO_DS_HREF) == 0)
 
2237
                prefix = "Ds";
2110
2238
#ifdef LASSO_WSF_ENABLED
2111
2239
        else if (strcmp((char*)href, LASSO_SOAP_BINDING_HREF) == 0)
2112
2240
                prefix = "SoapBinding";
2114
2242
                prefix = "SoapBindingExt";
2115
2243
        else if (strcmp((char*)href, LASSO_DISCO_HREF) == 0)
2116
2244
                prefix = "Disco";
2117
 
        else if (strcmp((char*)href, LASSO_DS_HREF) == 0)
2118
 
                prefix = "Ds";
2119
2245
        else if (strcmp((char*)href, LASSO_IS_HREF) == 0)
2120
2246
                prefix = "Is";
2121
2247
        else if (strcmp((char*)href, LASSO_SA_HREF) == 0)
2219
2345
}
2220
2346
 
2221
2347
/**
2222
 
 * lasso_node_new_from_xmlNode:
 
2348
 * _lasso_node_new_from_xmlNode:
2223
2349
 * @node: an xmlNode
2224
2350
 *
2225
2351
 * Builds a new #LassoNode from an xmlNode.
2226
2352
 *
2227
2353
 * Return value: a new node
2228
2354
 **/
2229
 
LassoNode*
2230
 
lasso_node_new_from_xmlNode(xmlNode *xmlnode)
 
2355
static LassoNode*
 
2356
_lasso_node_new_from_xmlNode(xmlNode *xmlnode)
2231
2357
{
2232
2358
        char *typename = NULL;
2233
2359
        xmlChar *xsitype = NULL;
2234
2360
        LassoNode *node = NULL;
2235
2361
        gboolean fromXsi = FALSE;
2236
2362
 
2237
 
        if (xmlnode == NULL || xmlnode->ns == NULL) {
2238
 
                message(G_LOG_LEVEL_CRITICAL, "Unable to build a LassoNode from a xmlNode");
2239
 
                return NULL;
2240
 
        }
2241
 
 
2242
2363
        xsitype = xmlGetNsProp(xmlnode, (xmlChar*)"type", (xmlChar*)LASSO_XSI_HREF);
2243
2364
        if (xsitype) {
2244
2365
                xmlChar *xmlPrefix, *separator;
2272
2393
                        fromXsi = TRUE;
2273
2394
        }
2274
2395
 
2275
 
        if (typename == NULL) {
 
2396
        if (typename == NULL && xmlnode->ns && xmlnode->ns->href) {
2276
2397
                typename = _type_name_from_href_and_nodename ((char*)xmlnode->ns->href, (char*)xmlnode->name);
2277
2398
        }
2278
2399
 
2310
2431
        return node;
2311
2432
}
2312
2433
 
 
2434
/**
 
2435
 * lasso_node_new_from_xmlNode:
 
2436
 * @node: an xmlNode
 
2437
 *
 
2438
 * Builds a new #LassoNode from an xmlNode.
 
2439
 *
 
2440
 * Return value: a new node
 
2441
 **/
 
2442
LassoNode*
 
2443
lasso_node_new_from_xmlNode(xmlNode *xmlnode)
 
2444
{
 
2445
        if (xmlnode == NULL || xmlnode->ns == NULL) {
 
2446
                message(G_LOG_LEVEL_CRITICAL, "Unable to build a LassoNode from a xmlNode");
 
2447
                return NULL;
 
2448
        }
 
2449
        return _lasso_node_new_from_xmlNode(xmlnode);
 
2450
}
2313
2451
 
2314
2452
static LassoNode*
2315
2453
lasso_node_new_from_xmlNode_with_type(xmlNode *xmlnode, char *typename)
2319
2457
        int rc = 0;
2320
2458
 
2321
2459
        if (typename == NULL)
2322
 
                return lasso_node_new_from_xmlNode(xmlnode); /* will auto-detect */
 
2460
                return _lasso_node_new_from_xmlNode(xmlnode); /* will auto-detect */
2323
2461
 
2324
2462
        gtype = g_type_from_name(typename);
2325
2463
        if (gtype == 0)
2531
2669
        klass->node_data->ns = xmlNewNs(NULL, (xmlChar*)href, (xmlChar*)prefix);
2532
2670
}
2533
2671
 
2534
 
static xmlNs *
2535
 
get_or_define_ns(xmlNode *xmlnode, xmlChar *ns_uri) {
2536
 
        xmlNs *ns;
2537
 
        char prefix[10];
2538
 
        int i = 1;
2539
 
 
2540
 
        ns = xmlSearchNsByHref(NULL, xmlnode, ns_uri);
2541
 
        if (ns)
2542
 
                return ns;
2543
 
        do {
2544
 
                sprintf(prefix, "ns%u", i);
2545
 
                i++;
2546
 
                ns = xmlSearchNs(NULL, xmlnode, BAD_CAST prefix);
2547
 
        } while (ns);
2548
 
        return xmlNewNs(xmlnode, ns_uri, BAD_CAST prefix);
2549
 
}
2550
 
 
2551
2672
static void
2552
2673
snippet_dump_any(gchar *key, gchar *value, xmlNode *xmlnode)
2553
2674
{
2564
2685
                        message(G_LOG_LEVEL_WARNING, "Invalid attribute name: %s", key);
2565
2686
                        return;
2566
2687
                }
2567
 
                ns_uri = strndup(key+1, end-(key+1));
2568
 
                ns = get_or_define_ns(xmlnode, BAD_CAST ns_uri);
2569
 
                xmlSetNsProp(xmlnode, ns, BAD_CAST key, BAD_CAST value);
 
2688
                ns_uri = g_strndup(key+1, end-(key+1));
 
2689
                ns = get_or_define_ns(xmlnode, BAD_CAST ns_uri, NULL);
 
2690
                xmlSetNsProp(xmlnode, ns, BAD_CAST &end[1], BAD_CAST value);
2570
2691
        } else {
2571
2692
                xmlSetProp(xmlnode, BAD_CAST key, BAD_CAST value);
2572
2693
        }
2573
2694
}
2574
2695
 
2575
2696
static void
2576
 
lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode,
 
2697
apply_snippet_ns(struct XmlSnippet *snippet, xmlNode *xmlnode)
 
2698
{
 
2699
        xmlNs *ns;
 
2700
 
 
2701
        if (! xmlnode)
 
2702
                return;
 
2703
        if (snippet->ns_uri) {
 
2704
                if (! xmlnode->ns || !lasso_strisequal((char*)xmlnode->ns->href, (char*)snippet->ns_uri)) {
 
2705
                        ns = get_or_define_ns(xmlnode, BAD_CAST snippet->ns_uri, BAD_CAST snippet->ns_name);
 
2706
                        xmlSetNs(xmlnode, ns);
 
2707
                }
 
2708
                /* If not a any snippet, apply given Name, what about xsi:type ? */
 
2709
        }
 
2710
        if (! (snippet->type & SNIPPET_ANY) && ! lasso_strisempty(snippet->name) &&
 
2711
                        lasso_strisnotequal((char*)xmlnode->name, (char*)snippet->name))
 
2712
                xmlNodeSetName(xmlnode, BAD_CAST snippet->name);
 
2713
}
 
2714
 
 
2715
static void
 
2716
lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, xmlNode *xmlnode,
2577
2717
                struct XmlSnippet *snippets, gboolean lasso_dump)
2578
2718
{
2579
2719
        struct XmlSnippet *snippet;
2580
2720
        SnippetType type;
 
2721
        GType g_type;
2581
2722
        xmlNode *t;
2582
 
        xmlNs *xmlns;
2583
2723
        GList *elem;
2584
2724
        struct XmlSnippet *snippet_any_attribute = NULL;
2585
2725
 
 
2726
        g_type = G_TYPE_FROM_CLASS(class);
 
2727
 
2586
2728
        for (snippet = snippets; snippet && snippet->name; snippet++) {
2587
 
                void *value = G_STRUCT_MEMBER(void*, node, snippet->offset);
2588
 
                char *str = value;
 
2729
                void *value;
 
2730
                char *str;
 
2731
 
 
2732
                if (! snippet->offset && ! (snippet->type & SNIPPET_PRIVATE)) {
 
2733
                        continue;
 
2734
                }
2589
2735
                type = snippet->type & 0xff;
2590
 
 
 
2736
                value = SNIPPET_STRUCT_MEMBER(void *, node, g_type, snippet);
 
2737
                str = value;
2591
2738
                if (lasso_dump == FALSE && snippet->type & SNIPPET_LASSO_DUMP)
2592
2739
                        continue;
2593
2740
 
2627
2774
                                {
2628
2775
                                        xmlNode *t2;
2629
2776
                                        t2 = lasso_node_get_xmlNode(LASSO_NODE(value), lasso_dump);
2630
 
                                        if (snippet->name && ! (snippet->type & SNIPPET_ANY)) {
2631
 
                                                xmlNodeSetName(t2, (xmlChar*)snippet->name);
2632
 
                                        }
 
2777
                                        apply_snippet_ns(snippet, t2);
2633
2778
                                        xmlAddChild(xmlnode, t2);
2634
2779
                                } break;
2635
2780
                        case SNIPPET_CONTENT:
2636
2781
                                xmlNewTextChild(xmlnode, NULL,
2637
2782
                                                (xmlChar*)snippet->name, (xmlChar*)str);
2638
2783
                                break;
2639
 
                        case SNIPPET_NAME_IDENTIFIER:
2640
 
                                xmlns = xmlNewNs(NULL, (xmlChar*)LASSO_LIB_HREF,
2641
 
                                                (xmlChar*)LASSO_LIB_PREFIX);
2642
 
                                t = xmlAddChild(xmlnode, lasso_node_get_xmlNode(
2643
 
                                                        LASSO_NODE(value), lasso_dump));
2644
 
                                xmlNodeSetName(t, (xmlChar*)snippet->name);
2645
 
                                xmlSetNs(t, xmlns);
2646
 
                                break;
2647
2784
                        case SNIPPET_NODE_IN_CHILD:
2648
2785
                                t = xmlNewTextChild(xmlnode, NULL, (xmlChar*)snippet->name, NULL);
2649
2786
                                xmlAddChild(t, lasso_node_get_xmlNode(
2655
2792
                                        xmlNode *subnode = lasso_node_get_xmlNode(
2656
2793
                                                        LASSO_NODE(elem->data), lasso_dump);
2657
2794
                                        if (subnode) {
2658
 
                                                if (snippet->name && snippet->name[0]) {
2659
 
                                                        xmlNodeSetName(subnode,
2660
 
                                                                        (xmlChar*)snippet->name);
2661
 
                                                }
 
2795
                                                apply_snippet_ns(snippet, subnode);
2662
2796
                                                xmlAddChild(xmlnode, subnode);
2663
2797
                                        }
2664
2798
                                        elem = g_list_next(elem);
2669
2803
                                 * no attrs, just content) */
2670
2804
                                elem = (GList *)value;
2671
2805
                                while (elem) {
2672
 
                                        xmlNs *content_ns = NULL;
2673
 
                                        if (snippet->ns_name) {
2674
 
                                                content_ns = xmlNewNs(xmlnode,
2675
 
                                                                (const xmlChar*)snippet->ns_uri,
2676
 
                                                                (const xmlChar*)snippet->ns_name);
2677
 
                                        }
2678
 
                                        xmlNewTextChild(xmlnode, content_ns,
 
2806
                                        xmlNode *subnode;
 
2807
                                        subnode = xmlNewTextChild(xmlnode, NULL,
2679
2808
                                                        (xmlChar*)snippet->name,
2680
2809
                                                        (xmlChar*)(elem->data));
 
2810
                                        apply_snippet_ns(snippet, subnode);
2681
2811
                                        elem = g_list_next(elem);
2682
2812
                                }
2683
2813
                                break;
2705
2835
                        case SNIPPET_ALLOW_TEXT:
2706
2836
                        case SNIPPET_ANY:
2707
2837
                        case SNIPPET_KEEP_XMLNODE:
 
2838
                        case SNIPPET_PRIVATE:
 
2839
                        case SNIPPET_MANDATORY:
 
2840
                        case SNIPPET_UNUSED1:
2708
2841
                                g_assert_not_reached();
2709
2842
                }
2710
2843
                if (snippet->type & SNIPPET_INTEGER)
2712
2845
        }
2713
2846
 
2714
2847
        if (snippet_any_attribute) {
2715
 
                GHashTable *value = G_STRUCT_MEMBER(GHashTable*, node,
2716
 
                                snippet_any_attribute->offset);
 
2848
                GHashTable *value = SNIPPET_STRUCT_MEMBER(GHashTable *, node, g_type,
 
2849
                                snippet_any_attribute);
2717
2850
                if (value) {
2718
2851
                        g_hash_table_foreach(value, (GHFunc)snippet_dump_any, xmlnode);
2719
2852
                }
2720
2853
        }
2721
2854
}
2722
2855
 
2723
 
static
2724
 
void lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
 
2856
static void
 
2857
lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
2725
2858
                struct XmlSnippet *snippet_signature)
2726
2859
{
2727
 
        LassoNodeClass *klass = LASSO_NODE_GET_CLASS(node);
2728
 
        LassoSignatureType sign_type;
2729
 
        LassoSignatureMethod sign_method;
2730
 
        xmlNode *signature = NULL, *reference, *key_info, *t;
2731
 
        char *uri;
2732
 
        char *id;
2733
 
 
2734
 
        while (klass && LASSO_IS_NODE_CLASS(klass) && klass->node_data) {
2735
 
                if (klass->node_data->sign_type_offset)
2736
 
                        break;
2737
 
                klass = g_type_class_peek_parent(klass);
2738
 
        }
2739
 
 
2740
 
        if (klass->node_data->sign_type_offset == 0)
2741
 
                return;
2742
 
 
2743
 
        sign_type = G_STRUCT_MEMBER(
2744
 
                        LassoSignatureType, node,
2745
 
                        klass->node_data->sign_type_offset);
2746
 
        sign_method = G_STRUCT_MEMBER(
2747
 
                        LassoSignatureMethod, node,
2748
 
                        klass->node_data->sign_method_offset);
2749
 
 
2750
 
        if (sign_type == LASSO_SIGNATURE_TYPE_NONE)
2751
 
                return;
2752
 
 
2753
 
        if (sign_method == LASSO_SIGNATURE_METHOD_RSA_SHA1) {
2754
 
                signature = xmlSecTmplSignatureCreate(NULL,
2755
 
                                xmlSecTransformExclC14NId,
2756
 
                                xmlSecTransformRsaSha1Id, NULL);
2757
 
        } else {
2758
 
                signature = xmlSecTmplSignatureCreate(NULL,
2759
 
                                xmlSecTransformExclC14NId,
2760
 
                                xmlSecTransformDsaSha1Id, NULL);
2761
 
        }
2762
 
        /* XXX: get out if signature == NULL ? */
2763
 
        xmlAddChild(xmlnode, signature);
2764
 
 
2765
 
        id = G_STRUCT_MEMBER(char*, node, snippet_signature->offset);
2766
 
        uri = g_strdup_printf("#%s", id);
2767
 
        reference = xmlSecTmplSignatureAddReference(signature,
2768
 
                        xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
2769
 
        lasso_release(uri);
2770
 
 
2771
 
        /* add enveloped transform */
2772
 
        xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
2773
 
        /* add exclusive C14N transform */
2774
 
        xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
2775
 
 
2776
 
        if (sign_type == LASSO_SIGNATURE_TYPE_WITHX509) {
2777
 
                /* add <dsig:KeyInfo/> */
2778
 
                key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
2779
 
                t = xmlSecTmplKeyInfoAddX509Data(key_info);
2780
 
        }
 
2860
        LassoNodeClass *klass = NULL;
 
2861
        LassoNodeClassData *node_data = NULL;
 
2862
        LassoSignatureContext context;
 
2863
        char *id = NULL;
 
2864
 
 
2865
        node_data = lasso_legacy_get_signature_node_data(node, &klass);
 
2866
        if (! node_data)
 
2867
                return;
 
2868
 
 
2869
        if (node_data->sign_type_offset == 0)
 
2870
                return;
 
2871
 
 
2872
        context = lasso_node_get_signature(node);
 
2873
        if (! lasso_validate_signature_context(context))
 
2874
                if (lasso_legacy_extract_and_copy_signature_parameters(node, node_data))
 
2875
                        context = lasso_node_get_signature(node);
 
2876
 
 
2877
        if (snippet_signature->offset) {
 
2878
                id = SNIPPET_STRUCT_MEMBER(char *, node, G_TYPE_FROM_CLASS(klass), snippet_signature);
 
2879
        }
 
2880
 
 
2881
        lasso_xmlnode_add_saml2_signature_template(xmlnode, context, id);
2781
2882
}
2782
2883
 
2783
2884
static struct XmlSnippet*
2784
 
find_xml_snippet_by_name(LassoNode *node, char *name)
 
2885
find_xml_snippet_by_name(LassoNode *node, char *name, LassoNodeClass **class_p)
2785
2886
{
2786
2887
        LassoNodeClass *class;
2787
2888
        struct XmlSnippet *snippet;
2791
2892
                for (snippet = class->node_data->snippets;
2792
2893
                                snippet && snippet->name && strcmp(snippet->name, name) != 0;
2793
2894
                                snippet++) ;
2794
 
                if (snippet && snippet->name)
 
2895
                if (snippet && snippet->name) {
 
2896
                        *class_p = class;
2795
2897
                        return snippet;
 
2898
                }
2796
2899
                class = g_type_class_peek_parent(class);
2797
2900
        }
2798
 
 
 
2901
        *class_p = NULL;
2799
2902
        return NULL;
2800
2903
}
2801
2904
 
2802
2905
static gboolean
2803
 
find_path(LassoNode *node, char *path, LassoNode **value_node, struct XmlSnippet **snippet)
 
2906
find_path(LassoNode *node, char *path, LassoNode **value_node, LassoNodeClass **class_p, struct XmlSnippet **snippet)
2804
2907
{
2805
2908
        char *s, *t;
2806
2909
        struct XmlSnippet *tsnippet = NULL;
2807
2910
        LassoNode *tnode = node;
2808
2911
 
 
2912
        *class_p = NULL;
2809
2913
        s = path;
2810
2914
        while (s-1) {
2811
2915
                t = strchr(s, '/');
2812
2916
                if (t) *t = 0;
2813
 
                tsnippet = find_xml_snippet_by_name(tnode, s);
 
2917
                tsnippet = find_xml_snippet_by_name(tnode, s, class_p);
2814
2918
                if (t) {
2815
 
                        tnode = G_STRUCT_MEMBER(LassoNode*, tnode, tsnippet->offset);
 
2919
                        tnode = SNIPPET_STRUCT_MEMBER(LassoNode *, tnode, G_TYPE_FROM_CLASS(*class_p),
 
2920
                                        tsnippet);
2816
2921
                        if (tnode == NULL)
2817
2922
                                return FALSE;
2818
2923
                }
2833
2938
{
2834
2939
        struct XmlSnippet *snippet;
2835
2940
        LassoNode *value_node;
 
2941
        LassoNodeClass *class;
 
2942
        GType g_type;
2836
2943
 
2837
 
        if (find_path(node, path, &value_node, &snippet) != TRUE)
 
2944
        if (find_path(node, path, &value_node, &class, &snippet) != TRUE)
2838
2945
                return NULL;
 
2946
        g_type = G_TYPE_FROM_CLASS(class);
2839
2947
 
2840
2948
        *xml_snippet = *snippet;
2841
2949
 
2842
2950
        if (snippet->type & SNIPPET_BOOLEAN) {
2843
 
                gboolean v = G_STRUCT_MEMBER(gboolean, value_node, snippet->offset);
 
2951
                gboolean v = SNIPPET_STRUCT_MEMBER(gboolean, value_node, g_type, snippet);
2844
2952
                return v ? g_strdup("true") : g_strdup("false");
2845
2953
        } else if (snippet->type & SNIPPET_INTEGER) {
2846
 
                int v = G_STRUCT_MEMBER(int, value_node, snippet->offset);
 
2954
                int v = SNIPPET_STRUCT_MEMBER(int, value_node, g_type, snippet);
2847
2955
                return g_strdup_printf("%d", v);
2848
2956
        } else if (snippet->type == SNIPPET_NODE) {
2849
 
                LassoNode *value = G_STRUCT_MEMBER(LassoNode*, value_node, snippet->offset);
 
2957
                LassoNode *value = SNIPPET_STRUCT_MEMBER(LassoNode *, value_node, g_type, snippet);
2850
2958
                return lasso_node_build_query(value);
2851
2959
        } else if (snippet->type == SNIPPET_EXTENSION) {
2852
2960
                /* convert all of the <lib:Extension> into a string, already
2853
2961
                 * escaped for URI usage */
2854
 
                GList *value = G_STRUCT_MEMBER(GList*, value_node, snippet->offset);
 
2962
                GList *value = SNIPPET_STRUCT_MEMBER(GList *, value_node, g_type, snippet);
2855
2963
                xmlChar *s, *s2;
2856
2964
                GString *result = g_string_new("");
2857
2965
                while (value) {
2902
3010
                return g_string_free(result, FALSE);
2903
3011
        } else if (snippet->type == SNIPPET_LIST_CONTENT) {
2904
3012
                /* not clear in spec; concat values with spaces */
2905
 
                GList *value = G_STRUCT_MEMBER(GList*, value_node, snippet->offset);
 
3013
                GList *value = SNIPPET_STRUCT_MEMBER(GList *, value_node, g_type, snippet);
2906
3014
                GString *result = g_string_new("");
2907
3015
                while (value) {
2908
3016
                        result = g_string_append(result, (char*)value->data);
2916
3024
                }
2917
3025
                return g_string_free(result, FALSE);
2918
3026
        } else {
2919
 
                char *value = G_STRUCT_MEMBER(char*, value_node, snippet->offset);
 
3027
                char *value = SNIPPET_STRUCT_MEMBER(char *, value_node, g_type, snippet);
2920
3028
                if (value == NULL) return NULL;
2921
3029
                return g_strdup(value);
2922
3030
        }
2928
3036
{
2929
3037
        struct XmlSnippet *snippet;
2930
3038
        LassoNode *value_node;
 
3039
        LassoNodeClass *class;
 
3040
        GType g_type;
2931
3041
        void *value;
2932
3042
 
2933
 
        if (find_path(node, path, &value_node, &snippet) != TRUE)
 
3043
        if (find_path(node, path, &value_node, &class, &snippet) != TRUE)
2934
3044
                return FALSE;
 
3045
        g_type = G_TYPE_FROM_CLASS(class);
2935
3046
 
2936
 
        value = G_STRUCT_MEMBER_P(value_node, snippet->offset);
 
3047
        value = SNIPPET_STRUCT_MEMBER_P(value_node, g_type, snippet);
2937
3048
 
2938
3049
        if (snippet->type & SNIPPET_INTEGER) {
2939
3050
                int val = atoi(query_value);
3067
3178
                         * Extension; build it */
3068
3179
                        struct XmlSnippet *extension_snippet;
3069
3180
                        LassoNode *value_node;
 
3181
                        LassoNodeClass *class;
3070
3182
                        GList **value;
3071
3183
                        xmlNode *xmlnode, *xmlchild;
3072
 
                        if (find_path(node, "Extension", &value_node, &extension_snippet) == TRUE) {
3073
 
                                value = G_STRUCT_MEMBER_P(value_node, extension_snippet->offset);
 
3184
                        if (find_path(node, "Extension", &value_node, &class, &extension_snippet) == TRUE) {
 
3185
                                GType g_type = G_TYPE_FROM_CLASS(class);
 
3186
                                value = SNIPPET_STRUCT_MEMBER_P(value_node, g_type,
 
3187
                                                extension_snippet);
3074
3188
                                if (*value) {
3075
3189
                                        xmlnode = (*value)->data;
3076
3190
                                } else {
3137
3251
static void
3138
3252
xmlDeclareNs(xmlNode *root_node, xmlNode *node)
3139
3253
{
3140
 
        xmlNs *ns, *ns2;
 
3254
        xmlNs *ns;
3141
3255
        xmlNode *t;
3142
3256
 
3143
3257
        if (strcmp((char*)node->name, "Signature") == 0)
3145
3259
 
3146
3260
        for (ns = node->nsDef; ns; ns = ns->next) {
3147
3261
                if (ns->prefix && strcmp((char*)ns->prefix, "xsi") != 0) {
3148
 
                        ns2 = xmlNewNs(root_node, ns->href, ns->prefix);
 
3262
                        xmlNewNs(root_node, ns->href, ns->prefix);
3149
3263
                }
3150
3264
        }
3151
3265
        for (t = node->children; t; t = t->next) {
3279
3393
        if (cur) {
3280
3394
                if (original_xmlnode) {
3281
3395
                        xmlNode *children = xmlCopyNodeList(original_xmlnode->children);
3282
 
                        xmlCopyPropList(cur, original_xmlnode->properties);
 
3396
                        xmlAttr *attrs = xmlCopyPropList(cur, original_xmlnode->properties);
 
3397
                        if (cur->properties == NULL) {
 
3398
                                cur->properties = attrs;
 
3399
                        } else {
 
3400
                                xmlAttr *it = cur->properties;
 
3401
                                while (it->next) {
 
3402
                                        it = it->next;
 
3403
                                }
 
3404
                                it->next = attrs;
 
3405
                        }
3283
3406
                        xmlAddChildList(cur, children);
3284
3407
                        return cur;
3285
3408
                } else {
3343
3466
                return (const char*)klass->node_data->ns->href;
3344
3467
        return NULL;
3345
3468
}
 
3469
 
 
3470
 
 
3471
/**
 
3472
 * lasso_node_export_to_saml2_query:
 
3473
 * @node: the #LassoNode object to pass as a query
 
3474
 * @param_name: the key value for the query string parameter
 
3475
 * @url:(allow-none): an optional URL to prepend to the query string
 
3476
 * @key:(allow-none): a #LassoKey object
 
3477
 *
 
3478
 * Export a node as signed query string, the node must support serialization as a query.
 
3479
 *
 
3480
 * Return value: an HTTP URL or query string if successful, NULL otherwise.
 
3481
 */
 
3482
char*
 
3483
lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const char *url,
 
3484
                LassoKey *key)
 
3485
{
 
3486
        char *value = NULL, *query = NULL, *signed_query = NULL, *result = NULL;
 
3487
        xmlChar *encoded_param = NULL;
 
3488
 
 
3489
        value = lasso_node_build_deflated_query(node);
 
3490
        if (! value)
 
3491
                goto cleanup;
 
3492
        encoded_param = xmlURIEscapeStr(BAD_CAST param_name, NULL);
 
3493
        if (! encoded_param)
 
3494
                goto cleanup;
 
3495
        query = g_strdup_printf("%s=%s", encoded_param, value);
 
3496
        if (! query)
 
3497
                goto cleanup;
 
3498
        if (LASSO_IS_KEY(key)) {
 
3499
                signed_query = lasso_key_query_sign(key, query);
 
3500
        } else {
 
3501
                lasso_transfer_string(signed_query, query);
 
3502
        }
 
3503
        if (! signed_query)
 
3504
                goto cleanup;
 
3505
        if (url) {
 
3506
                result = lasso_concat_url_query(url, signed_query);
 
3507
        } else {
 
3508
                lasso_transfer_string(result, signed_query);
 
3509
        }
 
3510
 
 
3511
cleanup:
 
3512
        lasso_release_string(value);
 
3513
        lasso_release_xml_string(encoded_param);
 
3514
        lasso_release_string(query);
 
3515
        lasso_release_string(signed_query);
 
3516
        return result;
 
3517
}
 
3518
 
 
3519
/**
 
3520
 * lasso_node_new_from_saml2_query:
 
3521
 * @url_or_qs: an URL containing a query string or a query string only
 
3522
 * @param_name: the key value for the query string parameter to extract as a #LassoNode.
 
3523
 * @key:(allow-none): a #LassoKey object
 
3524
 *
 
3525
 * Verify the signature on a SAML-2 encoded query string and return the encoded node.
 
3526
 *
 
3527
 * Return value: a newly build #LassoNode if successful, NULL otherwise.
 
3528
 */
 
3529
LassoNode*
 
3530
lasso_node_new_from_saml2_query(const char *url_or_qs, const char *param_name, LassoKey *key)
 
3531
{
 
3532
        char *needle = NULL;
 
3533
        LassoNode *result = NULL;
 
3534
 
 
3535
        if (! url_or_qs || ! param_name)
 
3536
                return NULL;
 
3537
        needle = strchr(url_or_qs, '?');
 
3538
        if (needle) {
 
3539
                url_or_qs = (const char*)(needle+1);
 
3540
        }
 
3541
        if (key) {
 
3542
                goto_cleanup_if_fail(lasso_key_query_verify(key, url_or_qs) == 0);
 
3543
        }
 
3544
cleanup:
 
3545
        return result;
 
3546
}