source: TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/decrypt3.c @ 7080

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/decrypt3.c@7080
Revision 7080, 10.0 KB checked in by pjkersha, 9 years ago (diff)
  • Property svn:keywords set to Id
Line 
1/**
2 * XML Security Library example: Decrypting an encrypted file using a custom keys manager.
3 *
4 * Decrypts encrypted XML file using a custom files based keys manager.
5 * We assume that key's name in <dsig:KeyName/> element is just
6 * key's file name in the current folder.
7 *
8 * Usage:
9 *      ./decrypt3 <xml-enc>
10 *
11 * Example:
12 *      ./decrypt3 encrypt1-res.xml
13 *      ./decrypt3 encrypt2-res.xml
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 <ctype.h>
23#include <assert.h>
24
25#include <libxml/tree.h>
26#include <libxml/xmlmemory.h>
27#include <libxml/parser.h>
28
29#ifndef XMLSEC_NO_XSLT
30#include <libxslt/xslt.h>
31#endif /* XMLSEC_NO_XSLT */
32
33#include <xmlsec/xmlsec.h>
34#include <xmlsec/xmltree.h>
35#include <xmlsec/xmlenc.h>
36#include <xmlsec/crypto.h>
37
38xmlSecKeyStoreId  files_keys_store_get_klass(void);
39xmlSecKeysMngrPtr create_files_keys_mngr(void);
40int decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file);
41
42int 
43main(int argc, char **argv) {
44    xmlSecKeysMngrPtr mngr;
45
46    assert(argv);
47
48    if(argc != 2) {
49        fprintf(stderr, "Error: wrong number of arguments.\n");
50        fprintf(stderr, "Usage: %s <enc-file>\n", argv[0]);
51        return(1);
52    }
53
54    /* Init libxml and libxslt libraries */
55    xmlInitParser();
56    LIBXML_TEST_VERSION
57    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
58    xmlSubstituteEntitiesDefault(1);
59#ifndef XMLSEC_NO_XSLT
60    xmlIndentTreeOutput = 1; 
61#endif /* XMLSEC_NO_XSLT */
62               
63    /* Init xmlsec library */
64    if(xmlSecInit() < 0) {
65        fprintf(stderr, "Error: xmlsec initialization failed.\n");
66        return(-1);
67    }
68
69    /* Check loaded library version */
70    if(xmlSecCheckVersion() != 1) {
71        fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
72        return(-1);
73    }
74
75    /* Load default crypto engine if we are supporting dynamic
76     * loading for xmlsec-crypto libraries. Use the crypto library
77     * name ("openssl", "nss", etc.) to load corresponding
78     * xmlsec-crypto library.
79     */
80#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
81    if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
82        fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
83                        "that you have it installed and check shared libraries path\n"
84                        "(LD_LIBRARY_PATH) envornment variable.\n");
85        return(-1);     
86    }
87#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
88
89    /* Init crypto library */
90    if(xmlSecCryptoAppInit(NULL) < 0) {
91        fprintf(stderr, "Error: crypto initialization failed.\n");
92        return(-1);
93    }
94
95    /* Init xmlsec-crypto library */
96    if(xmlSecCryptoInit() < 0) {
97        fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
98        return(-1);
99    }
100
101    /* create keys manager and load keys */
102    mngr = create_files_keys_mngr();
103    if(mngr == NULL) {
104        return(-1);
105    }
106
107    if(decrypt_file(mngr, argv[1]) < 0) {
108        xmlSecKeysMngrDestroy(mngr);   
109        return(-1);
110    }   
111
112    /* destroy keys manager */
113    xmlSecKeysMngrDestroy(mngr);
114   
115    /* Shutdown xmlsec-crypto library */
116    xmlSecCryptoShutdown();
117   
118    /* Shutdown crypto library */
119    xmlSecCryptoAppShutdown();
120   
121    /* Shutdown xmlsec library */
122    xmlSecShutdown();
123
124    /* Shutdown libxslt/libxml */
125#ifndef XMLSEC_NO_XSLT
126    xsltCleanupGlobals();           
127#endif /* XMLSEC_NO_XSLT */
128    xmlCleanupParser();
129   
130    return(0);
131}
132
133/**
134 * decrypt_file:
135 * @mngr:               the pointer to keys manager.
136 * @enc_file:           the encrypted XML  file name.
137 *
138 * Decrypts the XML file #enc_file using DES key from #key_file and
139 * prints results to stdout.
140 *
141 * Returns 0 on success or a negative value if an error occurs.
142 */
143int 
144decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file) {
145    xmlDocPtr doc = NULL;
146    xmlNodePtr node = NULL;
147    xmlSecEncCtxPtr encCtx = NULL;
148    int res = -1;
149   
150    assert(mngr);
151    assert(enc_file);
152
153    /* load template */
154    doc = xmlParseFile(enc_file);
155    if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
156        fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
157        goto done;     
158    }
159   
160    /* find start node */
161    node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
162    if(node == NULL) {
163        fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
164        goto done;     
165    }
166
167    /* create encryption context */
168    encCtx = xmlSecEncCtxCreate(mngr);
169    if(encCtx == NULL) {
170        fprintf(stderr,"Error: failed to create encryption context\n");
171        goto done;
172    }
173
174    /* decrypt the data */
175    if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
176        fprintf(stderr,"Error: decryption failed\n");
177        goto done;
178    }
179       
180    /* print decrypted data to stdout */
181    if(encCtx->resultReplaced != 0) {
182        fprintf(stdout, "Decrypted XML data:\n");
183        xmlDocDump(stdout, doc);
184    } else {
185        fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
186        if(xmlSecBufferGetData(encCtx->result) != NULL) {
187            fwrite(xmlSecBufferGetData(encCtx->result), 
188                  1, 
189                  xmlSecBufferGetSize(encCtx->result),
190                  stdout);
191        }
192    }
193    fprintf(stdout, "\n");
194       
195    /* success */
196    res = 0;
197
198done:   
199    /* cleanup */
200    if(encCtx != NULL) {
201        xmlSecEncCtxDestroy(encCtx);
202    }
203   
204    if(doc != NULL) {
205        xmlFreeDoc(doc); 
206    }
207    return(res);
208}
209
210/**
211 * create_files_keys_mngr:
212 * 
213 * Creates a files based keys manager: we assume that key name is
214 * the key file name,
215 *
216 * Returns pointer to newly created keys manager or NULL if an error occurs.
217 */
218xmlSecKeysMngrPtr
219create_files_keys_mngr(void) {
220    xmlSecKeyStorePtr keysStore;
221    xmlSecKeysMngrPtr mngr;
222
223    /* create files based keys store */
224    keysStore = xmlSecKeyStoreCreate(files_keys_store_get_klass());
225    if(keysStore == NULL) {
226        fprintf(stderr, "Error: failed to create keys store.\n");
227        return(NULL);
228    }
229   
230    /* create keys manager */
231    mngr = xmlSecKeysMngrCreate();
232    if(mngr == NULL) {
233        fprintf(stderr, "Error: failed to create keys manager.\n");
234        xmlSecKeyStoreDestroy(keysStore);
235        return(NULL);
236    }
237
238    /* add store to keys manager, from now on keys manager destroys the store if needed */
239    if(xmlSecKeysMngrAdoptKeysStore(mngr, keysStore) < 0) {
240        fprintf(stderr, "Error: failed to add keys store to keys manager.\n");
241        xmlSecKeyStoreDestroy(keysStore);
242        xmlSecKeysMngrDestroy(mngr);
243        return(NULL);
244    }
245   
246    /* initialize crypto library specific data in keys manager */
247    if(xmlSecCryptoKeysMngrInit(mngr) < 0) {
248        fprintf(stderr, "Error: failed to initialize crypto data in keys manager.\n");
249        xmlSecKeysMngrDestroy(mngr);
250        return(NULL);
251    }
252
253    /* set the get key callback */
254    mngr->getKey = xmlSecKeysMngrGetKey;
255    return(mngr);
256}
257
258/****************************************************************************
259 *
260 * Files Keys Store: we assume that key's name (content of the
261 * <dsig:KeyName/> element is a name of the file with a key (in the
262 * current folder).
263 * Attention: this probably not a good solution for high traffic systems.
264 *
265 ***************************************************************************/
266static xmlSecKeyPtr             files_keys_store_find_key       (xmlSecKeyStorePtr store,
267                                                                 const xmlChar* name,
268                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
269static xmlSecKeyStoreKlass files_keys_store_klass = {
270    sizeof(xmlSecKeyStoreKlass),
271    sizeof(xmlSecKeyStore),
272    BAD_CAST "files-based-keys-store",  /* const xmlChar* name; */         
273    NULL,                               /* xmlSecKeyStoreInitializeMethod initialize; */
274    NULL,                               /* xmlSecKeyStoreFinalizeMethod finalize; */
275    files_keys_store_find_key,          /* xmlSecKeyStoreFindKeyMethod findKey; */
276
277    /* reserved for the future */
278    NULL,                               /* void* reserved0; */
279    NULL,                               /* void* reserved1; */
280};
281
282/**
283 * files_keys_store_get_klass:
284 *
285 * The files based keys store klass: we assume that key name is the
286 * key file name,
287 *
288 * Returns files based keys store klass.
289 */
290xmlSecKeyStoreId
291files_keys_store_get_klass(void) {
292    return(&files_keys_store_klass);
293}
294
295/**
296 * files_keys_store_find_key:
297 * @store:              the pointer to simple keys store.
298 * @name:               the desired key name.
299 * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> node processing context.
300 * 
301 * Lookups key in the @store. The caller is responsible for destroying
302 * returned key with #xmlSecKeyDestroy function.
303 *
304 * Returns pointer to key or NULL if key not found or an error occurs.
305 */
306static xmlSecKeyPtr
307files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
308    xmlSecKeyPtr key;
309    const xmlChar* p;
310   
311    assert(store);
312    assert(keyInfoCtx);
313
314    /* it's possible to do not have the key name or desired key type
315     * but we could do nothing in this case */
316    if((name == NULL) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataIdUnknown)){
317        return(NULL);
318    }
319   
320    /* we don't want to open files in a folder other than "current";
321     * to prevent it limit the characters in the key name to alpha/digit,
322     * '.', '-' or '_'.
323     */
324    for(p = name; (*p) != '\0'; ++p) {
325        if(!isalnum((*p)) && ((*p) != '.') && ((*p) != '-') && ((*p) != '_')) {
326            return(NULL);
327        }
328    }
329   
330    if((keyInfoCtx->keyReq.keyId == xmlSecKeyDataDsaId) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataRsaId)) {
331        /* load key from a pem file, if key is not found then it's an error (is it?) */
332        key = xmlSecCryptoAppKeyLoad(name, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
333        if(key == NULL) {
334            fprintf(stderr,"Error: failed to load public pem key from \"%s\"\n", name);
335            return(NULL);
336        }
337    } else {
338        /* otherwise it's a binary key, if key is not found then it's an error (is it?) */
339        key = xmlSecKeyReadBinaryFile(keyInfoCtx->keyReq.keyId, name);
340        if(key == NULL) {
341            fprintf(stderr,"Error: failed to load key from binary file \"%s\"\n", name);
342            return(NULL);
343        }
344    }
345
346    /* set key name */
347    if(xmlSecKeySetName(key, name) < 0) {
348        fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", name);
349        xmlSecKeyDestroy(key);
350        return(NULL);   
351    }
352
353    return(key);
354}
355
Note: See TracBrowser for help on using the repository browser.