2 * XML Security Library example: Verifying a file signed with X509 certificate
4 * Verifies a file signed with X509 certificate.
6 * This example was developed and tested with OpenSSL crypto library. The
7 * certificates management policies for another crypto library may break it.
10 * verify3 <signed-file> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
13 * ./verify3 sign3-res.xml rootcert.pem
15 * This is free software; see Copyright file in the source
16 * distribution for preciese wording.
18 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
24 #include <libxml/tree.h>
25 #include <libxml/xmlmemory.h>
26 #include <libxml/parser.h>
28 #ifndef XMLSEC_NO_XSLT
29 #include <libxslt/xslt.h>
30 #endif /* XMLSEC_NO_XSLT */
32 #include <xmlsec/xmlsec.h>
33 #include <xmlsec/xmltree.h>
34 #include <xmlsec/xmldsig.h>
35 #include <xmlsec/crypto.h>
37 xmlSecKeysMngrPtr load_trusted_certs(char** files, int files_size);
38 int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);
41 main(int argc, char **argv) {
42 xmlSecKeysMngrPtr mngr;
47 fprintf(stderr, "Error: wrong number of arguments.\n");
48 fprintf(stderr, "Usage: %s <xml-file> <cert-file1> [<cert-file2> [...]]\n", argv[0]);
52 /* Init libxml and libxslt libraries */
55 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
56 xmlSubstituteEntitiesDefault(1);
57 #ifndef XMLSEC_NO_XSLT
58 xmlIndentTreeOutput = 1;
59 #endif /* XMLSEC_NO_XSLT */
61 /* Init xmlsec library */
62 if(xmlSecInit() < 0) {
63 fprintf(stderr, "Error: xmlsec initialization failed.\n");
67 /* Check loaded library version */
68 if(xmlSecCheckVersion() != 1) {
69 fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
73 /* Load default crypto engine if we are supporting dynamic
74 * loading for xmlsec-crypto libraries. Use the crypto library
75 * name ("openssl", "nss", etc.) to load corresponding
76 * xmlsec-crypto library.
78 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
79 if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
80 fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
81 "that you have it installed and check shared libraries path\n"
82 "(LD_LIBRARY_PATH) envornment variable.\n");
85 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
87 /* Init crypto library */
88 if(xmlSecCryptoAppInit(NULL) < 0) {
89 fprintf(stderr, "Error: crypto initialization failed.\n");
93 /* Init xmlsec-crypto library */
94 if(xmlSecCryptoInit() < 0) {
95 fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
99 /* create keys manager and load trusted certificates */
100 mngr = load_trusted_certs(&(argv[2]), argc - 2);
106 if(verify_file(mngr, argv[1]) < 0) {
107 xmlSecKeysMngrDestroy(mngr);
111 /* destroy keys manager */
112 xmlSecKeysMngrDestroy(mngr);
114 /* Shutdown xmlsec-crypto library */
115 xmlSecCryptoShutdown();
117 /* Shutdown crypto library */
118 xmlSecCryptoAppShutdown();
120 /* Shutdown xmlsec library */
123 /* Shutdown libxslt/libxml */
124 #ifndef XMLSEC_NO_XSLT
125 xsltCleanupGlobals();
126 #endif /* XMLSEC_NO_XSLT */
133 * load_trusted_certs:
134 * @files: the list of filenames.
135 * @files_size: the number of filenames in #files.
137 * Creates simple keys manager and load trusted certificates from PEM #files.
138 * The caller is responsible for destroing returned keys manager using
139 * @xmlSecKeysMngrDestroy.
141 * Returns the pointer to newly created keys manager or NULL if an error
145 load_trusted_certs(char** files, int files_size) {
146 xmlSecKeysMngrPtr mngr;
150 assert(files_size > 0);
152 /* create and initialize keys manager, we use a simple list based
153 * keys manager, implement your own xmlSecKeysStore klass if you need
154 * something more sophisticated
156 mngr = xmlSecKeysMngrCreate();
158 fprintf(stderr, "Error: failed to create keys manager.\n");
161 if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
162 fprintf(stderr, "Error: failed to initialize keys manager.\n");
163 xmlSecKeysMngrDestroy(mngr);
167 for(i = 0; i < files_size; ++i) {
170 /* load trusted cert */
171 if(xmlSecCryptoAppKeysMngrCertLoad(mngr, files[i], xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) {
172 fprintf(stderr,"Error: failed to load pem certificate from \"%s\"\n", files[i]);
173 xmlSecKeysMngrDestroy(mngr);
183 * @mngr: the pointer to keys manager.
184 * @xml_file: the signed XML file name.
186 * Verifies XML signature in #xml_file.
188 * Returns 0 on success or a negative value if an error occurs.
191 verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
192 xmlDocPtr doc = NULL;
193 xmlNodePtr node = NULL;
194 xmlSecDSigCtxPtr dsigCtx = NULL;
201 doc = xmlParseFile(xml_file);
202 if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
203 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
207 /* find start node */
208 node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
210 fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
214 /* create signature context */
215 dsigCtx = xmlSecDSigCtxCreate(mngr);
216 if(dsigCtx == NULL) {
217 fprintf(stderr,"Error: failed to create signature context\n");
221 /* Verify signature */
222 if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
223 fprintf(stderr,"Error: signature verify\n");
227 /* print verification result to stdout */
228 if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
229 fprintf(stdout, "Signature is OK\n");
231 fprintf(stdout, "Signature is INVALID\n");
239 if(dsigCtx != NULL) {
240 xmlSecDSigCtxDestroy(dsigCtx);