summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile40
-rw-r--r--examples/Makefile.w3288
-rw-r--r--examples/README126
-rw-r--r--examples/binary.dat1
-rw-r--r--examples/decrypt1.c223
-rw-r--r--examples/decrypt2.c293
-rw-r--r--examples/decrypt3.c372
-rw-r--r--examples/deskey.bin1
-rw-r--r--examples/encrypt1-res.xml13
-rw-r--r--examples/encrypt1-tmpl.xml13
-rw-r--r--examples/encrypt1.c219
-rw-r--r--examples/encrypt2-doc.xml9
-rw-r--r--examples/encrypt2-res.xml14
-rw-r--r--examples/encrypt2.c244
-rw-r--r--examples/encrypt3-doc.xml9
-rw-r--r--examples/encrypt3-res.xml27
-rw-r--r--examples/encrypt3.c340
-rw-r--r--examples/mywin32make.bat18
-rw-r--r--examples/rootcert.pem25
-rw-r--r--examples/rsacert.pem83
-rw-r--r--examples/rsakey.pem27
-rw-r--r--examples/rsapub.pem9
-rw-r--r--examples/sign1-res.xml31
-rw-r--r--examples/sign1-tmpl.xml27
-rw-r--r--examples/sign1.c212
-rw-r--r--examples/sign2-doc.xml9
-rw-r--r--examples/sign2-res.xml30
-rw-r--r--examples/sign2.c248
-rw-r--r--examples/sign3-doc.xml9
-rw-r--r--examples/sign3-res.xml58
-rw-r--r--examples/sign3.c261
-rw-r--r--examples/verify1.c215
-rw-r--r--examples/verify2.c285
-rw-r--r--examples/verify3.c266
-rw-r--r--examples/verify4-bad-res.xml90
-rw-r--r--examples/verify4-bad-tmpl.xml54
-rw-r--r--examples/verify4-res.xml80
-rw-r--r--examples/verify4-tmpl.xml47
-rw-r--r--examples/verify4.c309
-rw-r--r--examples/xkms-server.c839
-rw-r--r--examples/xmldsigverify.c381
41 files changed, 5645 insertions, 0 deletions
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 00000000..5c87150f
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,40 @@
+#
+#
+#
+PROGRAMS = \
+ sign1 sign2 sign3 \
+ verify1 verify2 verify3 verify4 \
+ encrypt1 encrypt2 encrypt3 \
+ decrypt1 decrypt2 decrypt3 \
+ xmldsigverify \
+ xkms-server
+
+CC = gcc
+CFLAGS += -g $(shell xmlsec1-config --cflags) -DUNIX_SOCKETS
+LDFLAGS += -g $(shell xmlsec1-config --libs)
+
+all: $(PROGRAMS)
+
+clean:
+ @rm -rf $(PROGRAMS)
+
+check: $(PROGRAMS)
+ ./sign1 sign1-tmpl.xml rsakey.pem
+ ./sign2 sign2-doc.xml rsakey.pem
+ ./sign3 sign3-doc.xml rsakey.pem rsacert.pem
+ ./verify1 sign1-res.xml rsapub.pem
+ ./verify1 sign2-res.xml rsapub.pem
+ ./verify2 sign1-res.xml rsapub.pem
+ ./verify2 sign2-res.xml rsapub.pem
+ ./verify3 sign3-res.xml rootcert.pem
+ ./verify4 verify4-res.xml rootcert.pem
+ ./encrypt1 encrypt1-tmpl.xml deskey.bin
+ ./encrypt2 encrypt2-doc.xml deskey.bin
+ ./encrypt3 encrypt3-doc.xml rsakey.pem
+ ./decrypt1 encrypt1-res.xml deskey.bin
+ ./decrypt1 encrypt2-res.xml deskey.bin
+ ./decrypt2 encrypt1-res.xml deskey.bin
+ ./decrypt2 encrypt2-res.xml deskey.bin
+ ./decrypt3 encrypt1-res.xml
+ ./decrypt3 encrypt2-res.xml
+ ./decrypt3 encrypt3-res.xml
diff --git a/examples/Makefile.w32 b/examples/Makefile.w32
new file mode 100644
index 00000000..ee81ab39
--- /dev/null
+++ b/examples/Makefile.w32
@@ -0,0 +1,88 @@
+# Makefile for xmlsec, specific for Windows, MSVC and NMAKE.
+#
+# Take a look at the beginning and modify the variables to suit your
+# environment. Having done that, you can do a
+
+XMLSEC_STATIC = yes
+XMLSEC_CRYPTO = openssl
+XMLSEC_CFLAGS =
+XMLSEC_LIBS =
+
+# There should never be a need to modify anything below this line.
+XMLSEC_OBJS_DIR = build
+XMLSEC_EXAMPLES = \
+ $(XMLSEC_OBJS_DIR)\sign1.exe \
+ $(XMLSEC_OBJS_DIR)\sign2.exe \
+ $(XMLSEC_OBJS_DIR)\sign3.exe \
+ $(XMLSEC_OBJS_DIR)\verify1.exe \
+ $(XMLSEC_OBJS_DIR)\verify2.exe \
+ $(XMLSEC_OBJS_DIR)\verify3.exe \
+ $(XMLSEC_OBJS_DIR)\verify4.exe \
+ $(XMLSEC_OBJS_DIR)\encrypt1.exe \
+ $(XMLSEC_OBJS_DIR)\encrypt2.exe \
+ $(XMLSEC_OBJS_DIR)\encrypt3.exe \
+ $(XMLSEC_OBJS_DIR)\decrypt1.exe \
+ $(XMLSEC_OBJS_DIR)\decrypt2.exe \
+ $(XMLSEC_OBJS_DIR)\decrypt3.exe \
+ $(XMLSEC_OBJS_DIR)\xkms-server.exe \
+
+#
+!IF "$(XMLSEC_CRYPTO)" == "openssl"
+XMLSEC_CFLAGS = $(XMLSEC_CFLAGS) /D "XMLSEC_CRYPTO_OPENSSL" /D "XMLSEC_CRYPTO=\"openssl\""
+XMLSEC_SOLIBS = libxmlsec-openssl.lib libeay32.lib wsock32.lib user32.lib gdi32.lib
+XMLSEC_ALIBS = libxmlsec-openssl_a.lib libeay32.lib wsock32.lib user32.lib gdi32.lib
+!ENDIF
+
+!IF "$(XMLSEC_CRYPTO)" == "nss"
+XMLSEC_CFLAGS = $(XMLSEC_CFLAGS) /D "XMLSEC_CRYPTO_NSS" /D "XMLSEC_CRYPTO=\"nss\""
+XMLSEC_SOLIBS = libxmlsec-nss.lib nss3.lib nspr4.lib plds4.lib plc4.lib
+XMLSEC_ALIBS = libxmlsec-nss_a.lib nss3.lib nspr4.lib plds4.lib plc4.lib
+!ENDIF
+
+!IF "$(XMLSEC_CRYPTO)" == "mscrypto"
+XMLSEC_CFLAGS = $(XMLSEC_CFLAGS) /D "XMLSEC_CRYPTO_MSCRYPTO" /D "XMLSEC_CRYPTO=\"mscrypto\""
+XMLSEC_SOLIBS = libxmlsec-mscrypto.lib user32.lib gdi32.lib crypt32.lib advapi32.lib
+XMLSEC_ALIBS = libxmlsec-mscrypto_a.lib user32.lib gdi32.lib crypt32.lib advapi32.lib
+!ENDIF
+
+!IF "$(XMLSEC_STATIC)" == "yes"
+XMLSEC_CFLAGS = $(XMLSEC_CFLAGS) /D "LIBXML_STATIC" /D "LIBXSLT_STATIC" /D "XMLSEC_STATIC"
+XMLSEC_LIBS = $(XMLSEC_LIBS) $(XMLSEC_ALIBS) libxmlsec_a.lib \
+ libxml2_a.lib libxslt_a.lib libexslt_a.lib
+!ELSE
+XMLSEC_LIBS = $(XMLSEC_LIBS) $(XMLSEC_SOLIBS) libxmlsec.lib libxml2.lib \
+ libxslt.lib libexslt.lib
+!ENDIF
+
+# The preprocessor and its options.
+CPP = cl.exe /EP
+CPPFLAGS = /nologo
+
+# The compiler and its options.
+CC = cl.exe
+CFLAGS = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /DWIN32_SOCKETS /W1 /MD $(XMLSEC_CFLAGS)
+
+# The linker and its options.
+LD = link.exe
+LDFLAGS = /nologo $(XMLSEC_LIBS) wsock32.lib
+
+# Optimisation and debug symbols.
+!if "$(DEBUG)" == "1"
+CFLAGS = $(CFLAGS) /D "_DEBUG" /Od /Z7
+LDFLAGS = $(LDFLAGS) /DEBUG
+!else
+CFLAGS = $(CFLAGS) /D "NDEBUG" /O2
+LDFLAGS = $(LDFLAGS) /OPT:NOWIN98
+!endif
+
+all : $(XMLSEC_OBJS_DIR) $(XMLSEC_EXAMPLES)
+
+$(XMLSEC_OBJS_DIR) :
+ if not exist $(XMLSEC_OBJS_DIR) mkdir $(XMLSEC_OBJS_DIR)
+
+.c{$(XMLSEC_OBJS_DIR)}.exe :
+ $(CC) /c $(CFLAGS) /Fo$(XMLSEC_OBJS_DIR)\ $<
+ $(LD) $(LDFLAGS) /OUT:$*.exe $*.obj
+
+clean:
+ if exist $(XMLSEC_OBJS_DIR) rmdir /S /Q $(XMLSEC_OBJS_DIR)
diff --git a/examples/README b/examples/README
new file mode 100644
index 00000000..bd680289
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,126 @@
+This folder contains XML Security Library examples.
+
+1. Files List
+-------------------------
+
+ README This file.
+ Makefile *nix makefile.
+ Makefile.w32 Win32 makefile.
+ rsakey.pem Private PEM key file
+ rsapub.pem Public PEM key file
+ rsacert.pem Certificate for rsakey.pem signed with rootcert.pem
+ rootcert.pem Root (trusted) certificate
+ deskey.bin A DES keys
+ sign1.c Signing with a template file
+ sign1-tmpl.xml An example template file for sign1 example
+ sign1-res.xml The result of processing sign1_tmpl.xml by sign1.c
+ sign2.c Signing a file with a dynamicaly created template
+ sign2-doc.xml An example XML file for signing by sign2.c
+ sign2-res.xml The result of signing sign2-doc.xml by sign2.c
+ sign3.c Signing a file with a dynamicaly created template and an X509 certificate
+ sign3-doc.xml An example XML file for signing by sign3.c
+ sign3-res.xml The result of signing sign3-doc.xml by sign3.c
+ verify1.c Verifying a signed document with a single key
+ verify2.c Verifying a signed document using keys manager
+ verify3.c Verifying a signed document using X509 certificate
+ verify4.c Verifying a simple SAML response using X509 certificate
+ verify4-tmpl.xml An example template file with a simple SAML response for verify4 example
+ verify4-res.xml Signed simple SAML response for verification by verify4.c
+ encrypt1.c Encrypting binary data with a template file
+ encrypt1-res.xml An example template file for encrypt1.c
+ encrypt1-tmpl.xml The result of processing encrypt1_tmpl.xml by encrypt1.c
+ encrypt2.c Encrypting XML file using a dynamicaly created template
+ encrypt2-doc.xml An example XML file for encryption by encrypt2.c
+ encrypt2-res.xml The result of encryptin encrypt2-doc.xml by encrypt2.c
+ encrypt2.c Encrypting XML file using a session DES key
+ encrypt2-doc.xml An example XML file for encryption by encrypt3.c
+ encrypt2-res.xml The result of encryptin encrypt3-doc.xml by encrypt3.c
+ decrypt1.c Decrypting binary data using a single key
+ decrypt2.c Decrypting binary data using keys manager
+ decrypt3.c Decrypting binary file using custom keys manager
+ xmldsigverify.c CGI script for signatures verifications
+
+2. Building Examples
+-------------------------
+
+Unixes:
+ Just run the usual 'make' command (assuming that xmlsec, libxml and
+ all other required libraries are already installed).
+
+Windows:
+ - Add paths to include and library files for xmlsec, libxml2, libexslt and
+ openssl or nss to the environment variables INCLUDE and LIB.
+ - Edit 'Makefile.w32' file and specify correct crypto engine (openssl or
+ nss for now). You can also specify necessary include and library paths
+ or change from static linking to using DLLs.
+ - Run 'nmake -f Makefile.w32'
+
+ If something does not work, check the README file in the top level
+ "win32" folder and have fun :)
+
+Other platforms:
+ If none of the above works for you and you've managed to compile xmlsec
+ library by yourself then you probably know what to do.
+
+
+
+3. Runnning Examples.
+-------------------------
+
+The following are just examples and you can use the programs from this
+folder with any other input files:
+
+ ./sign1 sign1-tmpl.xml rsakey.pem
+ ./sign2 sign2-doc.xml rsakey.pem
+ ./sign3 sign3-doc.xml rsakey.pem rsacert.pem
+
+ ./verify1 sign1-res.xml rsapub.pem
+ ./verify1 sign2-res.xml rsapub.pem
+ ./verify2 sign1-res.xml rsapub.pem
+ ./verify2 sign2-res.xml rsapub.pem
+ ./verify3 sign3-res.xml rootcert.pem
+ ./verify4 verify4-res.xml rootcert.pem
+
+ ./encrypt1 encrypt1-tmpl.xml deskey.bin
+ ./encrypt2 encrypt2-doc.xml deskey.bin
+ ./encrypt3 encrypt3-doc.xml rsakey.pem
+
+ ./decrypt1 encrypt1-res.xml deskey.bin
+ ./decrypt1 encrypt2-res.xml deskey.bin
+ ./decrypt2 encrypt1-res.xml deskey.bin
+ ./decrypt2 encrypt2-res.xml deskey.bin
+ ./decrypt3 encrypt1-res.xml
+ ./decrypt3 encrypt2-res.xml
+ ./decrypt3 encrypt3-res.xml
+
+4. Using xmlsec command line tool.
+-------------------------
+For Windows, use "xmlsec" instead of "xmlsec1".
+ xmlsec1 sign --privkey rsakey.pem --output sign1.xml sign1-tmpl.xml
+ xmlsec1 verify --pubkey rsapub.pem sign1.xml
+ xmlsec1 verify --pubkey rsapub.pem sign1-res.xml
+ xmlsec1 verify --pubkey rsapub.pem sign2-res.xml
+ xmlsec1 verify --trusted rootcert.pem sign3-res.xml
+ xmlsec1 verify --trusted rootcert.pem verify4-res.xml
+
+ xmlsec1 encrypt --deskey deskey.bin --binary-data binary.dat --output encrypt1.xml encrypt1-tmpl.xml
+ xmlsec1 decrypt --deskey deskey.bin encrypt1.xml
+ xmlsec1 decrypt --deskey deskey.bin encrypt1-res.xml
+ xmlsec1 decrypt --deskey deskey.bin encrypt2-res.xml
+ xmlsec1 decrypt --privkey rsakey.pem encrypt3-res.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/binary.dat b/examples/binary.dat
new file mode 100644
index 00000000..a039696a
--- /dev/null
+++ b/examples/binary.dat
@@ -0,0 +1 @@
+Big secret \ No newline at end of file
diff --git a/examples/decrypt1.c b/examples/decrypt1.c
new file mode 100644
index 00000000..39ad1039
--- /dev/null
+++ b/examples/decrypt1.c
@@ -0,0 +1,223 @@
+/**
+ * XML Security Library example: Decrypting an encrypted file using a single key.
+ *
+ * Decrypts encrypted XML file using a single DES key from a binary file
+ *
+ * Usage:
+ * ./decrypt1 <xml-enc> <des-key-file>
+ *
+ * Example:
+ * ./decrypt1 encrypt1-res.xml deskey.bin
+ * ./decrypt1 encrypt2-res.xml deskey.bin
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/crypto.h>
+
+int decrypt_file(const char* enc_file, const char* key_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <enc-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(decrypt_file(argv[1], argv[2]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * decrypt_file:
+ * @enc_file: the encrypted XML file name.
+ * @key_file: the Triple DES key file.
+ *
+ * Decrypts the XML file #enc_file using DES key from #key_file and
+ * prints results to stdout.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+decrypt_file(const char* enc_file, const char* key_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(enc_file);
+ assert(key_file);
+
+ /* load template */
+ doc = xmlParseFile(enc_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* create encryption context, we don't need keys manager in this example */
+ encCtx = xmlSecEncCtxCreate(NULL);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* load DES key */
+ encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file);
+ if(encCtx->encKey == NULL) {
+ fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* decrypt the data */
+ if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
+ fprintf(stderr,"Error: decryption failed\n");
+ goto done;
+ }
+
+ /* print decrypted data to stdout */
+ if(encCtx->resultReplaced != 0) {
+ fprintf(stdout, "Decrypted XML data:\n");
+ xmlDocDump(stdout, doc);
+ } else {
+ fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
+ if(xmlSecBufferGetData(encCtx->result) != NULL) {
+ fwrite(xmlSecBufferGetData(encCtx->result),
+ 1,
+ xmlSecBufferGetSize(encCtx->result),
+ stdout);
+ }
+ }
+ fprintf(stdout, "\n");
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/decrypt2.c b/examples/decrypt2.c
new file mode 100644
index 00000000..49513e12
--- /dev/null
+++ b/examples/decrypt2.c
@@ -0,0 +1,293 @@
+/**
+ * XML Security Library example: Decrypting an encrypted file using keys manager.
+ *
+ * Decrypts encrypted XML file using keys manager and a list of
+ * DES key from a binary file
+ *
+ * Usage:
+ * ./decrypt2 <xml-enc> <des-key-file1> [<des-key-file2> [...]]
+ *
+ * Example:
+ * ./decrypt2 encrypt1-res.xml deskey.bin
+ * ./decrypt2 encrypt2-res.xml deskey.bin
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeysMngrPtr load_des_keys(char** files, int files_size);
+int decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file);
+
+int
+main(int argc, char **argv) {
+ xmlSecKeysMngrPtr mngr;
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <enc-file> <key-file1> [<key-file2> [...]]\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load keys */
+ mngr = load_des_keys(&(argv[2]), argc - 2);
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ if(decrypt_file(mngr, argv[1]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_des_keys:
+ * @files: the list of filenames.
+ * @files_size: the number of filenames in #files.
+ *
+ * Creates simple keys manager and load DES keys from #files in it.
+ * The caller is responsible for destroing returned keys manager using
+ * @xmlSecKeysMngrDestroy.
+ *
+ * Returns the pointer to newly created keys manager or NULL if an error
+ * occurs.
+ */
+xmlSecKeysMngrPtr
+load_des_keys(char** files, int files_size) {
+ xmlSecKeysMngrPtr mngr;
+ xmlSecKeyPtr key;
+ int i;
+
+ assert(files);
+ assert(files_size > 0);
+
+ /* create and initialize keys manager, we use a simple list based
+ * keys manager, implement your own xmlSecKeysStore klass if you need
+ * something more sophisticated
+ */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ return(NULL);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ for(i = 0; i < files_size; ++i) {
+ assert(files[i]);
+
+ /* load DES key */
+ key = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, files[i]);
+ if(key == NULL) {
+ fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", files[i]);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* add key to keys manager, from now on keys manager is responsible
+ * for destroying key
+ */
+ if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
+ fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+ }
+
+ return(mngr);
+}
+
+/**
+ * decrypt_file:
+ * @mngr: the pointer to keys manager.
+ * @enc_file: the encrypted XML file name.
+ *
+ * Decrypts the XML file #enc_file using DES key from #key_file and
+ * prints results to stdout.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(enc_file);
+
+ /* load template */
+ doc = xmlParseFile(enc_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* create encryption context */
+ encCtx = xmlSecEncCtxCreate(mngr);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* decrypt the data */
+ if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
+ fprintf(stderr,"Error: decryption failed\n");
+ goto done;
+ }
+
+ /* print decrypted data to stdout */
+ if(encCtx->resultReplaced != 0) {
+ fprintf(stdout, "Decrypted XML data:\n");
+ xmlDocDump(stdout, doc);
+ } else {
+ fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
+ if(xmlSecBufferGetData(encCtx->result) != NULL) {
+ fwrite(xmlSecBufferGetData(encCtx->result),
+ 1,
+ xmlSecBufferGetSize(encCtx->result),
+ stdout);
+ }
+ }
+ fprintf(stdout, "\n");
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/decrypt3.c b/examples/decrypt3.c
new file mode 100644
index 00000000..253920fb
--- /dev/null
+++ b/examples/decrypt3.c
@@ -0,0 +1,372 @@
+/**
+ * XML Security Library example: Decrypting an encrypted file using a custom keys manager.
+ *
+ * Decrypts encrypted XML file using a custom files based keys manager.
+ * We assume that key's name in <dsig:KeyName/> element is just
+ * key's file name in the current folder.
+ *
+ * Usage:
+ * ./decrypt3 <xml-enc>
+ *
+ * Example:
+ * ./decrypt3 encrypt1-res.xml
+ * ./decrypt3 encrypt2-res.xml
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeyStoreId files_keys_store_get_klass(void);
+xmlSecKeysMngrPtr create_files_keys_mngr(void);
+int decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file);
+
+int
+main(int argc, char **argv) {
+ xmlSecKeysMngrPtr mngr;
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 2) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <enc-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load keys */
+ mngr = create_files_keys_mngr();
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ if(decrypt_file(mngr, argv[1]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * decrypt_file:
+ * @mngr: the pointer to keys manager.
+ * @enc_file: the encrypted XML file name.
+ *
+ * Decrypts the XML file #enc_file using DES key from #key_file and
+ * prints results to stdout.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(enc_file);
+
+ /* load template */
+ doc = xmlParseFile(enc_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
+ goto done;
+ }
+
+ /* create encryption context */
+ encCtx = xmlSecEncCtxCreate(mngr);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* decrypt the data */
+ if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
+ fprintf(stderr,"Error: decryption failed\n");
+ goto done;
+ }
+
+ /* print decrypted data to stdout */
+ if(encCtx->resultReplaced != 0) {
+ fprintf(stdout, "Decrypted XML data:\n");
+ xmlDocDump(stdout, doc);
+ } else {
+ fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
+ if(xmlSecBufferGetData(encCtx->result) != NULL) {
+ fwrite(xmlSecBufferGetData(encCtx->result),
+ 1,
+ xmlSecBufferGetSize(encCtx->result),
+ stdout);
+ }
+ }
+ fprintf(stdout, "\n");
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
+/**
+ * create_files_keys_mngr:
+ *
+ * Creates a files based keys manager: we assume that key name is
+ * the key file name,
+ *
+ * Returns pointer to newly created keys manager or NULL if an error occurs.
+ */
+xmlSecKeysMngrPtr
+create_files_keys_mngr(void) {
+ xmlSecKeyStorePtr keysStore;
+ xmlSecKeysMngrPtr mngr;
+
+ /* create files based keys store */
+ keysStore = xmlSecKeyStoreCreate(files_keys_store_get_klass());
+ if(keysStore == NULL) {
+ fprintf(stderr, "Error: failed to create keys store.\n");
+ return(NULL);
+ }
+
+ /* create keys manager */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ xmlSecKeyStoreDestroy(keysStore);
+ return(NULL);
+ }
+
+ /* add store to keys manager, from now on keys manager destroys the store if needed */
+ if(xmlSecKeysMngrAdoptKeysStore(mngr, keysStore) < 0) {
+ fprintf(stderr, "Error: failed to add keys store to keys manager.\n");
+ xmlSecKeyStoreDestroy(keysStore);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* initialize crypto library specific data in keys manager */
+ if(xmlSecCryptoKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize crypto data in keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* set the get key callback */
+ mngr->getKey = xmlSecKeysMngrGetKey;
+ return(mngr);
+}
+
+/****************************************************************************
+ *
+ * Files Keys Store: we assume that key's name (content of the
+ * <dsig:KeyName/> element is a name of the file with a key (in the
+ * current folder).
+ * Attention: this probably not a good solution for high traffic systems.
+ *
+ ***************************************************************************/
+static xmlSecKeyPtr files_keys_store_find_key (xmlSecKeyStorePtr store,
+ const xmlChar* name,
+ xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyStoreKlass files_keys_store_klass = {
+ sizeof(xmlSecKeyStoreKlass),
+ sizeof(xmlSecKeyStore),
+ BAD_CAST "files-based-keys-store", /* const xmlChar* name; */
+ NULL, /* xmlSecKeyStoreInitializeMethod initialize; */
+ NULL, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ files_keys_store_find_key, /* xmlSecKeyStoreFindKeyMethod findKey; */
+
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+/**
+ * files_keys_store_get_klass:
+ *
+ * The files based keys store klass: we assume that key name is the
+ * key file name,
+ *
+ * Returns files based keys store klass.
+ */
+xmlSecKeyStoreId
+files_keys_store_get_klass(void) {
+ return(&files_keys_store_klass);
+}
+
+/**
+ * files_keys_store_find_key:
+ * @store: the pointer to simple keys store.
+ * @name: the desired key name.
+ * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
+ *
+ * Lookups key in the @store. The caller is responsible for destroying
+ * returned key with #xmlSecKeyDestroy function.
+ *
+ * Returns pointer to key or NULL if key not found or an error occurs.
+ */
+static xmlSecKeyPtr
+files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+ xmlSecKeyPtr key;
+ const xmlChar* p;
+
+ assert(store);
+ assert(keyInfoCtx);
+
+ /* it's possible to do not have the key name or desired key type
+ * but we could do nothing in this case */
+ if((name == NULL) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataIdUnknown)){
+ return(NULL);
+ }
+
+ /* we don't want to open files in a folder other than "current";
+ * to prevent it limit the characters in the key name to alpha/digit,
+ * '.', '-' or '_'.
+ */
+ for(p = name; (*p) != '\0'; ++p) {
+ if(!isalnum((*p)) && ((*p) != '.') && ((*p) != '-') && ((*p) != '_')) {
+ return(NULL);
+ }
+ }
+
+ if((keyInfoCtx->keyReq.keyId == xmlSecKeyDataDsaId) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataRsaId)) {
+ /* load key from a pem file, if key is not found then it's an error (is it?) */
+ key = xmlSecCryptoAppKeyLoad(name, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(key == NULL) {
+ fprintf(stderr,"Error: failed to load public pem key from \"%s\"\n", name);
+ return(NULL);
+ }
+ } else {
+ /* otherwise it's a binary key, if key is not found then it's an error (is it?) */
+ key = xmlSecKeyReadBinaryFile(keyInfoCtx->keyReq.keyId, name);
+ if(key == NULL) {
+ fprintf(stderr,"Error: failed to load key from binary file \"%s\"\n", name);
+ return(NULL);
+ }
+ }
+
+ /* set key name */
+ if(xmlSecKeySetName(key, name) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", name);
+ xmlSecKeyDestroy(key);
+ return(NULL);
+ }
+
+ return(key);
+}
+
diff --git a/examples/deskey.bin b/examples/deskey.bin
new file mode 100644
index 00000000..019924a7
--- /dev/null
+++ b/examples/deskey.bin
@@ -0,0 +1 @@
+012345670123456701234567 \ No newline at end of file
diff --git a/examples/encrypt1-res.xml b/examples/encrypt1-res.xml
new file mode 100644
index 00000000..cc436a0e
--- /dev/null
+++ b/examples/encrypt1-res.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!--
+XML Security Library example: Encrypted binary data (encrypt1 example).
+-->
+<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#">
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <KeyName>deskey.bin</KeyName>
+ </KeyInfo>
+ <CipherData>
+ <CipherValue>t6JVBMihIgRyiK8AS8AX5NcXTfkdXPTK</CipherValue>
+ </CipherData>
+</EncryptedData>
diff --git a/examples/encrypt1-tmpl.xml b/examples/encrypt1-tmpl.xml
new file mode 100644
index 00000000..3d61a901
--- /dev/null
+++ b/examples/encrypt1-tmpl.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!--
+XML Security Library example: Simple encryption template file for encrypt1 example.
+-->
+<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#">
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <KeyName/>
+ </KeyInfo>
+ <CipherData>
+ <CipherValue></CipherValue>
+ </CipherData>
+</EncryptedData>
diff --git a/examples/encrypt1.c b/examples/encrypt1.c
new file mode 100644
index 00000000..fb4d103f
--- /dev/null
+++ b/examples/encrypt1.c
@@ -0,0 +1,219 @@
+/**
+ * XML Security Library example: Encrypting data using a template file.
+ *
+ * Encrypts binary data using a template file and a DES key from a binary file
+ *
+ * Usage:
+ * ./encrypt1 <xml-tmpl> <des-key-file>
+ *
+ * Example:
+ * ./encrypt1 encrypt1-tmpl.xml deskey.bin > encrypt1-res.xml
+ *
+ * The result could be decrypted with decrypt1 example:
+ * ./decrypt1 encrypt1-res.xml deskey.bin
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/crypto.h>
+
+int encrypt_file(const char* tmpl_file, const char* key_file,
+ const unsigned char* data, size_t dataSize);
+int
+main(int argc, char **argv) {
+ static const char secret_data[] = "Big secret";
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <tmpl-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(encrypt_file(argv[1], argv[2], secret_data, strlen(secret_data)) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * encrypt_file:
+ * @tmpl_file: the encryption template file name.
+ * @key_file: the Triple DES key file.
+ * @data: the binary data to encrypt.
+ * @dataSize: the binary data size.
+ *
+ * Encrypts binary #data using template from #tmpl_file and DES key from
+ * #key_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+encrypt_file(const char* tmpl_file, const char* key_file,
+ const unsigned char* data, size_t dataSize) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(tmpl_file);
+ assert(key_file);
+ assert(data);
+
+ /* load template */
+ doc = xmlParseFile(tmpl_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file);
+ goto done;
+ }
+
+ /* create encryption context, we don't need keys manager in this example */
+ encCtx = xmlSecEncCtxCreate(NULL);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* load DES key, assuming that there is not password */
+ encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file);
+ if(encCtx->encKey == NULL) {
+ fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* encrypt the data */
+ if(xmlSecEncCtxBinaryEncrypt(encCtx, node, data, dataSize) < 0) {
+ fprintf(stderr,"Error: encryption failed\n");
+ goto done;
+ }
+
+ /* print encrypted data with document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/encrypt2-doc.xml b/examples/encrypt2-doc.xml
new file mode 100644
index 00000000..d01549d8
--- /dev/null
+++ b/examples/encrypt2-doc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Original XML doc file before encryption (encrypt2 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+</Envelope>
diff --git a/examples/encrypt2-res.xml b/examples/encrypt2-res.xml
new file mode 100644
index 00000000..d2a0a573
--- /dev/null
+++ b/examples/encrypt2-res.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Encrypted XML file (encrypt2 example).
+-->
+<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
+<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+<KeyName>deskey.bin</KeyName>
+</KeyInfo>
+<CipherData>
+<CipherValue>WXlDyktaADlUe+PywKwS3KdKlahCteEKxi/hRlHcXNQlGwNGrYKy8aQ6dLtX1bKg
+IgL/XoAQN3B27zD91b1ZLGh6QQ9CjnVD98+hYJ9TPp4piPnII4vGUA==</CipherValue>
+</CipherData>
+</EncryptedData>
diff --git a/examples/encrypt2.c b/examples/encrypt2.c
new file mode 100644
index 00000000..4f1ad588
--- /dev/null
+++ b/examples/encrypt2.c
@@ -0,0 +1,244 @@
+/**
+ * XML Security Library example: Encrypting XML file with a dynamicaly created template.
+ *
+ * Encrypts XML file using a dynamicaly created template file and a DES key
+ * from a binary file
+ *
+ * Usage:
+ * ./encrypt2 <xml-doc> <des-key-file>
+ *
+ * Example:
+ * ./encrypt2 encrypt2-doc.xml deskey.bin > encrypt2-res.xml
+ *
+ * The result could be decrypted with decrypt1 example:
+ * ./decrypt1 encrypt2-res.xml deskey.bin
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/templates.h>
+#include <xmlsec/crypto.h>
+
+int encrypt_file(const char* xml_file, const char* key_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(encrypt_file(argv[1], argv[2]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * encrypt_file:
+ * @xml_file: the encryption template file name.
+ * @key_file: the Triple DES key file.
+ *
+ * Encrypts #xml_file using a dynamicaly created template and DES key from
+ * #key_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+encrypt_file(const char* xml_file, const char* key_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr encDataNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(xml_file);
+ assert(key_file);
+
+ /* load template */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create encryption template to encrypt XML file and replace
+ * its content with encryption result */
+ encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId,
+ NULL, xmlSecTypeEncElement, NULL, NULL);
+ if(encDataNode == NULL) {
+ fprintf(stderr, "Error: failed to create encryption template\n");
+ goto done;
+ }
+
+ /* we want to put encrypted data in the <enc:CipherValue/> node */
+ if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
+ fprintf(stderr, "Error: failed to add CipherValue node\n");
+ goto done;
+ }
+
+ /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed document */
+ keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
+ if(keyInfoNode == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
+ fprintf(stderr, "Error: failed to add key name\n");
+ goto done;
+ }
+
+ /* create encryption context, we don't need keys manager in this example */
+ encCtx = xmlSecEncCtxCreate(NULL);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* load DES key, assuming that there is not password */
+ encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file);
+ if(encCtx->encKey == NULL) {
+ fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(encCtx->encKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* encrypt the data */
+ if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
+ fprintf(stderr,"Error: encryption failed\n");
+ goto done;
+ }
+
+ /* we template is inserted in the doc */
+ encDataNode = NULL;
+
+ /* print encrypted data with document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(encDataNode != NULL) {
+ xmlFreeNode(encDataNode);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/encrypt3-doc.xml b/examples/encrypt3-doc.xml
new file mode 100644
index 00000000..e017c35a
--- /dev/null
+++ b/examples/encrypt3-doc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Original XML doc file before encryption (encrypt3 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+</Envelope>
diff --git a/examples/encrypt3-res.xml b/examples/encrypt3-res.xml
new file mode 100644
index 00000000..bcf7439c
--- /dev/null
+++ b/examples/encrypt3-res.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: XML doc file encrypted with a session DES key (encrypt3 example).
+-->
+<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
+<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
+<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
+<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+<KeyName>rsakey.pem</KeyName>
+</KeyInfo>
+<CipherData>
+<CipherValue>IPiEu9Nv+EsGyvVeXO9nl5iZhhi+uzQH1I3/DTs3+eamBvioyaawRIlvTql7LYL5
+Mi91Qs8ozfW/fWZ8zB8AE2PosaX37SqiuEta68+65/Ed4v1rkGN0Awux8+gJqJmp
+c2kJhzAoQIAIGAW4nTGP9tl9QUHfwKh2KPA104vezk70ijvF7TrbTmhdfmULAuWK
+Tbsg8sXAPhGmPh5KckM2Xe387iPh4ue2+2TGdWqwXygVdvIUIbcIMq6F+/mWlcmf
+Gs5FVI7CTjaLmeyO4ho+FGmicmqH2hEkZW0a2ktDh4BU/MxYF6L7oayrVWDGp2IH
+dzQAwUT2qJcFjElO8xUz3g==</CipherValue>
+</CipherData>
+</EncryptedKey>
+</KeyInfo>
+<CipherData>
+<CipherValue>xrfPSA+BEI+8ca23RN34gtee5lOMx8Cn+ZGWyxitiktdZ1+XREH+57li63VutCwp
+s6ifbZgXIBsFdxPpMBUFlyTWAAO+NLooIwGoczXi14z62lHr7Ck6FA==</CipherValue>
+</CipherData>
+</EncryptedData>
diff --git a/examples/encrypt3.c b/examples/encrypt3.c
new file mode 100644
index 00000000..aa9465a2
--- /dev/null
+++ b/examples/encrypt3.c
@@ -0,0 +1,340 @@
+/**
+ * XML Security Library example: Encrypting XML file with a session key and dynamicaly created template.
+ *
+ * Encrypts XML file using a dynamicaly created template file and a session
+ * DES key (encrypted with an RSA key).
+ *
+ * Usage:
+ * ./encrypt3 <xml-doc> <rsa-pem-key-file>
+ *
+ * Example:
+ * ./encrypt3 encrypt3-doc.xml rsakey.pem > encrypt3-res.xml
+ *
+ * The result could be decrypted with decrypt3 example:
+ * ./decrypt3 encrypt3-res.xml
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/templates.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeysMngrPtr load_rsa_keys(char* key_file);
+int encrypt_file(xmlSecKeysMngrPtr mngr, const char* xml_file, const char* key_name);
+
+int
+main(int argc, char **argv) {
+ xmlSecKeysMngrPtr mngr;
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load keys */
+ mngr = load_rsa_keys(argv[2]);
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ /* we use key filename as key name here */
+ if(encrypt_file(mngr, argv[1], argv[2]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_rsa_keys:
+ * @key_file: the key filename.
+ *
+ * Creates simple keys manager and load RSA key from #key_file in it.
+ * The caller is responsible for destroing returned keys manager using
+ * @xmlSecKeysMngrDestroy.
+ *
+ * Returns the pointer to newly created keys manager or NULL if an error
+ * occurs.
+ */
+xmlSecKeysMngrPtr
+load_rsa_keys(char* key_file) {
+ xmlSecKeysMngrPtr mngr;
+ xmlSecKeyPtr key;
+
+ assert(key_file);
+
+ /* create and initialize keys manager, we use a simple list based
+ * keys manager, implement your own xmlSecKeysStore klass if you need
+ * something more sophisticated
+ */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ return(NULL);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* load private RSA key */
+ key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(key == NULL) {
+ fprintf(stderr,"Error: failed to load rsa key from file \"%s\"\n", key_file);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(key, BAD_CAST key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* add key to keys manager, from now on keys manager is responsible
+ * for destroying key
+ */
+ if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
+ fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", key_file);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ return(mngr);
+}
+
+/**
+ * encrypt_file:
+ * @mngr: the pointer to keys manager.
+ * @xml_file: the encryption template file name.
+ * @key_name: the RSA key name.
+ *
+ * Encrypts #xml_file using a dynamicaly created template, a session DES key
+ * and an RSA key from keys manager.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+encrypt_file(xmlSecKeysMngrPtr mngr, const char* xml_file, const char* key_name) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr encDataNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlNodePtr encKeyNode = NULL;
+ xmlNodePtr keyInfoNode2 = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(xml_file);
+ assert(key_name);
+
+ /* load template */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create encryption template to encrypt XML file and replace
+ * its content with encryption result */
+ encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId,
+ NULL, xmlSecTypeEncElement, NULL, NULL);
+ if(encDataNode == NULL) {
+ fprintf(stderr, "Error: failed to create encryption template\n");
+ goto done;
+ }
+
+ /* we want to put encrypted data in the <enc:CipherValue/> node */
+ if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
+ fprintf(stderr, "Error: failed to add CipherValue node\n");
+ goto done;
+ }
+
+ /* add <dsig:KeyInfo/> */
+ keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
+ if(keyInfoNode == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ /* add <enc:EncryptedKey/> to store the encrypted session key */
+ encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode,
+ xmlSecTransformRsaPkcs1Id,
+ NULL, NULL, NULL);
+ if(encKeyNode == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ /* we want to put encrypted key in the <enc:CipherValue/> node */
+ if(xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
+ fprintf(stderr, "Error: failed to add CipherValue node\n");
+ goto done;
+ }
+
+ /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> */
+ keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
+ if(keyInfoNode2 == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ /* set key name so we can lookup key when needed */
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, key_name) == NULL) {
+ fprintf(stderr, "Error: failed to add key name\n");
+ goto done;
+ }
+
+ /* create encryption context */
+ encCtx = xmlSecEncCtxCreate(mngr);
+ if(encCtx == NULL) {
+ fprintf(stderr,"Error: failed to create encryption context\n");
+ goto done;
+ }
+
+ /* generate a Triple DES key */
+ encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
+ if(encCtx->encKey == NULL) {
+ fprintf(stderr,"Error: failed to generate session des key\n");
+ goto done;
+ }
+
+ /* encrypt the data */
+ if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
+ fprintf(stderr,"Error: encryption failed\n");
+ goto done;
+ }
+
+ /* we template is inserted in the doc */
+ encDataNode = NULL;
+
+ /* print encrypted data with document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+
+ /* cleanup */
+ if(encCtx != NULL) {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ if(encDataNode != NULL) {
+ xmlFreeNode(encDataNode);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/mywin32make.bat b/examples/mywin32make.bat
new file mode 100644
index 00000000..a7d22803
--- /dev/null
+++ b/examples/mywin32make.bat
@@ -0,0 +1,18 @@
+@echo off
+REM
+REM This is my personal configuration file.
+REM I am lazy to type all this crap again and again
+REM You are welcome to customize this file for your
+REM needs but do not check it into the CVS, please.
+REM
+REM Aleksey Sanin <aleksey@aleksey.com>
+REM
+
+SET XMLSEC_PREFIX=C:\cygwin\home\local
+SET XMLSEC_INCLUDE=%XMLSEC_PREFIX%\include
+SET XMLSEC_LIB=%XMLSEC_PREFIX%\lib
+
+SET INCLUDE=%XMLSEC_INCLUDE%;%INCLUDE%
+SET LIB=%XMLSEC_LIB%;%LIB%
+
+nmake -f Makefile.w32 %1 %2 %3
diff --git a/examples/rootcert.pem b/examples/rootcert.pem
new file mode 100644
index 00000000..38144d65
--- /dev/null
+++ b/examples/rootcert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEPDCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAyMDIwMjA4MDAzOFoXDTEyMDEzMTA4MDAzOFowgcsxCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTdW5ueXZhbGUxPTA7BgNVBAoT
+NFhNTCBTZWN1cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3ht
+bHNlYykxGTAXBgNVBAsTEFJvb3QgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtz
+ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvSvv4RNOzsjL+FQEoMwkidOOjJQciB2x
+WxI1QPkwFVC5Z86BcQugOWVJ+4JVTtE2uDjFElNI9SMINhd+4GkxlK+TVHvSZfCT
+Ia/EichBfRfZcPjVnXH3pzFCC9JkbGOIFAzuhBcz+KvN8gntuumolN2/fBYCbFZX
+4otzgMd5Rm8CAwEAAaOCASwwggEoMB0GA1UdDgQWBBS0ue+a5pcOaGUemM76VQ2J
+BttMfDCB+AYDVR0jBIHwMIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCB
+yzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1
+bm55dmFsZTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93
+d3cuYWxla3NleS5jb20veG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0
+ZTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2Vj
+QGFsZWtzZXkuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEA
+J/+WEipxRms7bdg0ORf+ipHNwgdvWDxaLeQqqKMSacHDFVZyKdurm4onypNI2w9K
+Gk6XKipJT67ew4QpVMgv5LAIoErMxIcVYu1tAfhjtNK5neF6X5v/r/cRQkdIYaaF
+BlnBUmHY6x83aiSMC2ASG2MKL8UDqF/y2/SlPuxmG50=
+-----END CERTIFICATE-----
diff --git a/examples/rsacert.pem b/examples/rsacert.pem
new file mode 100644
index 00000000..02489a43
--- /dev/null
+++ b/examples/rsacert.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 5 (0x5)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=California, L=Sunnyvale, O=XML Security Library (http://www.aleksey.com/xmlsec), OU=Root Certificate, CN=Aleksey Sanin/emailAddress=xmlsec@aleksey.com
+ Validity
+ Not Before: Mar 31 04:02:22 2003 GMT
+ Not After : Mar 28 04:02:22 2013 GMT
+ Subject: C=US, ST=California, O=XML Security Library (http://www.aleksey.com/xmlsec), OU=Examples RSA Certificate, CN=Aleksey Sanin/emailAddress=xmlsec@aleksey.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:97:b8:fe:b4:3f:83:35:78:16:89:04:ec:2b:61:
+ 8c:bf:c4:5f:00:81:4a:45:e6:d9:cd:e9:e2:3c:97:
+ 3b:45:ad:aa:e6:8d:0b:77:71:07:01:4f:7c:f9:7d:
+ e2:19:aa:dd:91:59:f4:f1:cf:3d:ba:78:46:96:11:
+ 9c:b6:5b:46:39:73:55:23:aa:f7:9e:00:5c:e5:e9:
+ 49:ec:3b:9c:3f:84:99:3a:90:ad:df:7e:64:86:c6:
+ 26:72:ce:31:08:79:7e:13:15:b8:e5:bf:d6:56:02:
+ 8d:60:21:4c:27:18:64:fb:fb:55:70:f6:33:bd:2f:
+ 55:70:d5:5e:7e:99:ae:a4:e0:aa:45:47:13:a8:30:
+ d5:a0:8a:9d:cc:20:ec:e4:8e:51:c9:54:c5:7f:3e:
+ 66:2d:74:bf:a3:7a:f8:f3:ec:94:57:39:b4:ac:00:
+ 75:62:61:54:b4:d0:e0:52:86:f8:5e:77:ec:50:43:
+ 9c:d2:ba:a7:8c:62:5a:bc:b2:fe:f3:cc:62:7e:23:
+ 60:6b:c7:51:49:37:78:7e:25:15:30:ab:fa:b4:ae:
+ 25:8f:22:fc:a3:48:7f:f2:0a:8a:6e:e0:fe:8d:f0:
+ 01:ed:c6:33:cc:6b:a1:fd:a6:80:ef:06:8c:af:f6:
+ 40:3a:8e:42:14:20:61:12:1f:e3:fc:05:b1:05:d5:
+ 65:c3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 24:84:2C:F2:D4:59:20:62:8B:2E:5C:86:90:A3:AA:30:BA:27:1A:9C
+ X509v3 Authority Key Identifier:
+ keyid:B4:B9:EF:9A:E6:97:0E:68:65:1E:98:CE:FA:55:0D:89:06:DB:4C:7C
+ DirName:/C=US/ST=California/L=Sunnyvale/O=XML Security Library (http://www.aleksey.com/xmlsec)/OU=Root Certificate/CN=Aleksey Sanin/emailAddress=xmlsec@aleksey.com
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ b5:3f:9b:32:31:4a:ff:2f:84:3b:a8:9b:11:5c:a6:5c:f0:76:
+ 52:d9:6e:f4:90:ad:fa:0d:90:c1:98:d5:4a:12:dd:82:6b:37:
+ e8:d9:2d:62:92:c9:61:37:98:86:8f:a4:49:6a:5e:25:d0:18:
+ 69:30:0f:98:8f:43:58:89:31:b2:3b:05:e2:ef:c7:a6:71:5f:
+ f7:fe:73:c5:a7:b2:cd:2e:73:53:71:7d:a8:4c:68:1a:32:1b:
+ 5e:48:2f:8f:9b:7a:a3:b5:f3:67:e8:b1:a2:89:4e:b2:4d:1b:
+ 79:9c:ff:f0:0d:19:4f:4e:b1:03:3d:99:f0:44:b7:8a:0b:34:
+ 9d:83
+-----BEGIN CERTIFICATE-----
+MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D
+-----END CERTIFICATE-----
diff --git a/examples/rsakey.pem b/examples/rsakey.pem
new file mode 100644
index 00000000..55d2fd9b
--- /dev/null
+++ b/examples/rsakey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAl7j+tD+DNXgWiQTsK2GMv8RfAIFKRebZzeniPJc7Ra2q5o0L
+d3EHAU98+X3iGardkVn08c89unhGlhGctltGOXNVI6r3ngBc5elJ7DucP4SZOpCt
+335khsYmcs4xCHl+ExW45b/WVgKNYCFMJxhk+/tVcPYzvS9VcNVefpmupOCqRUcT
+qDDVoIqdzCDs5I5RyVTFfz5mLXS/o3r48+yUVzm0rAB1YmFUtNDgUob4XnfsUEOc
+0rqnjGJavLL+88xifiNga8dRSTd4fiUVMKv6tK4ljyL8o0h/8gqKbuD+jfAB7cYz
+zGuh/aaA7waMr/ZAOo5CFCBhEh/j/AWxBdVlwwIDAQABAoIBAQCAvt6DnZF9gdW9
+l4vAlBqXb88d4phgELCp5tmviLUnP2NSGEWuqR7Eoeru2z9NgIxblvYfazh6Ty22
+kmNk6rcAcTnB9oYAcVZjUj8EUuEXlTFhXPvuNpafNu3RZd59znqJP1mSu+LpQWku
+NZMlabHnkTLDlGf7FXtvL9/rlgV4qk3QcDVF793JFszWrtK3mnld3KHQ6cuo9iSm
+0rQKtkDjeHsRell8qTQvfBsgG1q2bv8QWT45/eQrra9mMbGTr3DbnXvoeJmTj1VN
+XJV7tBNllxxPahlYMByJaf/Tuva5j6HWUEIfYky5ihr2z1P/fNQ2OSCM6SQHpkiG
+EXQDueXBAoGBAMfW7KcmToEQEcTiqfey6C1LOLoemcX0/ROUktPq/5JQJRRrT4t7
+XevLX0ed8sLyR5T29XQtdnuV0DJfvcJD+6ZwfOcQ+f6ZzCaNXJP97JtEt5kSWY01
+Ei+nphZ0RFvPb04V3qDU9dElU26GR36CRBYJyM2WQPx4v+/YyDSZH9kLAoGBAMJc
+ZBU8pRbIia/FFOHUlS3v5P18nVmXyOd0fvRq0ZelaQCebTZ4K9wjnCfw//yzkb2Z
+0vZFNB+xVBKB0Pt6nVvnSNzxdQ8EAXVFwHtXa25FUyP2RERQgTvmajqmgWjZsDYp
+6GHcK3ZhmdmscQHF/Q2Uo4scvBcheahm9IXiNskpAoGAXelEgTBhSAmTMCEMmti6
+fz6QQ/bJcNu2apMxhOE0hT+gjT34vaWV9481EWTKho5w0TJVGumaem1mz6VqeXaV
+Nhw6tiOmN91ysNNRpEJ6BGWAmjCjYNaF21s/k+HDlhmfRuTEIHSzqDuQP6pewrbY
+5Dpo4SQxGfRsznvjacRj0Q0CgYBN247oBvQnDUxCkhNMZ8kersOvW5T4x9neBge5
+R3UQZ12Jtu0O7dK8C7PJODyDcTeHmTAuIQjBTVrdUw1xP+v7XcoNX9hBnJws6zUw
+85MAiFrGxCcSqqEqaqHRPtQGOXXiLKV/ViA++tgTn4VhbXtyTkG5P1iFd45xjFSV
+sUm7CQKBgDn92tHxzePly1L1mK584TkVryx4cP9RFHpebnmNduGwwjnRuYipoj8y
+pPPAkVbbaA3f9OB2go48rN0Ft9nHdlqgh9BpIKCVtkIb1XN0K3Oa/8BW8W/GAiNG
+HJcsrOtIrGVRdlyJG6bDaN8T49DnhOcsqMbf+IkIvfh50VeE9L/e
+-----END RSA PRIVATE KEY-----
diff --git a/examples/rsapub.pem b/examples/rsapub.pem
new file mode 100644
index 00000000..838a346d
--- /dev/null
+++ b/examples/rsapub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl7j+tD+DNXgWiQTsK2GM
+v8RfAIFKRebZzeniPJc7Ra2q5o0Ld3EHAU98+X3iGardkVn08c89unhGlhGctltG
+OXNVI6r3ngBc5elJ7DucP4SZOpCt335khsYmcs4xCHl+ExW45b/WVgKNYCFMJxhk
++/tVcPYzvS9VcNVefpmupOCqRUcTqDDVoIqdzCDs5I5RyVTFfz5mLXS/o3r48+yU
+Vzm0rAB1YmFUtNDgUob4XnfsUEOc0rqnjGJavLL+88xifiNga8dRSTd4fiUVMKv6
+tK4ljyL8o0h/8gqKbuD+jfAB7cYzzGuh/aaA7waMr/ZAOo5CFCBhEh/j/AWxBdVl
+wwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/examples/sign1-res.xml b/examples/sign1-res.xml
new file mode 100644
index 00000000..04d8fed0
--- /dev/null
+++ b/examples/sign1-res.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Signed file (sign1 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <Reference URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <DigestValue>9H/rQr2Axe9hYTV2n/tCp+3UIQQ=</DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue>Mx4psIy9/UY+u8QBJRDrwQWKRaCGz0WOVftyDzAe6WHAFSjMNr7qb2ojq9kdipT8
+Oub5q2OQ7mzdSLiiejkrO1VeqM/90yEIGI4En6KEB6ArEzw+iq4N1wm6EptcyxXx
+M9StAOOa9ilWYqR9Tfx3SW1urUIuKYgUitxsONiUHBVaW6HeX51bsXoTF++4ZI+D
+jiPBjN4HHmr0cbJ6BXk91S27ffZIfp1Qj5nL9onFLUGbR6EFgu2luiRzQbPuM2tP
+XxyI7GZ8AfHnRJK28ARvBC9oi+O1ej20S79CIV7gdBxbLbFprozBHAwOEC57YgJc
+x+YEjSjcO7SBIR1FiUA7pw==</SignatureValue>
+ <KeyInfo>
+ <KeyName>rsakey.pem</KeyName>
+ </KeyInfo>
+ </Signature>
+</Envelope>
diff --git a/examples/sign1-tmpl.xml b/examples/sign1-tmpl.xml
new file mode 100644
index 00000000..ac71a949
--- /dev/null
+++ b/examples/sign1-tmpl.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Simple signature template file for sign1 example.
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
+ <Reference URI="">
+ <Transforms>
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ </Transforms>
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <DigestValue></DigestValue>
+ </Reference>
+ </SignedInfo>
+ <SignatureValue/>
+ <KeyInfo>
+ <KeyName/>
+ </KeyInfo>
+ </Signature>
+</Envelope>
+
diff --git a/examples/sign1.c b/examples/sign1.c
new file mode 100644
index 00000000..e545843f
--- /dev/null
+++ b/examples/sign1.c
@@ -0,0 +1,212 @@
+/**
+ * XML Security Library example: Signing a template file.
+ *
+ * Signs a template file using a key from PEM file
+ *
+ * Usage:
+ * ./sign1 <xml-tmpl> <pem-key>
+ *
+ * Example:
+ * ./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml
+ *
+ * The result signature could be validated using verify1 example:
+ * ./verify1 sign1-res.xml rsapub.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+int sign_file(const char* tmpl_file, const char* key_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <tmpl-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(sign_file(argv[1], argv[2]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * sign_file:
+ * @tmpl_file: the signature template file name.
+ * @key_file: the PEM private key file name.
+ *
+ * Signs the #tmpl_file using private key from #key_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+sign_file(const char* tmpl_file, const char* key_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(tmpl_file);
+ assert(key_file);
+
+ /* load template */
+ doc = xmlParseFile(tmpl_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file);
+ goto done;
+ }
+
+ /* create signature context, we don't need keys manager in this example */
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* load private key, assuming that there is not password */
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(dsigCtx->signKey == NULL) {
+ fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* sign the template */
+ if(xmlSecDSigCtxSign(dsigCtx, node) < 0) {
+ fprintf(stderr,"Error: signature failed\n");
+ goto done;
+ }
+
+ /* print signed document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/sign2-doc.xml b/examples/sign2-doc.xml
new file mode 100644
index 00000000..5d9fb352
--- /dev/null
+++ b/examples/sign2-doc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Original XML doc file for sign2 example.
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+</Envelope>
diff --git a/examples/sign2-res.xml b/examples/sign2-res.xml
new file mode 100644
index 00000000..b37cad94
--- /dev/null
+++ b/examples/sign2-res.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Signed XML doc file (sign2 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<Reference>
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
+D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
+XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
+T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
+JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
+3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
+<KeyInfo>
+<KeyName>rsakey.pem</KeyName>
+</KeyInfo>
+</Signature></Envelope>
diff --git a/examples/sign2.c b/examples/sign2.c
new file mode 100644
index 00000000..146bbbaa
--- /dev/null
+++ b/examples/sign2.c
@@ -0,0 +1,248 @@
+/**
+ * XML Security Library example: Signing a file with a dynamicaly created template.
+ *
+ * Signs a file using a dynamicaly created template and key from PEM file.
+ * The signature has one reference with one enveloped transform to sign
+ * the whole document except the <dsig:Signature/> node itself.
+ *
+ * Usage:
+ * sign2 <xml-doc> <pem-key>
+ *
+ * Example:
+ * ./sign2 sign2-doc.xml rsakey.pem > sign2-res.xml
+ *
+ * The result signature could be validated using verify1 example:
+ * ./verify1 sign2-res.xml rsapub.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/templates.h>
+#include <xmlsec/crypto.h>
+
+int sign_file(const char* xml_file, const char* key_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(sign_file(argv[1], argv[2]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * sign_file:
+ * @xml_file: the XML file name.
+ * @key_file: the PEM private key file name.
+ *
+ * Signs the #xml_file using private key from #key_file and dynamicaly
+ * created enveloped signature template.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+sign_file(const char* xml_file, const char* key_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr signNode = NULL;
+ xmlNodePtr refNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(xml_file);
+ assert(key_file);
+
+ /* load doc file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature template for RSA-SHA1 enveloped signature */
+ signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
+ xmlSecTransformRsaSha1Id, NULL);
+ if(signNode == NULL) {
+ fprintf(stderr, "Error: failed to create signature template\n");
+ goto done;
+ }
+
+ /* add <dsig:Signature/> node to the doc */
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
+
+ /* add reference */
+ refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
+ NULL, NULL, NULL);
+ if(refNode == NULL) {
+ fprintf(stderr, "Error: failed to add reference to signature template\n");
+ goto done;
+ }
+
+ /* add enveloped transform */
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
+ fprintf(stderr, "Error: failed to add enveloped transform to reference\n");
+ goto done;
+ }
+
+ /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed document */
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
+ if(keyInfoNode == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
+ fprintf(stderr, "Error: failed to add key name\n");
+ goto done;
+ }
+
+ /* create signature context, we don't need keys manager in this example */
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* load private key, assuming that there is not password */
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(dsigCtx->signKey == NULL) {
+ fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* sign the template */
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
+ fprintf(stderr,"Error: signature failed\n");
+ goto done;
+ }
+
+ /* print signed document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/sign3-doc.xml b/examples/sign3-doc.xml
new file mode 100644
index 00000000..f75da16a
--- /dev/null
+++ b/examples/sign3-doc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Original XML doc file for sign3 example.
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+</Envelope>
diff --git a/examples/sign3-res.xml b/examples/sign3-res.xml
new file mode 100644
index 00000000..847e1af2
--- /dev/null
+++ b/examples/sign3-res.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: Signed XML doc file (sign3 example).
+-->
+<Envelope xmlns="urn:envelope">
+ <Data>
+ Hello, World!
+ </Data>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+<Reference>
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+<DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
+D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
+XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
+T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
+JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
+3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D</X509Certificate>
+</X509Data>
+</KeyInfo>
+</Signature></Envelope>
diff --git a/examples/sign3.c b/examples/sign3.c
new file mode 100644
index 00000000..9d16cf72
--- /dev/null
+++ b/examples/sign3.c
@@ -0,0 +1,261 @@
+/**
+ * XML Security Library example: Signing a file with a dynamicaly created template and an X509 certificate.
+ *
+ * Signs a file using a dynamicaly created template, key from PEM file and
+ * an X509 certificate. The signature has one reference with one enveloped
+ * transform to sign the whole document except the <dsig:Signature/> node
+ * itself. The key certificate is written in the <dsig:X509Data/> node.
+ *
+ * This example was developed and tested with OpenSSL crypto library. The
+ * certificates management policies for another crypto library may break it.
+ *
+ * Usage:
+ * sign3 <xml-doc> <pem-key>
+ *
+ * Example:
+ * ./sign3 sign3-doc.xml rsakey.pem rsacert.pem > sign3-res.xml
+ *
+ * The result signature could be validated using verify3 example:
+ * ./verify3 sign3-res.xml rootcert.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/templates.h>
+#include <xmlsec/crypto.h>
+
+int sign_file(const char* xml_file, const char* key_file, const char* cert_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 4) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file> <cert-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(sign_file(argv[1], argv[2], argv[3]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * sign_file:
+ * @xml_file: the XML file name.
+ * @key_file: the PEM private key file name.
+ * @cert_file: the x509 certificate PEM file.
+ *
+ * Signs the @xml_file using private key from @key_file and dynamicaly
+ * created enveloped signature template. The certificate from @cert_file
+ * is placed in the <dsig:X509Data/> node.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+sign_file(const char* xml_file, const char* key_file, const char* cert_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr signNode = NULL;
+ xmlNodePtr refNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(xml_file);
+ assert(key_file);
+ assert(cert_file);
+
+ /* load doc file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature template for RSA-SHA1 enveloped signature */
+ signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
+ xmlSecTransformRsaSha1Id, NULL);
+ if(signNode == NULL) {
+ fprintf(stderr, "Error: failed to create signature template\n");
+ goto done;
+ }
+
+ /* add <dsig:Signature/> node to the doc */
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
+
+ /* add reference */
+ refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
+ NULL, NULL, NULL);
+ if(refNode == NULL) {
+ fprintf(stderr, "Error: failed to add reference to signature template\n");
+ goto done;
+ }
+
+ /* add enveloped transform */
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
+ fprintf(stderr, "Error: failed to add enveloped transform to reference\n");
+ goto done;
+ }
+
+ /* add <dsig:KeyInfo/> and <dsig:X509Data/> */
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
+ if(keyInfoNode == NULL) {
+ fprintf(stderr, "Error: failed to add key info\n");
+ goto done;
+ }
+
+ if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
+ fprintf(stderr, "Error: failed to add X509Data node\n");
+ goto done;
+ }
+
+ /* create signature context, we don't need keys manager in this example */
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* load private key, assuming that there is not password */
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(dsigCtx->signKey == NULL) {
+ fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* load certificate and add to the key */
+ if(xmlSecCryptoAppKeyCertLoad(dsigCtx->signKey, cert_file, xmlSecKeyDataFormatPem) < 0) {
+ fprintf(stderr,"Error: failed to load pem certificate \"%s\"\n", cert_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* sign the template */
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
+ fprintf(stderr,"Error: signature failed\n");
+ goto done;
+ }
+
+ /* print signed document to stdout */
+ xmlDocDump(stdout, doc);
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
diff --git a/examples/verify1.c b/examples/verify1.c
new file mode 100644
index 00000000..04917e5a
--- /dev/null
+++ b/examples/verify1.c
@@ -0,0 +1,215 @@
+/**
+ * XML Security Library example: Verifying a file using a single key.
+ *
+ * Verifies a file using a key from PEM file.
+ *
+ * Usage:
+ * verify1 <signed-file> <pem-key>
+ *
+ * Example:
+ * ./verify1 sign1-res.xml rsapub.pem
+ * ./verify1 sign2-res.xml rsapub.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+int verify_file(const char* xml_file, const char* key_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ assert(argv);
+
+ if(argc != 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file>\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ if(verify_file(argv[1], argv[2]) < 0) {
+ return(-1);
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * verify_file:
+ * @xml_file: the signed XML file name.
+ * @key_file: the PEM public key file name.
+ *
+ * Verifies XML signature in #xml_file using public key from #key_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+verify_file(const char* xml_file, const char* key_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(xml_file);
+ assert(key_file);
+
+ /* load file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature context, we don't need keys manager in this example */
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* load public key */
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(dsigCtx->signKey == NULL) {
+ fprintf(stderr,"Error: failed to load public pem key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
+ goto done;
+ }
+
+ /* Verify signature */
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ fprintf(stderr,"Error: signature verify\n");
+ goto done;
+ }
+
+ /* print verification result to stdout */
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ fprintf(stdout, "Signature is OK\n");
+ } else {
+ fprintf(stdout, "Signature is INVALID\n");
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
+
diff --git a/examples/verify2.c b/examples/verify2.c
new file mode 100644
index 00000000..36fde2d3
--- /dev/null
+++ b/examples/verify2.c
@@ -0,0 +1,285 @@
+/**
+ * XML Security Library example: Verifying a file using keys manager.
+ *
+ * Verifies a file using keys manager
+ *
+ * Usage:
+ * verify2 <signed-file> <public-pem-key1> [<public-pem-key2> [...]]
+ *
+ * Example:
+ * ./verify2 sign1-res.xml rsapub.pem
+ * ./verify2 sign2-res.xml rsapub.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeysMngrPtr load_keys(char** files, int files_size);
+int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ xmlSecKeysMngrPtr mngr;
+
+ assert(argv);
+
+ if(argc < 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <key-file1> [<key-file2> [...]]\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load keys */
+ mngr = load_keys(&(argv[2]), argc - 2);
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ /* verify file */
+ if(verify_file(mngr, argv[1]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_keys:
+ * @files: the list of filenames.
+ * @files_size: the number of filenames in #files.
+ *
+ * Creates simple keys manager and load PEM keys from #files in it.
+ * The caller is responsible for destroing returned keys manager using
+ * @xmlSecKeysMngrDestroy.
+ *
+ * Returns the pointer to newly created keys manager or NULL if an error
+ * occurs.
+ */
+xmlSecKeysMngrPtr
+load_keys(char** files, int files_size) {
+ xmlSecKeysMngrPtr mngr;
+ xmlSecKeyPtr key;
+ int i;
+
+ assert(files);
+ assert(files_size > 0);
+
+ /* create and initialize keys manager, we use a simple list based
+ * keys manager, implement your own xmlSecKeysStore klass if you need
+ * something more sophisticated
+ */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ return(NULL);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ for(i = 0; i < files_size; ++i) {
+ assert(files[i]);
+
+ /* load key */
+ key = xmlSecCryptoAppKeyLoad(files[i], xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if(key == NULL) {
+ fprintf(stderr,"Error: failed to load pem key from \"%s\"\n", files[i]);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* set key name to the file name, this is just an example! */
+ if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) {
+ fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ /* add key to keys manager, from now on keys manager is responsible
+ * for destroying key
+ */
+ if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
+ fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]);
+ xmlSecKeyDestroy(key);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+ }
+
+ return(mngr);
+}
+
+/**
+ * verify_file:
+ * @mngr: the pointer to keys manager.
+ * @xml_file: the signed XML file name.
+ *
+ * Verifies XML signature in #xml_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(xml_file);
+
+ /* load file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature context */
+ dsigCtx = xmlSecDSigCtxCreate(mngr);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* Verify signature */
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ fprintf(stderr,"Error: signature verify\n");
+ goto done;
+ }
+
+ /* print verification result to stdout */
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ fprintf(stdout, "Signature is OK\n");
+ } else {
+ fprintf(stdout, "Signature is INVALID\n");
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
+
diff --git a/examples/verify3.c b/examples/verify3.c
new file mode 100644
index 00000000..5f0666bb
--- /dev/null
+++ b/examples/verify3.c
@@ -0,0 +1,266 @@
+/**
+ * XML Security Library example: Verifying a file signed with X509 certificate
+ *
+ * Verifies a file signed with X509 certificate.
+ *
+ * This example was developed and tested with OpenSSL crypto library. The
+ * certificates management policies for another crypto library may break it.
+ *
+ * Usage:
+ * verify3 <signed-file> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
+ *
+ * Example:
+ * ./verify3 sign3-res.xml rootcert.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeysMngrPtr load_trusted_certs(char** files, int files_size);
+int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+ xmlSecKeysMngrPtr mngr;
+
+ assert(argv);
+
+ if(argc < 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <cert-file1> [<cert-file2> [...]]\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load trusted certificates */
+ mngr = load_trusted_certs(&(argv[2]), argc - 2);
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ /* verify file */
+ if(verify_file(mngr, argv[1]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_trusted_certs:
+ * @files: the list of filenames.
+ * @files_size: the number of filenames in #files.
+ *
+ * Creates simple keys manager and load trusted certificates from PEM #files.
+ * The caller is responsible for destroing returned keys manager using
+ * @xmlSecKeysMngrDestroy.
+ *
+ * Returns the pointer to newly created keys manager or NULL if an error
+ * occurs.
+ */
+xmlSecKeysMngrPtr
+load_trusted_certs(char** files, int files_size) {
+ xmlSecKeysMngrPtr mngr;
+ int i;
+
+ assert(files);
+ assert(files_size > 0);
+
+ /* create and initialize keys manager, we use a simple list based
+ * keys manager, implement your own xmlSecKeysStore klass if you need
+ * something more sophisticated
+ */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ return(NULL);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ for(i = 0; i < files_size; ++i) {
+ assert(files[i]);
+
+ /* load trusted cert */
+ if(xmlSecCryptoAppKeysMngrCertLoad(mngr, files[i], xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) {
+ fprintf(stderr,"Error: failed to load pem certificate from \"%s\"\n", files[i]);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+ }
+
+ return(mngr);
+}
+
+/**
+ * verify_file:
+ * @mngr: the pointer to keys manager.
+ * @xml_file: the signed XML file name.
+ *
+ * Verifies XML signature in #xml_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(xml_file);
+
+ /* load file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature context */
+ dsigCtx = xmlSecDSigCtxCreate(mngr);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* Verify signature */
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ fprintf(stderr,"Error: signature verify\n");
+ goto done;
+ }
+
+ /* print verification result to stdout */
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ fprintf(stdout, "Signature is OK\n");
+ } else {
+ fprintf(stdout, "Signature is INVALID\n");
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
+
diff --git a/examples/verify4-bad-res.xml b/examples/verify4-bad-res.xml
new file mode 100644
index 00000000..15928e2c
--- /dev/null
+++ b/examples/verify4-bad-res.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: A simple bad SAML response (verify4 example).
+
+This file could be verified with verify3 example (signature is valid)
+but verify4 example fails because of XPath transform which is not allowed
+in a simple SAML response.
+
+This file was created from a template with the following command (replace __ with double dashes):
+ ../apps/xmlsec sign __privkey rsakey.pem,rsacert.pem __output verify4-bad-res.xml verify4-bad-tmpl.xml
+-->
+<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2002-04-18T16:56:54Z" MajorVersion="1" MinorVersion="0" Recipient="https://shire.target.com" ResponseID="7ddc31-ed4a03d703-FB24AD27D96135B68C99FB9AACFE2FFC">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath xmlns:samlp_xpath="urn:oasis:names:tc:SAML:1.0:protocol">
+ count(ancestor-or-self::samlp_xpath:Response |
+ here()/ancestor::samlp_xpath:Response[1]) =
+ count(ancestor-or-self::samlp_xpath:Response)
+ </dsig:XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>t1nvDq1bZXEhBIXc/DHcqIrjRyI=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>PipZFFmmYcSnSU9p5AcOmFbRYoeatERYPy4IRk+jU26xk9sAM6yfhXtbK8csl/0w
+rjODj1jGcydBGP9I8kFAfHyZ+Ls+A+53oMNl+tGWfe8iICMowIU1HCxJtPrgbTKk
+1gc+VnYJ3IXhoVneeQKqzilXwA5X7FW7hgIecb5KwLShYV3iO8+z8pzt3NEGKAGQ
+p/lQmO3EQR4Zu0bCSOk6zXdlOhe5dPVFXJQLlE8Zz3WjGQNo0l4op0ZXKf1B+syH
+blHx0tnPQDtSBzQdKohJV39UgkGnL3rd5ggBzyXemjMTX8eFxNZ7bh4UgZ+Wo74W
+Zb4ompTc2ImxJfbpszWp8w==</dsig:SignatureValue>
+ <dsig:KeyInfo>
+ <dsig:X509Data>
+<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D</X509Certificate>
+</dsig:X509Data>
+ </dsig:KeyInfo>
+ </dsig:Signature>
+ <Status>
+ <StatusCode Value="samlp:Success"/>
+ </Status>
+ <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="7ddc31-ed4a03d735-FB24AD27D96135B68C99FB9AACFE2FFC" IssueInstant="2002-04-18T16:56:54Z" Issuer="hs.osu.edu" MajorVersion="1" MinorVersion="0">
+ <Conditions NotBefore="2002-04-18T16:56:54Z" NotOnOrAfter="2002-04-18T17:01:54Z">
+ <AudienceRestrictionCondition>
+ <Audience>http://middleware.internet2.edu/shibboleth/clubs/clubshib/1.0/</Audience>
+ </AudienceRestrictionCondition>
+ </Conditions>
+ <AuthenticationStatement AuthenticationInstant="2002-04-18T16:56:53Z" AuthenticationMethod="urn:mace:shibboleth:authmethod">
+ <Subject>
+ <NameIdentifier Format="urn:mace:shibboleth:1.0:handle" NameQualifier="osu.edu">foo</NameIdentifier>
+ <SubjectConfirmation>
+ <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:Bearer</ConfirmationMethod>
+ </SubjectConfirmation>
+ </Subject>
+ <SubjectLocality IPAddress="127.0.0.1"/>
+ <AuthorityBinding AuthorityKind="samlp:AttributeQuery" Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://aa.osu.edu/"/>
+ </AuthenticationStatement>
+ </Assertion>
+</Response>
diff --git a/examples/verify4-bad-tmpl.xml b/examples/verify4-bad-tmpl.xml
new file mode 100644
index 00000000..5cd026f3
--- /dev/null
+++ b/examples/verify4-bad-tmpl.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: A simple bad SAML response template (verify4 example).
+
+Sign it using the following command (replace __ with double dashes):
+
+ ../apps/xmlsec sign __privkey rsakey.pem,rsacert.pem __output verify4--bad-res.xml verify4-bad-tmpl.xml
+-->
+<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2002-04-18T16:56:54Z" MajorVersion="1" MinorVersion="0" Recipient="https://shire.target.com" ResponseID="7ddc31-ed4a03d703-FB24AD27D96135B68C99FB9AACFE2FFC">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath xmlns:samlp_xpath="urn:oasis:names:tc:SAML:1.0:protocol" >
+ count(ancestor-or-self::samlp_xpath:Response |
+ here()/ancestor::samlp_xpath:Response[1]) =
+ count(ancestor-or-self::samlp_xpath:Response)
+ </dsig:XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue/>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue/>
+ <dsig:KeyInfo>
+ <dsig:X509Data/>
+ </dsig:KeyInfo>
+ </dsig:Signature>
+ <Status>
+ <StatusCode Value="samlp:Success"/>
+ </Status>
+ <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="7ddc31-ed4a03d735-FB24AD27D96135B68C99FB9AACFE2FFC" IssueInstant="2002-04-18T16:56:54Z" Issuer="hs.osu.edu" MajorVersion="1" MinorVersion="0">
+ <Conditions NotBefore="2002-04-18T16:56:54Z" NotOnOrAfter="2002-04-18T17:01:54Z">
+ <AudienceRestrictionCondition>
+ <Audience>http://middleware.internet2.edu/shibboleth/clubs/clubshib/1.0/</Audience>
+ </AudienceRestrictionCondition>
+ </Conditions>
+ <AuthenticationStatement AuthenticationInstant="2002-04-18T16:56:53Z" AuthenticationMethod="urn:mace:shibboleth:authmethod">
+ <Subject>
+ <NameIdentifier Format="urn:mace:shibboleth:1.0:handle" NameQualifier="osu.edu">foo</NameIdentifier>
+ <SubjectConfirmation>
+ <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:Bearer</ConfirmationMethod>
+ </SubjectConfirmation>
+ </Subject>
+ <SubjectLocality IPAddress="127.0.0.1"/>
+ <AuthorityBinding AuthorityKind="samlp:AttributeQuery" Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://aa.osu.edu/"/>
+ </AuthenticationStatement>
+ </Assertion>
+</Response>
diff --git a/examples/verify4-res.xml b/examples/verify4-res.xml
new file mode 100644
index 00000000..7abe539f
--- /dev/null
+++ b/examples/verify4-res.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: A simple SAML response template (verify4 example).
+
+This file was signed using the following command (replace __ with double dashes):
+
+ ../apps/xmlsec sign __privkey rsakey.pem,rsacert.pem __output verify4-res.xml verify4-tmpl.xml
+-->
+<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2002-04-18T16:56:54Z" MajorVersion="1" MinorVersion="0" Recipient="https://shire.target.com" ResponseID="7ddc31-ed4a03d703-FB24AD27D96135B68C99FB9AACFE2FFC">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>t1nvDq1bZXEhBIXc/DHcqIrjRyI=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>EsNm7mOj9XY6pq1bfeuzFd1F/LQwbc1K/YgOYgrElk4tr8BhSd5OcrzXBgsivPvm
+HpjvSOBkjctGOFVE7x+6+G8TMudTja1IchEmGMh+pjMBlGNpvxSTedwtnoZBGWAz
+RlfRhRFThskup0T7Or+VBHYygPGM3gmwX0ZWVYpNzM/rfYSk7+obgIp9DxLDIXlW
+oLrJGVivubE+T63CPfBPaUIv1CbfBAzdo+11+8CiVsdWn2qwtGe5Fsmc3eCg06Oj
+sl1nyCIu3AONq1w8jIPOgmITF8PpwDm0+XoQUH0P4kHJqNLphnJZY+GlPAC6VlAW
+2bcAFr4Ul5yzHUBpxCDZfg==</dsig:SignatureValue>
+ <dsig:KeyInfo>
+ <dsig:X509Data>
+<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">MIIE3zCCBEigAwIBAgIBBTANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMB4X
+DTAzMDMzMTA0MDIyMloXDTEzMDMyODA0MDIyMlowgb8xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFy
+eSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMSEwHwYDVQQLExhFeGFt
+cGxlcyBSU0EgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
+BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAJe4/rQ/gzV4FokE7CthjL/EXwCBSkXm2c3p4jyXO0Wt
+quaNC3dxBwFPfPl94hmq3ZFZ9PHPPbp4RpYRnLZbRjlzVSOq954AXOXpSew7nD+E
+mTqQrd9+ZIbGJnLOMQh5fhMVuOW/1lYCjWAhTCcYZPv7VXD2M70vVXDVXn6ZrqTg
+qkVHE6gw1aCKncwg7OSOUclUxX8+Zi10v6N6+PPslFc5tKwAdWJhVLTQ4FKG+F53
+7FBDnNK6p4xiWryy/vPMYn4jYGvHUUk3eH4lFTCr+rSuJY8i/KNIf/IKim7g/o3w
+Ae3GM8xrof2mgO8GjK/2QDqOQhQgYRIf4/wFsQXVZcMCAwEAAaOCAVcwggFTMAkG
+A1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp
+ZmljYXRlMB0GA1UdDgQWBBQkhCzy1FkgYosuXIaQo6owuicanDCB+AYDVR0jBIHw
+MIHtgBS0ue+a5pcOaGUemM76VQ2JBttMfKGB0aSBzjCByzELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTE9MDsGA1UE
+ChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20v
+eG1sc2VjKTEZMBcGA1UECxMQUm9vdCBDZXJ0aWZpY2F0ZTEWMBQGA1UEAxMNQWxl
+a3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggEA
+MA0GCSqGSIb3DQEBBAUAA4GBALU/mzIxSv8vhDuomxFcplzwdlLZbvSQrfoNkMGY
+1UoS3YJrN+jZLWKSyWE3mIaPpElqXiXQGGkwD5iPQ1iJMbI7BeLvx6ZxX/f+c8Wn
+ss0uc1NxfahMaBoyG15IL4+beqO182fosaKJTrJNG3mc//ANGU9OsQM9mfBEt4oL
+NJ2D</X509Certificate>
+</dsig:X509Data>
+ </dsig:KeyInfo>
+ </dsig:Signature>
+ <Status>
+ <StatusCode Value="samlp:Success"/>
+ </Status>
+ <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="7ddc31-ed4a03d735-FB24AD27D96135B68C99FB9AACFE2FFC" IssueInstant="2002-04-18T16:56:54Z" Issuer="hs.osu.edu" MajorVersion="1" MinorVersion="0">
+ <Conditions NotBefore="2002-04-18T16:56:54Z" NotOnOrAfter="2002-04-18T17:01:54Z">
+ <AudienceRestrictionCondition>
+ <Audience>http://middleware.internet2.edu/shibboleth/clubs/clubshib/1.0/</Audience>
+ </AudienceRestrictionCondition>
+ </Conditions>
+ <AuthenticationStatement AuthenticationInstant="2002-04-18T16:56:53Z" AuthenticationMethod="urn:mace:shibboleth:authmethod">
+ <Subject>
+ <NameIdentifier Format="urn:mace:shibboleth:1.0:handle" NameQualifier="osu.edu">foo</NameIdentifier>
+ <SubjectConfirmation>
+ <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:Bearer</ConfirmationMethod>
+ </SubjectConfirmation>
+ </Subject>
+ <SubjectLocality IPAddress="127.0.0.1"/>
+ <AuthorityBinding AuthorityKind="samlp:AttributeQuery" Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://aa.osu.edu/"/>
+ </AuthenticationStatement>
+ </Assertion>
+</Response>
diff --git a/examples/verify4-tmpl.xml b/examples/verify4-tmpl.xml
new file mode 100644
index 00000000..0546b905
--- /dev/null
+++ b/examples/verify4-tmpl.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+XML Security Library example: A simple SAML response template (verify4 example).
+
+Sign it using the following command (replace __ with double dashes):
+
+ ../apps/xmlsec sign __privkey rsakey.pem,rsacert.pem __output verify4-res.xml verify4-tmpl.xml
+-->
+<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2002-04-18T16:56:54Z" MajorVersion="1" MinorVersion="0" Recipient="https://shire.target.com" ResponseID="7ddc31-ed4a03d703-FB24AD27D96135B68C99FB9AACFE2FFC">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue/>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue/>
+ <dsig:KeyInfo>
+ <dsig:X509Data/>
+ </dsig:KeyInfo>
+ </dsig:Signature>
+ <Status>
+ <StatusCode Value="samlp:Success"/>
+ </Status>
+ <Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="7ddc31-ed4a03d735-FB24AD27D96135B68C99FB9AACFE2FFC" IssueInstant="2002-04-18T16:56:54Z" Issuer="hs.osu.edu" MajorVersion="1" MinorVersion="0">
+ <Conditions NotBefore="2002-04-18T16:56:54Z" NotOnOrAfter="2002-04-18T17:01:54Z">
+ <AudienceRestrictionCondition>
+ <Audience>http://middleware.internet2.edu/shibboleth/clubs/clubshib/1.0/</Audience>
+ </AudienceRestrictionCondition>
+ </Conditions>
+ <AuthenticationStatement AuthenticationInstant="2002-04-18T16:56:53Z" AuthenticationMethod="urn:mace:shibboleth:authmethod">
+ <Subject>
+ <NameIdentifier Format="urn:mace:shibboleth:1.0:handle" NameQualifier="osu.edu">foo</NameIdentifier>
+ <SubjectConfirmation>
+ <ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:Bearer</ConfirmationMethod>
+ </SubjectConfirmation>
+ </Subject>
+ <SubjectLocality IPAddress="127.0.0.1"/>
+ <AuthorityBinding AuthorityKind="samlp:AttributeQuery" Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://aa.osu.edu/"/>
+ </AuthenticationStatement>
+ </Assertion>
+</Response>
diff --git a/examples/verify4.c b/examples/verify4.c
new file mode 100644
index 00000000..1445e997
--- /dev/null
+++ b/examples/verify4.c
@@ -0,0 +1,309 @@
+/**
+ * XML Security Library example: Verifying a simple SAML response with X509 certificate
+ *
+ * Verifies a simple SAML response. In addition to refular verification
+ * we ensure that the signature has only one <dsig:Reference/> element
+ * with an empty or NULL URI attribute and one enveloped signature transform
+ * as it is required by SAML specification.
+ *
+ * This example was developed and tested with OpenSSL crypto library. The
+ * certificates management policies for another crypto library may break it.
+ *
+ * Usage:
+ * verify4 <signed-file> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
+ *
+ * Example (sucecess):
+ * ./verify4 verify4-res.xml rootcert.pem
+ *
+ * Example (failure):
+ * ./verify4 verify4-bad-res.xml rootcert.pem
+ * In the same time, verify3 example successfuly verifies this signature:
+ * ./verify3 verify4-bad-res.xml rootcert.pem
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+xmlSecKeysMngrPtr load_trusted_certs(char** files, int files_size);
+int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);
+
+int
+main(int argc, char **argv) {
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+ xmlSecKeysMngrPtr mngr;
+
+ assert(argv);
+
+ if(argc < 3) {
+ fprintf(stderr, "Error: wrong number of arguments.\n");
+ fprintf(stderr, "Usage: %s <xml-file> <cert-file1> [<cert-file2> [...]]\n", argv[0]);
+ return(1);
+ }
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager and load trusted certificates */
+ mngr = load_trusted_certs(&(argv[2]), argc - 2);
+ if(mngr == NULL) {
+ return(-1);
+ }
+
+ /* verify file */
+ if(verify_file(mngr, argv[1]) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_trusted_certs:
+ * @files: the list of filenames.
+ * @files_size: the number of filenames in #files.
+ *
+ * Creates simple keys manager and load trusted certificates from PEM #files.
+ * The caller is responsible for destroing returned keys manager using
+ * @xmlSecKeysMngrDestroy.
+ *
+ * Returns the pointer to newly created keys manager or NULL if an error
+ * occurs.
+ */
+xmlSecKeysMngrPtr
+load_trusted_certs(char** files, int files_size) {
+ xmlSecKeysMngrPtr mngr;
+ int i;
+
+ assert(files);
+ assert(files_size > 0);
+
+ /* create and initialize keys manager, we use a simple list based
+ * keys manager, implement your own xmlSecKeysStore klass if you need
+ * something more sophisticated
+ */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error: failed to create keys manager.\n");
+ return(NULL);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error: failed to initialize keys manager.\n");
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+
+ for(i = 0; i < files_size; ++i) {
+ assert(files[i]);
+
+ /* load trusted cert */
+ if(xmlSecCryptoAppKeysMngrCertLoad(mngr, files[i], xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) {
+ fprintf(stderr,"Error: failed to load pem certificate from \"%s\"\n", files[i]);
+ xmlSecKeysMngrDestroy(mngr);
+ return(NULL);
+ }
+ }
+
+ return(mngr);
+}
+
+/**
+ * verify_file:
+ * @mngr: the pointer to keys manager.
+ * @xml_file: the signed XML file name.
+ *
+ * Verifies XML signature in #xml_file.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int res = -1;
+
+ assert(mngr);
+ assert(xml_file);
+
+ /* load file */
+ doc = xmlParseFile(xml_file);
+ if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
+ goto done;
+ }
+
+ /* create signature context */
+ dsigCtx = xmlSecDSigCtxCreate(mngr);
+ if(dsigCtx == NULL) {
+ fprintf(stderr,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* limit the Reference URI attributes to empty or NULL */
+ dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeEmpty;
+
+ /* limit allowed transforms for siganture and reference processing */
+ if((xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
+ (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
+ (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformSha1Id) < 0) ||
+ (xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformRsaSha1Id) < 0)) {
+
+ fprintf(stderr,"Error: failed to limit allowed siganture transforms\n");
+ goto done;
+ }
+ if((xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
+ (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
+ (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformSha1Id) < 0) ||
+ (xmlSecDSigCtxEnableReferenceTransform(dsigCtx, xmlSecTransformEnvelopedId) < 0)) {
+
+ fprintf(stderr,"Error: failed to limit allowed reference transforms\n");
+ goto done;
+ }
+
+ /* in addition, limit possible key data to valid X509 certificates only */
+ if(xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataX509Id) < 0) {
+ fprintf(stderr,"Error: failed to limit allowed key data\n");
+ goto done;
+ }
+
+ /* Verify signature */
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ fprintf(stderr,"Error: signature verify\n");
+ goto done;
+ }
+
+ /* check that we have only one Reference */
+ if((dsigCtx->status == xmlSecDSigStatusSucceeded) &&
+ (xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) != 1)) {
+
+ fprintf(stderr,"Error: only one reference is allowed\n");
+ goto done;
+ }
+
+ /* print verification result to stdout */
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ fprintf(stdout, "Signature is OK\n");
+ } else {
+ fprintf(stdout, "Signature is INVALID\n");
+ }
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+ return(res);
+}
+
+
diff --git a/examples/xkms-server.c b/examples/xkms-server.c
new file mode 100644
index 00000000..188d5c73
--- /dev/null
+++ b/examples/xkms-server.c
@@ -0,0 +1,839 @@
+/**
+ * XML Security Library example: simple XKMS server
+ *
+ * Starts XKMS server on specified port.
+ *
+ * Usage:
+ * ./xkms-server [--port <port>] [--format plain|soap-1.1|soap-1.2] <keys-file>
+ *
+ * Example:
+ * ./xkms-server --port 8080 --format soap-1.1 keys.xml
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef XMLSEC_NO_XKMS
+
+int main(int argc, char** argv) {
+ fprintf(stderr, "ERROR: XKMS is disabled.\n");
+ return 1;
+}
+
+#else /* XMLSEC_NO_XKMS */
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/buffer.h>
+#include <xmlsec/xkms.h>
+#include <xmlsec/crypto.h>
+
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+#include <xmlsec/app.h>
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+#ifdef UNIX_SOCKETS
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <signal.h>
+#else /* UNIX_SOCKETS */
+#ifdef WIN32_SOCKETS
+#include <windows.h>
+#include <winsock.h>
+#else /* WIN32_SOCKETS */
+#error "Your operating system is not supported"
+#endif /* WIN32_SOCKETS */
+#endif /* UNIX_SOCKETS */
+
+#define DEFAULT_PORT 1234
+#define PENDING_QUEUE_SIZE 100
+
+#define LOG_LEVEL_SILENT 0
+#define LOG_LEVEL_INFO 1
+#define LOG_LEVEL_DATA 2
+#define LOG_LEVEL_DEBUG 3
+
+#ifdef UNIX_SOCKETS
+static int sockfd = -1;
+#endif /* UNIX_SOCKETS */
+
+#ifdef WIN32_SOCKETS
+static SOCKET sockfd = -1;
+#endif /* WIN32_SOCKETS */
+
+static int finished = 0;
+static int log_level = LOG_LEVEL_INFO;
+
+static int init_server(unsigned short port);
+static void stop_server();
+static void int_signal_handler(int sig_num);
+static const xmlChar* my_strnstr(const xmlChar* str, xmlSecSize strLen, const xmlChar* tmpl, xmlSecSize tmplLen);
+
+static int handle_connection(int fd, xmlSecXkmsServerCtxPtr xkmsCtx, xmlSecXkmsServerFormat format);
+static int read_request(int fd, const char* in_ip, xmlSecBufferPtr buffer);
+static int send_response(int fd, const char* in_ip, int resp_code,
+ const char* body, int body_size);
+
+static char usage[] = "[--port <port>] [--format plain|soap-1.1|soap-1.2] <keys-file>";
+static char http_header[] =
+ "HTTP/1.0 %d\n"
+ "Server: XML Security Library: Simple XKMS Server/1.0\n"
+ "Content-length: %d\n"
+ "\n";
+static char http_503[] =
+ "Error 503 - Service Unavailable\n";
+
+int main(int argc, char** argv) {
+ int argpos;
+ unsigned short port = DEFAULT_PORT;
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+ xmlSecKeysMngrPtr mngr = NULL;
+ xmlSecXkmsServerCtxPtr xkmsCtx = NULL;
+ xmlSecXkmsServerFormat format = xmlSecXkmsServerFormatPlain;
+ int ret;
+
+ fprintf(stdout, "Log: server is starting up\n");
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stderr, "Error %d: xmlsec initialization failed.\n", errno);
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stderr, "Error %d: loaded xmlsec library version is not compatible.\n", errno);
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stderr, "Error %d: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n", errno);
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(NULL) < 0) {
+ fprintf(stderr, "Error %d: crypto initialization failed.\n", errno);
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stderr, "Error %d: xmlsec-crypto initialization failed.\n", errno);
+ return(-1);
+ }
+
+ /* Create and initialize keys manager */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stderr, "Error %d: failed to create keys manager.\n", errno);
+ goto done;
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stderr, "Error %d: failed to initialize keys manager.\n", errno);
+ goto done;
+ }
+
+ /* Create XKMS server context */
+ xkmsCtx = xmlSecXkmsServerCtxCreate(mngr);
+ if(xkmsCtx == NULL) {
+ fprintf(stderr, "Error %d: XKMS server context initialization failed\n", errno);
+ goto done;
+ }
+
+ /* Process input parameters */
+ for(argpos = 1; (argpos < argc) && (argv[argpos][0] == '-'); argpos++) {
+ if((strcmp(argv[argpos], "--port") == 0) || (strcmp(argv[argpos], "-p") == 0)) {
+ argpos++;
+ port = atoi(argv[argpos]);
+ if(port == 0) {
+ fprintf(stderr, "Error %d: invalid port number \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage);
+ goto done;
+ }
+ } else if((strcmp(argv[argpos], "--format") == 0) || (strcmp(argv[argpos], "-f") == 0)) {
+ argpos++;
+ format = xmlSecXkmsServerFormatFromString(BAD_CAST argv[argpos]);
+ if(format == xmlSecXkmsServerFormatUnknown) {
+ fprintf(stderr, "Error %d: invalid format \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage);
+ goto done;
+ }
+ } else if((strcmp(argv[argpos], "--log-level") == 0) || (strcmp(argv[argpos], "-l") == 0)) {
+ argpos++;
+ log_level = atoi(argv[argpos]);
+ } else {
+ fprintf(stderr, "Error %d: unknown parameter \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage);
+ goto done;
+ }
+ }
+ if(argpos >= argc) {
+ fprintf(stderr, "Error %d: keys file is not specified.\nUsage: %s %s\n", errno, argv[0], usage);
+ goto done;
+ }
+
+ /* Load keys */
+ for(; argpos < argc; argpos++) {
+ if(xmlSecCryptoAppDefaultKeysMngrLoad(mngr, argv[argpos]) < 0) {
+ fprintf(stderr, "Error %d: failed to load xml keys file \"%s\".\nUsage: %s %s\n", errno, argv[argpos], argv[0], usage);
+ goto done;
+ }
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log: loaded keys from \"%s\"\n", argv[argpos]);
+ }
+ }
+
+ /* Startup TCP server */
+ if(init_server(port) < 0) {
+ fprintf(stderr, "Error, errno: server initialization failed\n", errno);
+ goto done;
+ }
+ assert(sockfd != -1);
+
+ /* main loop: accept connections and process requests */
+ while(finished == 0) {
+ fd_set fds;
+ struct timeval timeout;
+
+ /* Set up polling using select() */
+ FD_ZERO(&fds);
+ FD_SET(sockfd, &fds);
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_sec = 1;
+ ret = select(sockfd + 1, &fds, NULL, NULL, &timeout);
+ if((ret <= 0) || !FD_ISSET(sockfd, &fds)) {
+ /* error, timed out or not our socket: try again */
+ continue;
+ }
+
+ if(handle_connection(sockfd, xkmsCtx, format) < 0) {
+ fprintf(stderr, "Error %d: unable to accept incomming connection\n");
+ goto done;
+ }
+ }
+
+done:
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log: server is shutting down\n");
+ }
+
+ /* Shutdown TCP server */
+ stop_server();
+
+ /* Destroy xkms server context */
+ if(xkmsCtx != NULL) {
+ xmlSecXkmsServerCtxDestroy(xkmsCtx);
+ xkmsCtx = NULL;
+ }
+
+ /* Destroy keys manager */
+ if(mngr != NULL) {
+ xmlSecKeysMngrDestroy(mngr);
+ mngr = NULL;
+ }
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+ xmlCleanupParser();
+
+ fprintf(stdout, "Log: server is down, bye!\n");
+ return(0);
+}
+
+/**
+ * init_server:
+ * @port: the server'xmlSecBufferGetData(buffer) TCP port number.
+ *
+ * Starts up a TCP server listening on given @port.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+static int
+init_server(unsigned short port) {
+#ifdef WIN32_SOCKETS
+ WSADATA data;
+#endif /* WIN32_SOCKETS */
+ struct sockaddr_in saddr;
+ int flags;
+
+#ifdef WIN32_SOCKETS
+ if(WSAStartup(MAKEWORD(1,1), &data)) {
+ fprintf(stderr, "Error %d: WSAStartup() failed\n", errno);
+ return(-1);
+ }
+#endif /* WIN32_SOCKETS */
+
+ /* create socket */
+ sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+#ifdef UNIX_SOCKETS
+ if(sockfd == -1) {
+#endif /* UNIX_SOCKETS */
+
+#ifdef WIN32_SOCKETS
+ if(sockfd == INVALID_SOCKET) {
+#endif /* WIN32_SOCKETS */
+
+ fprintf(stderr, "Error %d: socket() failed\n", errno);
+ return(-1);
+ }
+
+ /* enable reuse of address */
+ flags = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flags, sizeof(flags)) != 0) {
+ fprintf(stderr, "Error %d: setsockopt(SO_REUSEADDR) failed\n", errno);
+ return(-1);
+ }
+
+#ifdef UNIX_SOCKETS
+ /* set non-blocking */
+ flags = fcntl(sockfd, F_GETFL);
+ if(flags < 0) {
+ fprintf(stderr, "Error %d: fcntl(F_GETFL) failed\n", errno);
+ return(-1);
+ }
+ if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ fprintf(stderr, "Error %d: fcntl(F_SETFL) failed\n", errno);
+ return(-1);
+ }
+#endif /* UNIX_SOCKETS */
+
+ /* preset socket structure for socket binding */
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = htons(port);
+ saddr.sin_addr.s_addr = INADDR_ANY;
+ if(bind(sockfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)) != 0) {
+ fprintf(stderr, "Error %d: bind() failed\n", errno);
+ return(-1);
+ }
+
+ /* prepare for listening */
+ if(listen(sockfd, PENDING_QUEUE_SIZE) != 0) {
+ fprintf(stderr, "Error %d: listen() failed\n", errno);
+ return(-1);
+ }
+
+#ifdef UNIX_SOCKETS
+ /* setup SIGINT handler that will stop the server */
+ signal(SIGINT, int_signal_handler);
+#endif /* UNIX_SOCKETS */
+
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log: server is ready and listening on port %d\n", port);
+ }
+ return(0);
+}
+
+/**
+ * stop_server:
+ *
+ * Shuts down TCP server.
+ */
+static void
+stop_server() {
+#ifdef UNIX_SOCKETS
+ if(sockfd != -1) {
+ shutdown(sockfd, SHUT_RDWR);
+ close(sockfd);
+ sockfd = -1;
+ }
+#endif /* UNIX_SOCKETS */
+
+#ifdef WIN32_SOCKETS
+ if(sockfd != -1) {
+ close(sockfd);
+ sockfd = -1;
+ }
+#endif /* WIN32_SOCKETS */
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log: server is shutted down\n");
+ }
+}
+
+/**
+ * int_signal_handler:
+ * @sig_num: the signal number.
+ *
+ * Unix's Ctrl-C signal handler that stops the server.
+ */
+static void
+int_signal_handler(int sig_num) {
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log: server is asked to shutdown\n");
+ }
+ finished = 1;
+}
+
+/**
+ * handle_connection:
+ * @sockfd: the server's socket.
+ * @xkmsCtx: the template XKMS server context.
+ * @format: the expected format of XKMS requests.
+ *
+ * Establishs a connection, forks a child process (onUnix), reads the request,
+ * processes it and writes back the response.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+static int
+handle_connection(int sockfd, xmlSecXkmsServerCtxPtr xkmsCtx, xmlSecXkmsServerFormat format) {
+#ifdef UNIX_SOCKETS
+ int fd = -1;
+#endif /* UNIX_SOCKETS */
+
+#ifdef WIN32_SOCKETS
+ SOCKET fd = -1;
+#endif /* WIN32_SOCKETS */
+
+ int in_child_process = 0;
+ struct sockaddr_in saddr;
+ int saddr_size;
+ xmlSecXkmsServerCtxPtr xkmsCtx2 = NULL;
+ xmlSecBufferPtr buffer = NULL;
+ xmlDocPtr inDoc = NULL;
+ xmlDocPtr outDoc = NULL;
+ xmlNodePtr result = NULL;
+ xmlOutputBufferPtr output = NULL;
+ int resp_ready = 0;
+ int ret;
+
+ assert(sockfd != -1);
+ assert(xkmsCtx != NULL);
+
+ /* Get the socket connection */
+ saddr_size = sizeof(struct sockaddr_in);
+ fd = accept(sockfd, (struct sockaddr *)&saddr, &saddr_size);
+
+#ifdef UNIX_SOCKETS
+ if(sockfd == -1) {
+#endif /* UNIX_SOCKETS */
+
+#ifdef WIN32_SOCKETS
+ if(sockfd == INVALID_SOCKET) {
+#endif /* WIN32_SOCKETS */
+
+ fprintf(stderr, "Error %d: accept() failed\n", errno);
+ return(-1);
+ }
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log [%s]: got connection\n", inet_ntoa(saddr.sin_addr));
+ }
+
+ /* Create a copy of XKMS server context */
+ xkmsCtx2 = xmlSecXkmsServerCtxCreate(NULL);
+ if(xkmsCtx2 == NULL) {
+ fprintf(stderr, "Error %d [%s]: a copy of XKMS server context initialization failed\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+ if(xmlSecXkmsServerCtxCopyUserPref(xkmsCtx2, xkmsCtx) < 0) {
+ fprintf(stderr, "Error %d [%s]: XKMS server context copy failed\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+
+#ifdef UNIX_SOCKETS
+ /* on Unix we use child process to process requests */
+ if(fork()) {
+ /* parent process */
+ return(0);
+ }
+
+ /* child process */
+ in_child_process = 1;
+ close(sockfd); /* we don't need listening socket */
+#endif /* UNIX_SOCKETS */
+
+ buffer = xmlSecBufferCreate(0);
+ if(buffer == NULL) {
+ fprintf(stderr, "Error %d [%s]: xmlSecBufferCreate() failed\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+
+ /* read input request */
+ ret = read_request(fd, inet_ntoa(saddr.sin_addr), buffer);
+ if(ret < 0) {
+ fprintf(stderr, "Error %d [%s]: read_request() failed\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+
+ /* parse request */
+ inDoc = xmlParseMemory(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer) );
+ if((inDoc == NULL) || (xmlDocGetRootElement(inDoc) == NULL)) {
+ fprintf(stderr, "Error %d [%s]: failed to parse request\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+ xmlSecBufferEmpty(buffer);
+
+ /* prepare result document */
+ outDoc = xmlNewDoc(BAD_CAST "1.0");
+ if(outDoc == NULL) {
+ fprintf(stderr, "Error %d [%s]: failed to create result doc\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+
+ result = xmlSecXkmsServerCtxProcess(xkmsCtx2, xmlDocGetRootElement(inDoc), format, outDoc);
+ if(result == NULL) {
+ fprintf(stderr, "Error %d [%s]: failed to process xkms server request\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+
+ /* apppend returned result node to the output document */
+ xmlDocSetRootElement(outDoc, result);
+
+ /* create LibXML2 output buffer */
+ output = xmlSecBufferCreateOutputBuffer(buffer);
+ if(output == NULL) {
+ fprintf(stderr, "Error %d [%s]: xmlSecBufferCreateOutputBuffer() failed\n", errno, inet_ntoa(saddr.sin_addr));
+ goto done;
+ }
+ xmlNodeDumpOutput(output, result->doc, result, 0, 0, NULL);
+
+ xmlOutputBufferClose(output); output = NULL;
+ resp_ready = 1;
+done:
+ /* send back response */
+ if((resp_ready == 1) && (xmlSecBufferGetData(buffer) != NULL)) {
+ ret = send_response(fd, inet_ntoa(saddr.sin_addr), 200, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log [%s]: processed request\n", inet_ntoa(saddr.sin_addr));
+ }
+ } else if(fd >= 0) {
+ ret = send_response(fd, inet_ntoa(saddr.sin_addr), 503, http_503, strlen(http_503));
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log [%s]: failed to process request\n", inet_ntoa(saddr.sin_addr));
+ }
+ } else {
+ ret = -1;
+ }
+ if(ret < 0) {
+ fprintf(stderr, "Error %d [%s]: send_response() failed\n", errno, inet_ntoa(saddr.sin_addr));
+ }
+
+ /* cleanup */
+ if(output != NULL) {
+ xmlOutputBufferClose(output);
+ output = NULL;
+ }
+
+ if(outDoc != NULL) {
+ xmlFreeDoc(outDoc);
+ outDoc = NULL;
+ }
+
+ if(inDoc != NULL) {
+ xmlFreeDoc(inDoc);
+ inDoc = NULL;
+ }
+
+ if(buffer != NULL) {
+ xmlSecBufferDestroy(buffer);
+ buffer = NULL;
+ }
+
+ if(xkmsCtx2 != NULL) {
+ xmlSecXkmsServerCtxDestroy(xkmsCtx2);
+ xkmsCtx2 = NULL;
+ }
+
+ if(fd >= 0) {
+#ifdef UNIX_SOCKETS
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+#endif /* UNIX_SCOKETS */
+
+#ifdef WIN32_SOCKETS
+ close(fd);
+#endif /* WIN32_SCOKETS */
+
+ fd = -1;
+ }
+
+ if(in_child_process) {
+ exit(0);
+ }
+ return(0);
+}
+
+/**
+ * read_request:
+ * @fd: the request's socket.
+ * @in_ip: the request's IP address (for logging).
+ * @buffer: the output buffer.
+ *
+ * Reads the request from socket @fd and stores it in the @buffer.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+static int
+read_request(int fd, const char* in_ip, xmlSecBufferPtr buffer) {
+ char buf[1024];
+ const xmlChar* s;
+ const xmlChar* p;
+ int nread;
+ int length = 0;
+ int found = 0;
+ int counter;
+
+ assert(fd != -1);
+ assert(in_ip != NULL);
+ assert(buffer);
+
+ /* first read the http headers */
+ counter = 5;
+ while(my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n\r\n", 4) == NULL) {
+ nread = recv(fd, buf, sizeof(buf), 0);
+ if(nread < 0) {
+ fprintf(stderr, "Error %d [%s]: read() failed\n", errno, in_ip);
+ return(-1);
+ }
+
+ if((nread > 0) && (xmlSecBufferAppend(buffer, buf, nread) < 0)) {
+ fprintf(stderr, "Error %d [%s]: xmlSecBufferAppend(%d) failed\n", errno, in_ip, nread);
+ return(-1);
+ }
+
+ if(nread < sizeof(buffer)) {
+ counter--;
+ if(counter <= 0) {
+ break;
+ }
+ }
+ }
+
+ if(xmlSecBufferGetData(buffer) == NULL) {
+ fprintf(stderr, "Error %d [%s]: no bytes read\n", errno, in_ip);
+ return(-1);
+ }
+
+ if(log_level >= LOG_LEVEL_DEBUG) {
+ xmlSecBufferAppend(buffer, BAD_CAST "\0", 1);
+ fprintf(stdout, "Debug [%s]: request headers:\n%s\n", in_ip, xmlSecBufferGetData(buffer));
+ xmlSecBufferRemoveTail(buffer, 1);
+ }
+
+ /* Parse the request and extract the body. We expect the request to look
+ * like this:
+ * POST <path> HTTP/1.x\r\n
+ * <header1>\r\n
+ * <header2>\r\n
+ * ...
+ * <headerN>\r\n
+ * \r\n
+ * <body>
+ */
+
+ /* analyze the first line */
+ p = my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n", 2);
+ if(p == NULL) {
+ fprintf(stderr, "Error %d [%s]: there is no HTTP header\n", errno, in_ip);
+ return(-1);
+ }
+ if(xmlStrncasecmp(xmlSecBufferGetData(buffer), BAD_CAST "POST ", 5) != 0) {
+ fprintf(stderr, "Error %d [%s]: not a POST request\n", errno, in_ip);
+ return(-1);
+ }
+ /* "POST " + " HTTP/1.x" == 14 */
+ s = xmlSecBufferGetData(buffer);
+ if(p - s <= 14) {
+ fprintf(stderr, "Error %d [%s]: first line has bad length\n", errno, in_ip);
+ return(-1);
+ }
+ if((xmlStrncasecmp(p - 9, BAD_CAST " HTTP/1.0", 9) != 0) &&
+ (xmlStrncasecmp(p - 9, BAD_CAST " HTTP/1.1", 9) != 0)) {
+
+ fprintf(stderr, "Error %d [%s]: first line does not end with \" HTTP/1.x\"\n", errno, in_ip);
+ return(-1);
+ }
+ if(xmlSecBufferRemoveHead(buffer, p - xmlSecBufferGetData(buffer) + 2) < 0) {
+ fprintf(stderr, "Error %d [%s]: failed to skip first line\n", errno, in_ip);
+ return(-1);
+ }
+
+ /* now skip all the headers (i.e. everything until empty line) */
+ found = 0;
+ while(!found) {
+ p = my_strnstr(xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), BAD_CAST "\r\n", 2);
+ if(p == NULL) {
+ fprintf(stderr, "Error %d [%s]: there is no HTTP body\n", errno, in_ip);
+ return(-1);
+ }
+
+ if(p == xmlSecBufferGetData(buffer)) {
+ found = 1;
+ } else if(xmlStrncasecmp(xmlSecBufferGetData(buffer), BAD_CAST "Content-length: ", 16) == 0) {
+ length = atoi(xmlSecBufferGetData(buffer) + 16);
+ }
+
+ if(xmlSecBufferRemoveHead(buffer, p - xmlSecBufferGetData(buffer) + 2) < 0) {
+ fprintf(stderr, "Error %d [%s]: failed to skip header line\n", errno, in_ip);
+ return(-1);
+ }
+ }
+
+ /* remove the trailing \0 we added */
+ xmlSecBufferRemoveTail(buffer, 1);
+
+ /* now read the body */
+ counter = 5;
+ while(xmlSecBufferGetSize(buffer) < length) {
+ nread = recv(fd, buf, sizeof(buf), 0);
+ if(nread < 0) {
+ fprintf(stderr, "Error %d [%s]: read() failed\n", errno, in_ip);
+ return(-1);
+ }
+
+ if((nread > 0) && (xmlSecBufferAppend(buffer, buf, nread) < 0)) {
+ fprintf(stderr, "Error %d [%s]: xmlSecBufferAppend(%d) failed\n", errno, in_ip, nread);
+ return(-1);
+ }
+ if(nread < sizeof(buffer)) {
+ counter--;
+ if(counter <= 0) {
+ break;
+ }
+ }
+ }
+ if(log_level >= LOG_LEVEL_INFO) {
+ fprintf(stdout, "Log [%s]: body size is %d bytes\n", in_ip, xmlSecBufferGetSize(buffer));
+ }
+ if(log_level >= LOG_LEVEL_DATA) {
+ xmlSecBufferAppend(buffer, BAD_CAST "\0", 1);
+ fprintf(stdout, "Log [%s]: request body:\n%s\n", in_ip, xmlSecBufferGetData(buffer));
+ xmlSecBufferRemoveTail(buffer, 1);
+ }
+ return(0);
+}
+
+/**
+ * send_response:
+ * @fd: the request's socket.
+ * @in_ip: the request's IP address (for logging).
+ * @resp_code: the HTTP response code.
+ * @body: the response body.
+ * @body_len: the response body length.
+ *
+ * Writes HTTP response headers and @body to the @socket.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+static int
+send_response(int fd, const char* in_ip, int resp_code, const char* body, int body_size) {
+ char header[sizeof(http_header) + 100];
+
+ assert(fd != -1);
+ assert(in_ip != NULL);
+ assert(resp_code > 0);
+ assert(body != NULL);
+
+ /* prepare and send http header */
+ sprintf(header, http_header, resp_code, body_size);
+ if(send(fd, header, strlen(header), 0) == -1) {
+ fprintf(stderr, "Error %d [%s]: send(header) failed\n", errno, in_ip);
+ return(-1);
+ }
+
+ if(log_level >= LOG_LEVEL_DATA) {
+ xmlChar* tmp = xmlStrndup(body, body_size);
+ fprintf(stdout, "Log [%s]: response is\n%s\n", in_ip, tmp);
+ xmlFree(tmp);
+ }
+
+ /* send body */
+ if(send(fd, body, body_size, 0) == -1) {
+ fprintf(stderr, "Error %d [%s]: send(body) failed\n", errno, in_ip);
+ return(-1);
+ }
+
+ return(0);
+}
+
+/**
+ * my_strnstr:
+ * @str: the soruce string.
+ * @strLen: the source string length.
+ * @tmpl: the template string.
+ * @tmplLen: the template string length.
+ *
+ * Searches for the first occurence of @tmpl in @str.
+ *
+ * Returns pointer to the first occurence of @tmpl in @str or NULL if it is not found.
+ */
+static const xmlChar*
+my_strnstr(const xmlChar* str, xmlSecSize strLen, const xmlChar* tmpl, xmlSecSize tmplLen) {
+ xmlSecSize pos;
+
+ if((str == NULL) || (tmpl == NULL)) {
+ return(NULL);
+ }
+ for(pos = 0; pos + tmplLen <= strLen; pos++) {
+ if(xmlStrncmp(str + pos, tmpl, tmplLen) == 0) {
+ return(str + pos);
+ }
+ }
+
+ return(NULL);
+}
+
+#endif /* XMLSEC_NO_XKMS */
+
diff --git a/examples/xmldsigverify.c b/examples/xmldsigverify.c
new file mode 100644
index 00000000..f4c376ea
--- /dev/null
+++ b/examples/xmldsigverify.c
@@ -0,0 +1,381 @@
+/**
+ * XML Security Library example: CGI verification script.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#include <libxslt/security.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+
+/* #define XMLDSIGVERIFY_DEFAULT_TRUSTED_CERTS_FOLDER "/etc/httpd/conf/ssl.crt" */
+#define XMLDSIGVERIFY_DEFAULT_TRUSTED_CERTS_FOLDER "/var/www/cgi-bin/keys-certs.def"
+#define XMLDSIGVERIFY_KEY_AND_CERTS_FOLDER "/var/www/cgi-bin/keys-certs"
+
+
+int load_keys(xmlSecKeysMngrPtr mngr, const char* path, int report_loaded_keys);
+int load_trusted_certs(xmlSecKeysMngrPtr mngr, const char* path, int report_loaded_certs);
+int verify_request(xmlSecKeysMngrPtr mngr);
+int url_decode(char *buf, size_t size);
+
+int
+main(int argc, char **argv) {
+ xmlSecKeysMngrPtr mngr;
+#ifndef XMLSEC_NO_XSLT
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* start response */
+ fprintf(stdout, "Content-type: text/plain\n");
+ fprintf(stdout, "\n");
+
+ /* Init libxml and libxslt libraries */
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif /* XMLSEC_NO_XSLT */
+
+ /* make sure that we print out everything to stdout */
+ xmlGenericErrorContext = stdout;
+
+ /* Init libxslt */
+#ifndef XMLSEC_NO_XSLT
+ /* disable everything */
+ xsltSecPrefs = xsltNewSecurityPrefs();
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
+#endif /* XMLSEC_NO_XSLT */
+
+ /* Init xmlsec library */
+ if(xmlSecInit() < 0) {
+ fprintf(stdout, "Error: xmlsec initialization failed.\n");
+ return(-1);
+ }
+
+ /* Check loaded library version */
+ if(xmlSecCheckVersion() != 1) {
+ fprintf(stdout, "Error: loaded xmlsec library version is not compatible.\n");
+ return(-1);
+ }
+
+ /* Load default crypto engine if we are supporting dynamic
+ * loading for xmlsec-crypto libraries. Use the crypto library
+ * name ("openssl", "nss", etc.) to load corresponding
+ * xmlsec-crypto library.
+ */
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ fprintf(stdout, "Error: unable to load default xmlsec-crypto library. Make sure\n"
+ "that you have it installed and check shared libraries path\n"
+ "(LD_LIBRARY_PATH) envornment variable.\n");
+ return(-1);
+ }
+#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
+
+ /* Init crypto library */
+ if(xmlSecCryptoAppInit(XMLDSIGVERIFY_DEFAULT_TRUSTED_CERTS_FOLDER) < 0) {
+ fprintf(stdout, "Error: crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* Init xmlsec-crypto library */
+ if(xmlSecCryptoInit() < 0) {
+ fprintf(stdout, "Error: xmlsec-crypto initialization failed.\n");
+ return(-1);
+ }
+
+ /* create keys manager */
+ mngr = xmlSecKeysMngrCreate();
+ if(mngr == NULL) {
+ fprintf(stdout, "Error: failed to create keys manager.\n");
+ return(-1);
+ }
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+ fprintf(stdout, "Error: failed to initialize keys manager.\n");
+ return(-1);
+ }
+
+ if(load_keys(mngr, XMLDSIGVERIFY_KEY_AND_CERTS_FOLDER, 0) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ if(load_trusted_certs(mngr, XMLDSIGVERIFY_KEY_AND_CERTS_FOLDER, 0) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ if(verify_request(mngr) < 0) {
+ xmlSecKeysMngrDestroy(mngr);
+ return(-1);
+ }
+
+ /* Destroy keys manager */
+ xmlSecKeysMngrDestroy(mngr);
+
+ /* Shutdown xmlsec-crypto library */
+ xmlSecCryptoShutdown();
+
+ /* Shutdown crypto library */
+ xmlSecCryptoAppShutdown();
+
+ /* Shutdown xmlsec library */
+ xmlSecShutdown();
+
+ /* Shutdown libxslt/libxml */
+#ifndef XMLSEC_NO_XSLT
+ xsltFreeSecurityPrefs(xsltSecPrefs);
+ xsltCleanupGlobals();
+#endif /* XMLSEC_NO_XSLT */
+
+ xmlCleanupParser();
+
+ return(0);
+}
+
+/**
+ * load_trusted_certs:
+ * @mngr: the keys manager.
+ * @path: the path to a folder that contains trusted certificates.
+ *
+ * Loads trusted certificates from @path.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int load_trusted_certs(xmlSecKeysMngrPtr mngr, const char* path, int report_loaded_certs) {
+ DIR* dir;
+ struct dirent* entry;
+ char filename[256];
+ int len;
+
+ assert(mngr);
+ assert(path);
+
+ dir = opendir(path);
+ if(dir == NULL) {
+ fprintf(stdout, "Error: failed to open folder \"%s\".\n", path);
+ return(-1);
+ }
+ while((entry = readdir(dir)) != NULL) {
+ assert(entry->d_name);
+ len = strlen(entry->d_name);
+ if((len > 4) && (strcmp(entry->d_name + len - 4, ".pem") == 0)) {
+ snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
+ if(xmlSecCryptoAppKeysMngrCertLoad(mngr, filename, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) {
+ fprintf(stdout,"Error: failed to load pem certificate from \"%s\"\n", filename);
+ closedir(dir);
+ return(-1);
+ }
+ if(report_loaded_certs) {
+ fprintf(stdout, "Loaded trusted certificate from \"%s\"...\n", filename);
+ }
+ } else if((len > 4) && (strcmp(entry->d_name + len - 4, ".der") == 0)) {
+ snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
+ if(xmlSecCryptoAppKeysMngrCertLoad(mngr, filename, xmlSecKeyDataFormatDer, xmlSecKeyDataTypeTrusted) < 0) {
+ fprintf(stdout,"Error: failed to load der certificate from \"%s\"\n", filename);
+ closedir(dir);
+ return(-1);
+ }
+ if(report_loaded_certs) {
+ fprintf(stdout, "Loaded trusted certificate from \"%s\"...\n", filename);
+ }
+ }
+ }
+ closedir(dir);
+ return(0);
+}
+
+int load_keys(xmlSecKeysMngrPtr mngr, const char* path, int report_loaded_keys) {
+ char filename[256];
+
+ assert(mngr);
+
+ snprintf(filename, sizeof(filename), "%s/keys.xml", path);
+ if(xmlSecCryptoAppDefaultKeysMngrLoad(mngr, filename) < 0) {
+ fprintf(stdout,"Error: failed to load keys from \"%s\"\n", filename);
+ return(-1);
+ }
+
+ if(report_loaded_keys) {
+ fprintf(stdout, "Loaded keys from \"%s\"...\n", filename);
+ }
+ return(0);
+}
+
+
+/**
+ * verify_request:
+ * @mng: the keys manager
+ *
+ * Verifies XML signature in the request (stdin).
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+verify_request(xmlSecKeysMngrPtr mngr) {
+ xmlBufferPtr buffer = NULL;
+ char buf[256];
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecDSigCtxPtr dsigCtx = NULL;
+ int ret;
+ int res = -1;
+
+ assert(mngr);
+
+ /* load request in the buffer */
+ buffer = xmlBufferCreate();
+ if(buffer == NULL) {
+ fprintf(stdout,"Error: failed to create buffer\n");
+ goto done;
+ }
+
+ while(!feof(stdin)) {
+ ret = fread(buf, 1, sizeof(buf), stdin);
+ if(ret < 0) {
+ fprintf(stdout,"Error: read failed\n");
+ goto done;
+ }
+ xmlBufferAdd(buffer, buf, ret);
+ }
+
+ /* is the document subbmitted from the form? */
+ if(strncmp((char*)xmlBufferContent(buffer), "_xmldoc=", 8) == 0) {
+ xmlBufferShrink(buffer, 8);
+ buffer->use = url_decode((char*)xmlBufferContent(buffer), xmlBufferLength(buffer));
+ }
+
+ /**
+ * Load doc
+ */
+ doc = xmlReadMemory(xmlBufferContent(buffer), xmlBufferLength(buffer),
+ NULL, NULL,
+ XML_PARSE_NOENT | XML_PARSE_NOCDATA |
+ XML_PARSE_PEDANTIC | XML_PARSE_NOCDATA);
+ if (doc == NULL) {
+ fprintf(stdout, "Error: unable to parse xml document (syntax error)\n");
+ goto done;
+ }
+
+ /*
+ * Check the document is of the right kind
+ */
+ if(xmlDocGetRootElement(doc) == NULL) {
+ fprintf(stdout,"Error: empty document\n");
+ goto done;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if(node == NULL) {
+ fprintf(stdout, "Error: start <dsig:Signature/> node not found\n");
+ goto done;
+ }
+
+ /* create signature context */
+ dsigCtx = xmlSecDSigCtxCreate(mngr);
+ if(dsigCtx == NULL) {
+ fprintf(stdout,"Error: failed to create signature context\n");
+ goto done;
+ }
+
+ /* we would like to store and print out everything */
+ /* actually we would not because it opens a security hole
+ dsigCtx->flags = XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES |
+ XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES |
+ XMLSEC_DSIG_FLAGS_STORE_SIGNATURE;
+ */
+
+ /* Verify signature */
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ fprintf(stdout,"Error: signature verification failed\n");
+ goto done;
+ }
+
+ /* print verification result to stdout */
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ fprintf(stdout, "RESULT: Signature is OK\n");
+ } else {
+ fprintf(stdout, "RESULT: Signature is INVALID\n");
+ }
+ fprintf(stdout, "---------------------------------------------------\n");
+ xmlSecDSigCtxDebugDump(dsigCtx, stdout);
+
+ /* success */
+ res = 0;
+
+done:
+ /* cleanup */
+ if(dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if(doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+
+ if(buffer != NULL) {
+ xmlBufferFree(buffer);
+ }
+ return(res);
+}
+
+/* not the best way to do it */
+#define toHex(c) ( ( ('0' <= (c)) && ((c) <= '9') ) ? (c) - '0' : \
+ ( ( ('A' <= (c)) && ((c) <= 'F') ) ? (c) - 'A' + 10 : 0 ) )
+
+/**
+ * url_decode:
+ * @buf: the input buffer.
+ * @size: the input buffer size.
+ *
+ * Does url decoding in-place.
+ *
+ * Returns length of the decoded result on success or
+ * a negative value if an error occurs.
+ */
+int url_decode(char *buf, size_t size) {
+ char *p1, *p2;
+
+ assert(buf);
+
+ p1 = p2 = buf;
+ while(p1 - buf < size) {
+ if(((*p1) == '%') && ((p1 - buf) <= (size - 3))) {
+ *(p2++) = (char)(toHex(p1[1]) * 16 + toHex(p1[2]));
+ p1 += 3;
+ } else if((*p1) == '+') {
+ *(p2++) = ' ';
+ p1++;
+ } else {
+ *(p2++) = *(p1++);
+ }
+ }
+ return(p2 - buf);
+}
+
+