Git init
[external/xmlsec1.git] / examples / verify3.c
1 /** 
2  * XML Security Library example: Verifying a file signed with X509 certificate
3  *
4  * Verifies a file signed with X509 certificate. 
5  * 
6  * This example was developed and tested with OpenSSL crypto library. The 
7  * certificates management policies for another crypto library may break it.
8  *
9  * Usage: 
10  *      verify3 <signed-file> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
11  *
12  * Example:
13  *      ./verify3 sign3-res.xml rootcert.pem
14  * 
15  * This is free software; see Copyright file in the source
16  * distribution for preciese wording.
17  * 
18  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
19  */
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23
24 #include <libxml/tree.h>
25 #include <libxml/xmlmemory.h>
26 #include <libxml/parser.h>
27
28 #ifndef XMLSEC_NO_XSLT
29 #include <libxslt/xslt.h>
30 #endif /* XMLSEC_NO_XSLT */
31
32 #include <xmlsec/xmlsec.h>
33 #include <xmlsec/xmltree.h>
34 #include <xmlsec/xmldsig.h>
35 #include <xmlsec/crypto.h>
36
37 xmlSecKeysMngrPtr load_trusted_certs(char** files, int files_size);
38 int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);
39
40 int 
41 main(int argc, char **argv) {
42     xmlSecKeysMngrPtr mngr;
43     
44     assert(argv);
45
46     if(argc < 3) {
47         fprintf(stderr, "Error: wrong number of arguments.\n");
48         fprintf(stderr, "Usage: %s <xml-file> <cert-file1> [<cert-file2> [...]]\n", argv[0]);
49         return(1);
50     }
51
52     /* Init libxml and libxslt libraries */
53     xmlInitParser();
54     LIBXML_TEST_VERSION
55     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
56     xmlSubstituteEntitiesDefault(1);
57 #ifndef XMLSEC_NO_XSLT
58     xmlIndentTreeOutput = 1; 
59 #endif /* XMLSEC_NO_XSLT */
60                 
61     /* Init xmlsec library */
62     if(xmlSecInit() < 0) {
63         fprintf(stderr, "Error: xmlsec initialization failed.\n");
64         return(-1);
65     }
66
67     /* Check loaded library version */
68     if(xmlSecCheckVersion() != 1) {
69         fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
70         return(-1);
71     }
72
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.
77      */
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");
83         return(-1);     
84     }
85 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
86
87     /* Init crypto library */
88     if(xmlSecCryptoAppInit(NULL) < 0) {
89         fprintf(stderr, "Error: crypto initialization failed.\n");
90         return(-1);
91     }
92
93     /* Init xmlsec-crypto library */
94     if(xmlSecCryptoInit() < 0) {
95         fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
96         return(-1);
97     }
98
99     /* create keys manager and load trusted certificates */
100     mngr = load_trusted_certs(&(argv[2]), argc - 2);
101     if(mngr == NULL) {
102         return(-1);
103     }
104     
105     /* verify file */
106     if(verify_file(mngr, argv[1]) < 0) {
107         xmlSecKeysMngrDestroy(mngr);    
108         return(-1);
109     }    
110     
111     /* destroy keys manager */
112     xmlSecKeysMngrDestroy(mngr);
113     
114     /* Shutdown xmlsec-crypto library */
115     xmlSecCryptoShutdown();
116     
117     /* Shutdown crypto library */
118     xmlSecCryptoAppShutdown();
119     
120     /* Shutdown xmlsec library */
121     xmlSecShutdown();
122
123     /* Shutdown libxslt/libxml */
124 #ifndef XMLSEC_NO_XSLT
125     xsltCleanupGlobals();            
126 #endif /* XMLSEC_NO_XSLT */
127     xmlCleanupParser();
128     
129     return(0);
130 }
131
132 /**
133  * load_trusted_certs:
134  * @files:              the list of filenames.
135  * @files_size:         the number of filenames in #files.
136  *
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.
140  *
141  * Returns the pointer to newly created keys manager or NULL if an error
142  * occurs.
143  */
144 xmlSecKeysMngrPtr 
145 load_trusted_certs(char** files, int files_size) {
146     xmlSecKeysMngrPtr mngr;
147     int i;
148         
149     assert(files);
150     assert(files_size > 0);
151     
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 
155      */
156     mngr = xmlSecKeysMngrCreate();
157     if(mngr == NULL) {
158         fprintf(stderr, "Error: failed to create keys manager.\n");
159         return(NULL);
160     }
161     if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
162         fprintf(stderr, "Error: failed to initialize keys manager.\n");
163         xmlSecKeysMngrDestroy(mngr);
164         return(NULL);
165     }    
166     
167     for(i = 0; i < files_size; ++i) {
168         assert(files[i]);
169
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);
174             return(NULL);
175         }
176     }
177
178     return(mngr);
179 }
180
181 /** 
182  * verify_file:
183  * @mngr:               the pointer to keys manager.
184  * @xml_file:           the signed XML file name.
185  *
186  * Verifies XML signature in #xml_file.
187  *
188  * Returns 0 on success or a negative value if an error occurs.
189  */
190 int 
191 verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
192     xmlDocPtr doc = NULL;
193     xmlNodePtr node = NULL;
194     xmlSecDSigCtxPtr dsigCtx = NULL;
195     int res = -1;
196     
197     assert(mngr);
198     assert(xml_file);
199
200     /* load file */
201     doc = xmlParseFile(xml_file);
202     if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
203         fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
204         goto done;      
205     }
206     
207     /* find start node */
208     node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
209     if(node == NULL) {
210         fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
211         goto done;      
212     }
213
214     /* create signature context */
215     dsigCtx = xmlSecDSigCtxCreate(mngr);
216     if(dsigCtx == NULL) {
217         fprintf(stderr,"Error: failed to create signature context\n");
218         goto done;
219     }
220
221     /* Verify signature */
222     if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
223         fprintf(stderr,"Error: signature verify\n");
224         goto done;
225     }
226         
227     /* print verification result to stdout */
228     if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
229         fprintf(stdout, "Signature is OK\n");
230     } else {
231         fprintf(stdout, "Signature is INVALID\n");
232     }    
233
234     /* success */
235     res = 0;
236
237 done:    
238     /* cleanup */
239     if(dsigCtx != NULL) {
240         xmlSecDSigCtxDestroy(dsigCtx);
241     }
242     
243     if(doc != NULL) {
244         xmlFreeDoc(doc); 
245     }
246     return(res);
247 }
248
249