1 /* $Id$
2  *
3  * Lasso - A free implementation of the Liberty Alliance specifications.
4  *
5  * Copyright (C) 2004-2007 Entr'ouvert
6  * http://lasso.entrouvert.org
7  *
8  * Authors: See AUTHORS file in top-level directory.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 /**
25  * SECTION:lasso
26  * @short_description: Initialization functions
27  *
28  * <sec2>
29  * <title>Environment variables</title>
30  * <para>
31  * <literal>LASSO_FLAG</literal> is an environment variable containing white-space separated values
32  * which allows to modify the behaviour of lasso. To negate the effect of one of
33  * the value, just add <literal>no-</literal> in front of its name. The flag are also modifiable
34  * using the lasso_set_flag() function. Those values are:
35  *
36  * <informaltable frame="non">
37  * <tgroup cols="2">
38  * <tbody>
39  * <rows>
40  * <entry><literal>no-verify-signature</literal></entry>
41  * <entry><para>Disable the validation of signatures on all message, usually for
42  * debugging pupose</para></entry>
43  * </rows>
44  * <rows>
45  * <entry><literal>memory-debug</literal></entry>
46  * <entry><para>Enable the tracing of nodes allocation, deallocation and initialization.</para></entry>
47  * </rows>
48  * <rows id="strict-checking">
49  * <entry><literal>strict-checking</literal></entry>
50  * <entry><para>Enable checking which were not done in previous version of Lasso, like matching <literal>ResponseTo</literal> attributes of response messages to the identifier of the request.</para></entry>
51  * </rows>
52  * <rows>
53  * <entry><literal>no-add-signature</literal></entry>
54  * <entry><para>Disable all signatures</para></entry>
55  * </rows>
56  * <rows>
57  * <entry><literal>no-sign-messages</literal></entry>
58  * <entry><para>Disable signatures on messages.</para></entry>
59  * </rows>
60  * <rows>
61  * <entry><literal>no-sign-messages</literal></entry>
62  * <entry><para>Disable signatures on messages.</para></entry>
63  * </rows>
64  * <rows>
65  * <entry><literal>pem-public-key</literal></entry>
66  * <entry><para>Allow PEM key in ds:KeyValue nodes, it's outside the XMLSig specification.</para></entry>
67  * </rows>
68  * </tbody>
69  * </tgroup>
70  * </informaltable>
71  * </para>
72  * </sec2>
73  **/
74 
75 #include <stdlib.h> /* getenv */
76 #include <string.h> /* strcmp */
77 #include <xmlsec/xmlsec.h>
78 #include <xmlsec/crypto.h>
79 #include <xmlsec/errors.h>
80 #include <libxslt/xslt.h>
81 #include <config.h>
82 #include "lasso.h"
83 #include "lasso_config.h"
84 #include "debug.h"
85 #include "backward_comp.h"
86 #include "registry-private.h"
87 #include "xml/private.h"
88 #include "utils.h"
89 
90 /* Set to true, it forces lasso_provider_verify_signature and lasso_query_verify_signature to always
91  * return TRUE. */
92 gboolean lasso_flag_verify_signature = TRUE;
93 /* Set to true, it activates debugging code for LassoNode freeing */
94 gboolean lasso_flag_memory_debug = FALSE;
95 /* set to true, it activates more strict validation of messages */
96 gboolean lasso_flag_strict_checking = FALSE;
97 /* set to false, it does not sign messages */
98 gboolean lasso_flag_add_signature = TRUE;
99 static void lasso_flag_parse_environment_variable();
100 /* do not sign messages */
101 gboolean lasso_flag_sign_messages = TRUE;
102 /* thin sessions */
103 gboolean lasso_flag_thin_sessions = FALSE;
104 /* PEM public key */
105 gboolean lasso_flag_pem_public_key = FALSE;
106 
107 #ifndef LASSO_FLAG_ENV_VAR
108 #define LASSO_FLAG_ENV_VAR "LASSO_FLAG"
109 #endif
110 
111 #if defined _MSC_VER
112 HINSTANCE g_hModule = NULL;
113 
114 /**
115  * DllMain:
116  * @hinstDLL: hnadle to the DLL module
117  * @fdwReason: reason value of the DLL call
118  * @lpvReserved: use is unknown.
119  *
120  * Called when the DLL is attached or detached by a program.
121  *
122  * Return value: %TRUE if everything is OK
123  **/
124 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)125 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
126 {
127 	if (fdwReason == DLL_PROCESS_ATTACH)
128 	{
129 		DisableThreadLibraryCalls(hinstDLL);
130 		g_hModule = hinstDLL;
131 	}
132 	return TRUE;
133 }
134 #endif
135 
136 #include "types.c"
137 
138 static void
lasso_xml_structured_error_func(G_GNUC_UNUSED void * user_data,xmlErrorPtr error)139 lasso_xml_structured_error_func(G_GNUC_UNUSED void *user_data, xmlErrorPtr error)
140 {
141 	g_log("libxml2", G_LOG_LEVEL_DEBUG, "libxml2: %s", error->message);
142 }
143 
144 void
lasso_xmlsec_errors_callback(const char * file G_GNUC_UNUSED,int line G_GNUC_UNUSED,const char * func G_GNUC_UNUSED,const char * errorObject G_GNUC_UNUSED,const char * errorSubject G_GNUC_UNUSED,int reason G_GNUC_UNUSED,const char * msg)145 lasso_xmlsec_errors_callback(const char *file G_GNUC_UNUSED, int line G_GNUC_UNUSED, const char *func G_GNUC_UNUSED,
146 		const char *errorObject G_GNUC_UNUSED, const char *errorSubject G_GNUC_UNUSED, int reason G_GNUC_UNUSED,
147 		const char *msg)
148 {
149 	g_log("libxmlsec", G_LOG_LEVEL_DEBUG, "libxmlsec: %s:%d:%s:%s:%s:%s:%s", file, line, func, errorObject, errorSubject, xmlSecErrorsGetMsg(reason), msg);
150 }
151 
152 /**
153  * lasso_init:
154  *
155  * Initializes Lasso library.
156  *
157  * Return value: 0 on success; or a negative value otherwise.
158  **/
lasso_init()159 int lasso_init()
160 {
161 	int i;
162 
163 #ifndef GLIB_VERSION_2_36
164 	g_type_init();
165 #endif
166 
167 	/* Init Lasso classes */
168 	for (i=0; functions[i]; i++)
169 		functions[i]();
170 
171 	/* Init libxml and libxslt libraries */
172 	xmlInitParser();
173 	/*LIBXML_TEST_VERSION*/
174 	/* xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; */
175 	/* xmlSubstituteEntitiesDefault(1); */
176 
177 	/* Init xmlsec library */
178 	if (xmlSecInit() < 0) {
179 		message(G_LOG_LEVEL_CRITICAL, "XMLSec initialization failed.");
180 		return LASSO_ERROR_UNDEFINED;
181 	}
182 
183 	/* Load default crypto engine if we are supporting dynamic
184 	 * loading for xmlsec-crypto libraries. Use the crypto library
185 	 * name ("openssl", "nss", etc.) to load corresponding
186 	 * xmlsec-crypto library.
187 	 */
188 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
189 	if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
190 		message(G_LOG_LEVEL_CRITICAL,
191 				"Unable to load default xmlsec-crypto library. Make sure"
192 				"that you have it installed and check shared libraries path"
193 				"(LD_LIBRARY_PATH) environment variable.");
194 		return LASSO_ERROR_UNDEFINED;
195 	}
196 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
197 
198 	/* Init crypto library */
199 	if (xmlSecCryptoAppInit(NULL) < 0) {
200 		message(G_LOG_LEVEL_CRITICAL, "Crypto initialization failed.");
201 		return LASSO_ERROR_UNDEFINED;
202 	}
203 
204 	/* Init xmlsec-crypto library */
205 	if (xmlSecCryptoInit() < 0) {
206 		message(G_LOG_LEVEL_CRITICAL, "xmlsec-crypto initialization failed.");
207 		return LASSO_ERROR_UNDEFINED;
208 	}
209 	lasso_flag_parse_environment_variable();
210 	xmlSetStructuredErrorFunc(NULL, lasso_xml_structured_error_func);
211 	xmlSecErrorsSetCallback(lasso_xmlsec_errors_callback);
212 	return 0;
213 }
214 
215 /**
216  * lasso_shutdown:
217  *
218  * Clean ups Lasso library.
219  *
220  * Return value: 0 on success; or a negative value otherwise.
221  **/
lasso_shutdown()222 int lasso_shutdown()
223 {
224 	/* Shutdown xmlsec-crypto library */
225 	xmlSecCryptoShutdown();
226 
227 	/* Shutdown crypto library */
228 	xmlSecCryptoAppShutdown();
229 
230 	/* Shutdown xmlsec library */
231 	xmlSecShutdown();
232 
233 	/* Shutdown libxslt/libxml */
234 #ifndef XMLSEC_NO_XSLT
235 	xsltCleanupGlobals();
236 #endif /* XMLSEC_NO_XSLT */
237 	/* Cleanup function for the XML library */
238 	xmlCleanupParser();
239 
240 	/* Disallocate default registry */
241 	lasso_registry_default_shutdown();
242 
243 	if (lasso_flag_memory_debug == TRUE) {
244 	/* this is to debug memory for regression tests */
245 		xmlMemoryDump();
246 	}
247 	return 0;
248 }
249 
250 /**
251  * lasso_check_version:
252  * @major: major version numbe
253  * @minor: minor version number
254  * @subminor: subminor version number
255  * @mode: version check mode
256  *
257  * Checks if the loaded version of Lasso library could be used.
258  *
259  * Return value: 1 if the loaded lasso library version is OK to use
260  *     0 if it is not; or a negative value if an error occurs.
261  **/
262 int
lasso_check_version(int major,int minor,int subminor,LassoCheckVersionMode mode)263 lasso_check_version(int major, int minor, int subminor, LassoCheckVersionMode mode)
264 {
265 	if (mode == LASSO_CHECK_VERSION_NUMERIC) {
266 		if (LASSO_VERSION_MAJOR*10000 + LASSO_VERSION_MINOR*100 + LASSO_VERSION_SUBMINOR <
267 				major*10000 + minor*100 + subminor)
268 			return 0;
269 		return 1;
270 	}
271 	/* we always want to have a match for major version number */
272 	if (major != LASSO_VERSION_MAJOR) {
273 		return 0;
274 	}
275 
276 	if (mode == LASSO_CHECK_VERSION_EXACT) {
277 		if (minor != LASSO_VERSION_MINOR || subminor != LASSO_VERSION_SUBMINOR) {
278 			return 0;
279 		}
280 	}
281 
282 	if (mode == LASSO_CHECK_VERSIONABI_COMPATIBLE) {
283 		if (minor < LASSO_VERSION_MINOR || (minor == LASSO_VERSION_MINOR &&
284 					subminor < LASSO_VERSION_SUBMINOR)) {
285 			return 0;
286 		}
287 	}
288 
289 	if (mode > LASSO_CHECK_VERSION_NUMERIC)
290 		return LASSO_ERROR_UNDEFINED;
291 
292 	return 1;
293 }
294 
295 /**
296  * lasso_set_flag:
297  * @flag: a string representing a flag name, prefix with 'no-' to disable it.
298  *
299  * Set a debugging flag. You can also use the environment variable LASSO_FLAG
300  * to get the same effect. LASSO_FLAG must contain flag name separated by spaces, commas,
301  * tabulations or colons.
302  */
lasso_set_flag(char * flag)303 void lasso_set_flag(char *flag) {
304 	gboolean value = TRUE;
305 
306 	g_return_if_fail(flag);
307 
308 	/* Handle negative flags */
309 	if (flag && strncmp(flag, "no-", 3) == 0) {
310 		value = FALSE;
311 		flag += 3;
312 	}
313 
314 	do {
315 		if (lasso_strisequal(flag,"verify-signature")) {
316 			lasso_flag_verify_signature = value;
317 			continue;
318 		}
319 		if (lasso_strisequal(flag,"memory-debug")) {
320 			lasso_flag_memory_debug = value;
321 			continue;
322 		}
323 		if (lasso_strisequal(flag,"strict-checking")) {
324 			lasso_flag_strict_checking = value;
325 			continue;
326 		}
327 		if (lasso_strisequal(flag,"add-signature")) {
328 			lasso_flag_add_signature = value;
329 			continue;
330 		}
331 		if (lasso_strisequal(flag,"sign-messages")) {
332 			lasso_flag_sign_messages = value;
333 			continue;
334 		}
335 		if (lasso_strisequal(flag,"thin-sessions")) {
336 			lasso_flag_thin_sessions = value;
337 		}
338 		if (lasso_strisequal(flag,"pem-public-key")) {
339 			lasso_flag_pem_public_key = value;
340 		}
341 	} while (FALSE);
342 }
343 
lasso_flag_parse_environment_variable()344 static void lasso_flag_parse_environment_variable() {
345 	char *lasso_flag = getenv(LASSO_FLAG_ENV_VAR);
346 	char *save_ptr;
347 	char *token;
348 	const char delim[] = ", \t:";
349 
350 	if (lasso_flag) {
351 		token = strtok_r(lasso_flag, delim, &save_ptr);
352 		do {
353 			lasso_set_flag(token);
354 		} while ((token = strtok_r(NULL, delim, &save_ptr)) != NULL);
355 	}
356 }
357