1 /* $Id$
2  *
3  * Lasso - A free implementation of the Liberty Alliance specifications.
4  *
5  * Copyright (C) 2004-2007 Entr'ouvert
6  * http://lasso.entrouvert.org
7  *
8  * Authors: See AUTHORS file in top-level directory.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef __LASSO_XML_PRIVATE_H__
25 #define __LASSO_XML_PRIVATE_H__
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif /* __cplusplus */
30 
31 #include "xml.h"
32 #include "xml_enc.h"
33 #include <xmlsec/crypto.h>
34 #include <xmlsec/xmlenc.h>
35 #include "saml-2.0/saml2_encrypted_element.h"
36 #include "../utils.h"
37 
38 typedef enum {
39 	SNIPPET_NODE,
40 	SNIPPET_CONTENT,
41 	SNIPPET_TEXT_CHILD,
42 	SNIPPET_UNUSED1,
43 	SNIPPET_ATTRIBUTE,
44 	SNIPPET_NODE_IN_CHILD,
45 	SNIPPET_LIST_NODES,
46 	SNIPPET_LIST_CONTENT,
47 	SNIPPET_EXTENSION,
48 	SNIPPET_SIGNATURE,
49 	SNIPPET_LIST_XMLNODES,
50 	SNIPPET_XMLNODE,
51 	SNIPPET_COLLECT_NAMESPACES,
52 	SNIPPET_JUMP_OFFSET_SIGN = 1 << 19,
53 	SNIPPET_JUMP_OFFSET_SHIFT = 15,
54 	SNIPPET_JUMP_OFFSET_MASK = 0x0f << SNIPPET_JUMP_OFFSET_SHIFT,
55 	SNIPPET_JUMP_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT,
56 	SNIPPET_JUMP_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT,
57 	SNIPPET_JUMP_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT,
58 	SNIPPET_JUMP_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT,
59 	SNIPPET_JUMP_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT,
60 	SNIPPET_JUMP_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT,
61 	SNIPPET_JUMP_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT,
62 	SNIPPET_BACK_1 = 1 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
63 	SNIPPET_BACK_2 = 2 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
64 	SNIPPET_BACK_3 = 3 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
65 	SNIPPET_BACK_4 = 4 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
66 	SNIPPET_BACK_5 = 5 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
67 	SNIPPET_BACK_6 = 6 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
68 	SNIPPET_BACK_7 = 7 << SNIPPET_JUMP_OFFSET_SHIFT | SNIPPET_JUMP_OFFSET_SIGN,
69 	/* transformers for content transformation */
70 	SNIPPET_STRING  = 1 << 0, /* default, can be omitted */
71 	SNIPPET_BOOLEAN = 1 << 20,
72 	SNIPPET_INTEGER = 1 << 21,
73 	SNIPPET_LASSO_DUMP = 1 << 22,
74 	SNIPPET_OPTIONAL = 1 << 23, /* optional, ignored if 0 */
75 	SNIPPET_OPTIONAL_NEG = 1 << 24, /* optional, ignored if -1 */
76 	SNIPPET_ANY = 1 << 25, /* ##any node */
77 	SNIPPET_ALLOW_TEXT = 1 << 26, /* allow text childs in list of nodes */
78 	SNIPPET_KEEP_XMLNODE = 1 << 27, /* force keep xmlNode */
79 	SNIPPET_PRIVATE = 1 << 28, /* means that the offset is relative to a private extension */
80 	SNIPPET_MANDATORY = 1 << 29, /* means that the element cardinality is at least 1 */
81 	SNIPPET_JUMP_ON_MATCH = 1 << 30,
82 	SNIPPET_JUMP_ON_MISS = 1 << 31,
83 	SNIPPET_JUMP = SNIPPET_JUMP_ON_MISS | SNIPPET_JUMP_ON_MATCH,
84 
85 } SnippetType;
86 
87 #define SNIPPET_JUMP_OFFSET(type) ((type & SNIPPET_JUMP_OFFSET_SIGN) ? \
88 		                      (-(type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT) \
89 		                    : ((type & SNIPPET_JUMP_OFFSET_MASK) >> SNIPPET_JUMP_OFFSET_SHIFT))
90 
91 typedef enum {
92 	NO_OPTION = 0,
93 	NO_SINGLE_REFERENCE = 1 /* SAML signature should contain a single reference,
94 				  * but WS-Security signatures can contain many */,
95 	EMPTY_URI = 2,
96 } SignatureVerificationOption;
97 
98 struct XmlSnippet {
99 	char *name; /* name of the node or attribute to match */
100 	SnippetType type; /* type of node to deserialize */
101 	guint offset; /* offset of the storage field relative to the public or private object (if
102 			 using SNIPPET_PRIVATE). If 0, means that no storage must be done, it will
103 			 be handled by the init_from_xml virtual method. */
104 	char *class_name; /* Force a certain LassoNode class for deserializing a node, usually
105 			     useless. */
106 	char *ns_name; /* if the namespace is different from the one of the parent node, specify it
107 			  there */
108 	char *ns_uri;
109 };
110 
111 /**
112  * LassoSignatureContext:
113  * @signature_method: the method for signing (RSA, DSA, HMAC)
114  * @signature_key: a key for the signature
115  *
116  * Information needed to make a signature
117  */
118 typedef struct _LassoSignatureContext {
119 	LassoSignatureMethod signature_method;
120 	xmlSecKey *signature_key;
121 } LassoSignatureContext;
122 
123 #define LASSO_SIGNATURE_CONTEXT_NONE ((LassoSignatureContext){LASSO_SIGNATURE_TYPE_NONE, NULL})
124 
125 #define lasso_assign_signature_context(to, from) \
126 	do { \
127 		LassoSignatureContext *__to = &(to); \
128 		LassoSignatureContext __from = (from); \
129 		__to->signature_method = __from.signature_method; \
130 		lasso_assign_sec_key(__to->signature_key, __from.signature_key); \
131 	} while(0)
132 
133 #define lasso_assign_new_signature_context(to, from) \
134 	do { \
135 		LassoSignatureContext *__to = &(to); \
136 		LassoSignatureContext __from = (from); \
137 		__to->signature_method = __from.signature_method; \
138 		lasso_assign_new_sec_key(__to->signature_key, __from.signature_key); \
139 	} while(0)
140 
141 static inline gboolean
lasso_validate_signature_context(LassoSignatureContext context)142 lasso_validate_signature_context(LassoSignatureContext context) {
143 	return lasso_validate_signature_method(context.signature_method)
144 		&& context.signature_key != NULL;
145 }
146 
147 /**
148  * This inline method replace normal use of G_STRUCT_MEMBER_P/G_STRUCT_MEMBER, in order to add an
149  * indirection through the private structure attached to a GObject instance if needed */
150 inline static void *
snippet_struct_member(void * base,GType type,struct XmlSnippet * snippet)151 snippet_struct_member(void *base, GType type, struct XmlSnippet *snippet)
152 {
153 	if (snippet->type & SNIPPET_PRIVATE) {
154 		if (! G_IS_OBJECT(base))
155 			return NULL;
156 		GObject *object = (GObject*)base;
157 		base = g_type_instance_get_private((GTypeInstance*)object,
158 				type);
159 	}
160 	return G_STRUCT_MEMBER_P(base, snippet->offset);
161 }
162 
163 #define SNIPPET_STRUCT_MEMBER(type, base, gtype, snippet) \
164 	(*(type*)snippet_struct_member(base, gtype, snippet))
165 
166 #define SNIPPET_STRUCT_MEMBER_P(base, gtype, snippet) \
167 	snippet_struct_member(base, gtype, snippet)
168 
169 struct QuerySnippet {
170 	char *path;
171 	char *field_name;
172 };
173 
174 struct _LassoNodeClassData
175 {
176 	struct XmlSnippet *snippets;
177 	struct QuerySnippet *query_snippets;
178 	char *node_name;
179 	xmlNs *ns;
180 	char *id_attribute_name;
181 	int id_attribute_offset;
182 	int sign_type_offset;
183 	int sign_method_offset;
184 	int private_key_file_offset;
185 	int certificate_file_offset;
186 	gboolean keep_xmlnode;
187 	gboolean xsi_sub_type;
188 };
189 
190 void lasso_node_class_set_nodename(LassoNodeClass *klass, char *name);
191 void lasso_node_class_set_ns(LassoNodeClass *klass, char *href, char *prefix);
192 void lasso_node_class_add_snippets(LassoNodeClass *klass, struct XmlSnippet *snippets);
193 void lasso_node_class_add_query_snippets(LassoNodeClass *klass, struct QuerySnippet *snippets);
194 
195 gchar* lasso_node_build_query_from_snippets(LassoNode *node);
196 gboolean lasso_node_init_from_query_fields(LassoNode *node, char **query_fields);
197 gboolean lasso_node_init_from_saml2_query_fields(LassoNode *node,
198 		char **query_fields, char **relay_state);
199 LassoMessageFormat lasso_node_init_from_message_with_format(LassoNode *node, const char *message, LassoMessageFormat constraint, xmlDoc **doc_out, xmlNode **root_out);
200 
201 typedef enum {
202 	LASSO_PEM_FILE_TYPE_UNKNOWN,
203 	LASSO_PEM_FILE_TYPE_PUB_KEY,
204 	LASSO_PEM_FILE_TYPE_PRIVATE_KEY,
205 	LASSO_PEM_FILE_TYPE_CERT
206 } LassoPemFileType;
207 
208 void  lasso_build_random_sequence(char *buffer, unsigned int size);
209 char* lasso_build_unique_id(unsigned int size);
210 char* lasso_get_current_time(void);
211 char* lasso_time_to_iso_8601_gmt(time_t now);
212 time_t lasso_iso_8601_gmt_to_time_t(const char *xsdtime);
213 LassoPemFileType lasso_get_pem_file_type(const char *file);
214 
215 xmlSecKeyPtr lasso_get_public_key_from_pem_file(const char *file);
216 xmlSecKeyPtr lasso_get_public_key_from_pem_cert_file(const char *file);
217 xmlSecKeysMngr* lasso_load_certs_from_pem_certs_chain_file (const char *file);
218 
219 char* lasso_query_sign(char *query, LassoSignatureContext signature_context);
220 
221 int lasso_query_verify_signature(const char *query, const xmlSecKey *public_key);
222 
223 int lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key);
224 
225 char* lasso_sha1(const char *str);
226 
227 char* lasso_sha256(const char *str);
228 
229 char* lasso_sha384(const char *str);
230 
231 char* lasso_sha512(const char *str);
232 
233 xmlChar** lasso_urlencoded_to_strings(const char *str);
234 
235 int lasso_sign_node(xmlNode *xmlnode, LassoSignatureContext context, const char *id_attr_name, const char *id_value);
236 
237 int lasso_verify_signature(xmlNode *signed_node, xmlDoc *doc, const char *id_attr_name,
238 		xmlSecKeysMngr *keys_manager, xmlSecKey *public_key,
239 		SignatureVerificationOption signature_verification_option,
240 		GList **uri_references);
241 void xmlCleanNs(xmlNode *root_node);
242 
243 void xml_insure_namespace(xmlNode *xmlnode, xmlNs *ns, gboolean force,
244 		gchar *ns_href, gchar *ns_prefix);
245 
246 gchar* lasso_node_build_deflated_query(LassoNode *node);
247 
248 gchar* lasso_node_build_query(LassoNode *node);
249 
250 gboolean lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate_string);
251 
252 xmlNode* lasso_node_get_xmlnode_for_any_type(LassoNode *node, xmlNode *cur);
253 
254 LassoSaml2EncryptedElement* lasso_node_encrypt(LassoNode *lasso_node,
255 	xmlSecKey *encryption_public_key, LassoEncryptionSymKeyType encryption_sym_key_type, const char *recipient);
256 
257 int lasso_node_decrypt_xmlnode(xmlNode* encrypted_element, GList *encrypted_key,
258 		xmlSecKey *encryption_private_key, LassoNode **output);
259 
260 void lasso_node_remove_signature(LassoNode *node);
261 
262 char* lasso_concat_url_query(const char *url, const char *query);
263 
264 xmlDocPtr lasso_xml_parse_memory(const char *buffer, int size);
265 
266 xmlNode* lasso_xml_get_soap_content(xmlNode *root);
267 
268 xmlNodePtr lasso_xml_next_element_node(xmlNodePtr node);
269 
270 const xmlChar* lasso_xml_get_node_ns_href(const xmlNodePtr node);
271 
272 gboolean lasso_xml_is_element_node(const xmlNodePtr node,
273                                    const xmlChar *name, const xmlChar *ns);
274 
275 gboolean lasso_xml_is_soap(xmlNode *root);
276 
277 xmlNodePtr lasso_xml_soap11_get_header(xmlNodePtr envelope_node);
278 
279 xmlNodePtr lasso_xml_soap11_get_body(xmlNodePtr envelope_node);
280 
281 gboolean lasso_eval_xpath_expression(xmlXPathContextPtr xpath_ctx, const char *expression,
282 		xmlXPathObjectPtr *xpath_object_ptr, int *xpath_error_code);
283 
284 #define IF_SAML2(profile) \
285 	if (lasso_provider_get_protocol_conformance(LASSO_PROVIDER(profile->server)) == \
286 			LASSO_PROTOCOL_SAML_2_0)
287 
288 char * lasso_get_relaystate_from_query(const char *query);
289 char * lasso_url_add_parameters(char *url, gboolean free, ...);
290 xmlChar * lasso_xmlURIEscapeStr(const xmlChar *from, const xmlChar *list);
291 xmlSecKey* lasso_xmlsec_load_private_key_from_buffer(const char *buffer, size_t length, const char *password, LassoSignatureMethod signature_method, const char *certificate);
292 xmlSecKey* lasso_xmlsec_load_private_key(const char *filename_or_buffer, const char *password,
293 		LassoSignatureMethod signature_method, const char *certificate);
294 xmlDocPtr lasso_xml_parse_file(const char *filepath);
295 xmlDocPtr lasso_xml_parse_memory_with_error(const char *buffer, int size, xmlError *error);
296 xmlSecKeyPtr lasso_xmlsec_load_key_info(xmlNode *key_descriptor);
297 char* lasso_xmlnode_to_string(xmlNode *node, gboolean format, int level);
298 gboolean lasso_string_to_xsd_integer(const char *str, long int *integer);
299 void lasso_set_string_from_prop(char **str, xmlNode *node, xmlChar *name, xmlChar *ns);
300 
301 void lasso_node_add_custom_namespace(LassoNode *node, const char *prefix, const char *href);
302 
303 int lasso_node_set_signature(LassoNode *node, LassoSignatureContext context);
304 
305 LassoSignatureContext lasso_node_get_signature(LassoNode *node);
306 
307 void lasso_node_set_encryption(LassoNode *node, xmlSecKey *encryption_public_key,
308 		LassoEncryptionSymKeyType encryption_sym_key_type);
309 
310 void lasso_node_get_encryption(LassoNode *node, xmlSecKey **encryption_public_key,
311 		LassoEncryptionSymKeyType *encryption_sym_key_type);
312 gboolean lasso_base64_decode(const char *from, char **buffer, int *buffer_len);
313 
314 xmlSecKeyPtr
315 lasso_create_hmac_key(const xmlSecByte * buf, xmlSecSize size);
316 
317 lasso_error_t
318 lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size);
319 
320 LassoSignatureContext lasso_make_signature_context_from_buffer(const void *buffer, size_t length,
321 		const char *password, LassoSignatureMethod signature_method,
322 		const char *certificate);
323 
324 LassoSignatureContext lasso_make_signature_context_from_path_or_string(char *filename_or_buffer,
325 		const char *password, LassoSignatureMethod signature_method,
326 		const char *certificate);
327 
328 xmlNs * get_or_define_ns(xmlNode *xmlnode, const xmlChar *ns_uri, const xmlChar
329 		*advised_prefix);
330 
331 void set_qname_attribute(xmlNode *node,
332 		const xmlChar *attribute_ns_prefix,
333 		const xmlChar *attribute_ns_href,
334 		const xmlChar *attribute_name,
335 		const xmlChar *prefix,
336 		const xmlChar *href,
337 		const xmlChar *name);
338 
339 
340 void set_xsi_type(xmlNode *node,
341 		const xmlChar *type_ns_prefix,
342 		const xmlChar *type_ns_href,
343 		const xmlChar *type_name);
344 
345 void lasso_xmlnode_add_saml2_signature_template(xmlNode *node, LassoSignatureContext context,
346 		const char *id);
347 
348 gchar* lasso_xmlnode_build_deflated_query(xmlNode *xmlnode);
349 
350 xmlTextReader *lasso_xmltextreader_from_message(const char *message, char **to_free);
351 
352 #ifdef __cplusplus
353 }
354 #endif /* __cplusplus */
355 
356 #endif /* __LASSO_XML_PRIVATE_H__ */
357