1 /*
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  *
5  * This is free software; see Copyright file in the source
6  * distribution for preciese wording.
7  *
8  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:templates
12  * @Short_description: XML signature and encryption template functions.
13  * @Stability: Stable
14  *
15  */
16 #include "globals.h"
17 
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <libxml/tree.h>
22 
23 #include <xmlsec/xmlsec.h>
24 #include <xmlsec/xmltree.h>
25 #include <xmlsec/transforms.h>
26 #include <xmlsec/strings.h>
27 #include <xmlsec/base64.h>
28 #include <xmlsec/templates.h>
29 #include <xmlsec/errors.h>
30 
31 
32 static xmlNodePtr       xmlSecTmplAddReference          (xmlNodePtr parentNode,
33                                                          xmlSecTransformId digestMethodId,
34                                                          const xmlChar *id,
35                                                          const xmlChar *uri,
36                                                          const xmlChar *type);
37 static int              xmlSecTmplPrepareEncData        (xmlNodePtr parentNode,
38                                                          xmlSecTransformId encMethodId);
39 static int              xmlSecTmplNodeWriteNsList       (xmlNodePtr parentNode,
40                                                          const xmlChar** namespaces);
41 /**************************************************************************
42  *
43  * <dsig:Signature/> node
44  *
45  **************************************************************************/
46 /**
47  * xmlSecTmplSignatureCreate:
48  * @doc:                the pointer to signature document or NULL; in the
49  *                      second case, application must later call @xmlSetTreeDoc
50  *                      to ensure that all the children nodes have correct
51  *                      pointer to XML document.
52  * @c14nMethodId:       the signature canonicalization method.
53  * @signMethodId:       the signature  method.
54  * @id:                 the node id (may be NULL).
55  *
56  * Creates new <dsig:Signature/> node with the mandatory <dsig:SignedInfo/>,
57  * <dsig:CanonicalizationMethod/>, <dsig:SignatureMethod/> and
58  * <dsig:SignatureValue/> children and sub-children.
59  * The application is responsible for inserting the returned node
60  * in the XML document.
61  *
62  * Returns: the pointer to newly created <dsig:Signature/> node or NULL if an
63  * error occurs.
64  */
65 xmlNodePtr
xmlSecTmplSignatureCreate(xmlDocPtr doc,xmlSecTransformId c14nMethodId,xmlSecTransformId signMethodId,const xmlChar * id)66 xmlSecTmplSignatureCreate(xmlDocPtr doc, xmlSecTransformId c14nMethodId,
67                       xmlSecTransformId signMethodId, const xmlChar *id) {
68     return xmlSecTmplSignatureCreateNsPref(doc, c14nMethodId, signMethodId, id, NULL);
69 }
70 
71 /**
72  * xmlSecTmplSignatureCreateNsPref:
73  * @doc:                the pointer to signature document or NULL; in the
74  *                      second case, application must later call @xmlSetTreeDoc
75  *                      to ensure that all the children nodes have correct
76  *                      pointer to XML document.
77  * @c14nMethodId:       the signature canonicalization method.
78  * @signMethodId:       the signature  method.
79  * @id:                 the node id (may be NULL).
80  * @nsPrefix:   the namespace prefix for the signature element (e.g. "dsig"), or NULL
81  *
82  * Creates new <dsig:Signature/> node with the mandatory
83  * <dsig:SignedInfo/>, <dsig:CanonicalizationMethod/>,
84  * <dsig:SignatureMethod/> and <dsig:SignatureValue/> children and
85  * sub-children. This method differs from xmlSecTmplSignatureCreate in
86  * that it will define the http://www.w3.org/2000/09/xmldsig#
87  * namespace with the given prefix that will be used for all of the
88  * appropriate child nodes.  The application is responsible for
89  * inserting the returned node in the XML document.
90  *
91  * Returns: the pointer to newly created <dsig:Signature/> node or NULL if an
92  * error occurs.
93  */
94 xmlNodePtr
xmlSecTmplSignatureCreateNsPref(xmlDocPtr doc,xmlSecTransformId c14nMethodId,xmlSecTransformId signMethodId,const xmlChar * id,const xmlChar * nsPrefix)95 xmlSecTmplSignatureCreateNsPref(xmlDocPtr doc, xmlSecTransformId c14nMethodId,
96                                 xmlSecTransformId signMethodId, const xmlChar *id,
97                                 const xmlChar* nsPrefix) {
98     xmlNodePtr signNode;
99     xmlNodePtr signedInfoNode;
100     xmlNodePtr cur;
101     xmlNsPtr ns;
102 
103     xmlSecAssert2(c14nMethodId != NULL, NULL);
104     xmlSecAssert2(c14nMethodId->href != NULL, NULL);
105     xmlSecAssert2(signMethodId != NULL, NULL);
106     xmlSecAssert2(signMethodId->href != NULL, NULL);
107 
108     /* create Signature node itself */
109     signNode = xmlNewDocNode(doc, NULL, xmlSecNodeSignature, NULL);
110     if(signNode == NULL) {
111         xmlSecXmlError2("xmlNewDocNode", NULL,
112                         "node=%s", xmlSecErrorsSafeString(xmlSecNodeSignature));
113         return(NULL);
114     }
115 
116     ns = xmlNewNs(signNode, xmlSecDSigNs, nsPrefix);
117     if(ns == NULL) {
118         xmlSecXmlError2("xmlNewNs", NULL,
119                         "ns=%s", xmlSecErrorsSafeString(xmlSecDSigNs));
120         xmlFreeNode(signNode);
121         return(NULL);
122     }
123     xmlSetNs(signNode, ns);
124 
125     if(id != NULL) {
126         xmlSetProp(signNode, BAD_CAST "Id", id);
127     }
128 
129     /* add SignedInfo node */
130     signedInfoNode = xmlSecAddChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
131     if(signedInfoNode == NULL) {
132         xmlSecInternalError("xmlSecAddChild(xmlSecNodeSignedInfo)", NULL);
133         xmlFreeNode(signNode);
134         return(NULL);
135     }
136 
137     /* add SignatureValue node */
138     cur = xmlSecAddChild(signNode, xmlSecNodeSignatureValue, xmlSecDSigNs);
139     if(cur == NULL) {
140         xmlSecInternalError("xmlSecAddChild(xmlSecNodeSignatureValue)", NULL);
141         xmlFreeNode(signNode);
142         return(NULL);
143     }
144 
145     /* add CanonicalizationMethod node to SignedInfo */
146     cur = xmlSecAddChild(signedInfoNode, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs);
147     if(cur == NULL) {
148         xmlSecInternalError("xmlSecAddChild(xmlSecNodeCanonicalizationMethod)", NULL);
149         xmlFreeNode(signNode);
150         return(NULL);
151     }
152     if(xmlSetProp(cur, xmlSecAttrAlgorithm, c14nMethodId->href) == NULL) {
153         xmlSecXmlError2("xmlSetProp", NULL,
154                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
155         xmlFreeNode(signNode);
156         return(NULL);
157     }
158 
159     /* add SignatureMethod node to SignedInfo */
160     cur = xmlSecAddChild(signedInfoNode, xmlSecNodeSignatureMethod, xmlSecDSigNs);
161     if(cur == NULL) {
162         xmlSecInternalError("xmlSecAddChild(xmlSecNodeSignatureMethod)", NULL);
163         xmlFreeNode(signNode);
164         return(NULL);
165     }
166     if(xmlSetProp(cur, xmlSecAttrAlgorithm, signMethodId->href) == NULL) {
167         xmlSecXmlError2("xmlSetProp", NULL,
168                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
169         xmlFreeNode(signNode);
170         return(NULL);
171     }
172 
173     return(signNode);
174 }
175 
176 /**
177  * xmlSecTmplSignatureEnsureKeyInfo:
178  * @signNode:           the  pointer to <dsig:Signature/> node.
179  * @id:                 the node id (may be NULL).
180  *
181  * Adds (if necessary) <dsig:KeyInfo/> node to the <dsig:Signature/>
182  * node @signNode.
183  *
184  * Returns: the pointer to newly created <dsig:KeyInfo/> node or NULL if an
185  * error occurs.
186  */
187 xmlNodePtr
xmlSecTmplSignatureEnsureKeyInfo(xmlNodePtr signNode,const xmlChar * id)188 xmlSecTmplSignatureEnsureKeyInfo(xmlNodePtr signNode, const xmlChar *id) {
189     xmlNodePtr res;
190 
191     xmlSecAssert2(signNode != NULL, NULL);
192 
193     res = xmlSecFindChild(signNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
194     if(res == NULL) {
195         xmlNodePtr signValueNode;
196 
197         signValueNode = xmlSecFindChild(signNode, xmlSecNodeSignatureValue, xmlSecDSigNs);
198         if(signValueNode == NULL) {
199             xmlSecNodeNotFoundError("xmlSecFindChild", signNode,
200                                     xmlSecNodeSignatureValue, NULL);
201             return(NULL);
202         }
203 
204         res = xmlSecAddNextSibling(signValueNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
205         if(res == NULL) {
206             xmlSecInternalError("xmlSecAddNextSibling(xmlSecNodeKeyInfo)", NULL);
207             return(NULL);
208         }
209     }
210     if(id != NULL) {
211         xmlSetProp(res, xmlSecAttrId, id);
212     }
213     return(res);
214 }
215 
216 /**
217  * xmlSecTmplSignatureAddReference:
218  * @signNode:           the pointer to <dsig:Signature/> node.
219  * @digestMethodId:     the reference digest method.
220  * @id:                 the node id (may be NULL).
221  * @uri:                the reference node uri (may be NULL).
222  * @type:               the reference node type (may be NULL).
223  *
224  * Adds <dsig:Reference/> node with given URI (@uri), Id (@id) and
225  * Type (@type) attributes and the required children <dsig:DigestMethod/> and
226  * <dsig:DigestValue/> to the <dsig:SignedInfo/> child of @signNode.
227  *
228  * Returns: the pointer to newly created <dsig:Reference/> node or NULL
229  * if an error occurs.
230  */
231 xmlNodePtr
xmlSecTmplSignatureAddReference(xmlNodePtr signNode,xmlSecTransformId digestMethodId,const xmlChar * id,const xmlChar * uri,const xmlChar * type)232 xmlSecTmplSignatureAddReference(xmlNodePtr signNode, xmlSecTransformId digestMethodId,
233                     const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
234     xmlNodePtr signedInfoNode;
235 
236     xmlSecAssert2(signNode != NULL, NULL);
237     xmlSecAssert2(digestMethodId != NULL, NULL);
238     xmlSecAssert2(digestMethodId->href != NULL, NULL);
239 
240     signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
241     if(signedInfoNode == NULL) {
242         xmlSecNodeNotFoundError("xmlSecFindChild", signNode,
243                                 xmlSecNodeSignedInfo, NULL);
244         return(NULL);
245     }
246 
247     return(xmlSecTmplAddReference(signedInfoNode, digestMethodId, id, uri, type));
248 }
249 
250 static xmlNodePtr
xmlSecTmplAddReference(xmlNodePtr parentNode,xmlSecTransformId digestMethodId,const xmlChar * id,const xmlChar * uri,const xmlChar * type)251 xmlSecTmplAddReference(xmlNodePtr parentNode, xmlSecTransformId digestMethodId,
252                     const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
253     xmlNodePtr res;
254     xmlNodePtr cur;
255 
256     xmlSecAssert2(parentNode != NULL, NULL);
257     xmlSecAssert2(digestMethodId != NULL, NULL);
258     xmlSecAssert2(digestMethodId->href != NULL, NULL);
259 
260     /* add Reference node */
261     res = xmlSecAddChild(parentNode, xmlSecNodeReference, xmlSecDSigNs);
262     if(res == NULL) {
263         xmlSecInternalError("xmlSecAddChild(xmlSecNodeReference)", NULL);
264         return(NULL);
265     }
266 
267     /* set Reference node attributes */
268     if(id != NULL) {
269         xmlSetProp(res, xmlSecAttrId, id);
270     }
271     if(type != NULL) {
272         xmlSetProp(res, xmlSecAttrType, type);
273     }
274     if(uri != NULL) {
275         xmlSetProp(res, xmlSecAttrURI, uri);
276     }
277 
278     /* add DigestMethod node and set algorithm */
279     cur = xmlSecAddChild(res, xmlSecNodeDigestMethod, xmlSecDSigNs);
280     if(cur == NULL) {
281         xmlSecInternalError("xmlSecAddChild(xmlSecNodeDigestMethod)", NULL);
282         xmlUnlinkNode(res);
283         xmlFreeNode(res);
284         return(NULL);
285     }
286     if(xmlSetProp(cur, xmlSecAttrAlgorithm, digestMethodId->href) == NULL) {
287         xmlSecXmlError2("xmlSetProp", NULL,
288                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
289         xmlUnlinkNode(res);
290         xmlFreeNode(res);
291         return(NULL);
292     }
293 
294     /* add DigestValue node */
295     cur = xmlSecAddChild(res, xmlSecNodeDigestValue, xmlSecDSigNs);
296     if(cur == NULL) {
297         xmlSecInternalError("xmlSecAddChild(xmlSecNodeDigestValue)", NULL);
298         xmlUnlinkNode(res);
299         xmlFreeNode(res);
300         return(NULL);
301     }
302 
303     return(res);
304 }
305 
306 /**
307  * xmlSecTmplSignatureAddObject:
308  * @signNode:           the pointer to <dsig:Signature/> node.
309  * @id:                 the node id (may be NULL).
310  * @mimeType:           the object mime type (may be NULL).
311  * @encoding:           the object encoding (may be NULL).
312  *
313  * Adds <dsig:Object/> node to the <dsig:Signature/> node @signNode.
314  *
315  * Returns: the pointer to newly created <dsig:Object/> node or NULL
316  * if an error occurs.
317  */
318 xmlNodePtr
xmlSecTmplSignatureAddObject(xmlNodePtr signNode,const xmlChar * id,const xmlChar * mimeType,const xmlChar * encoding)319 xmlSecTmplSignatureAddObject(xmlNodePtr signNode, const xmlChar *id,
320                          const xmlChar *mimeType, const xmlChar *encoding) {
321     xmlNodePtr res;
322 
323     xmlSecAssert2(signNode != NULL, NULL);
324 
325     res = xmlSecAddChild(signNode, xmlSecNodeObject, xmlSecDSigNs);
326     if(res == NULL) {
327         xmlSecInternalError("xmlSecAddChild(xmlSecNodeObject)", NULL);
328         return(NULL);
329     }
330     if(id != NULL) {
331         xmlSetProp(res, xmlSecAttrId, id);
332     }
333     if(mimeType != NULL) {
334         xmlSetProp(res, xmlSecAttrMimeType, mimeType);
335     }
336     if(encoding != NULL) {
337         xmlSetProp(res, xmlSecAttrEncoding, encoding);
338     }
339     return(res);
340 }
341 
342 /**
343  * xmlSecTmplSignatureGetSignMethodNode:
344  * @signNode:           the pointer to <dsig:Signature /> node.
345  *
346  * Gets pointer to <dsig:SignatureMethod/> child of <dsig:KeyInfo/> node.
347  *
348  * Returns: pointer to <dsig:SignatureMethod /> node or NULL if an error occurs.
349  */
350 xmlNodePtr
xmlSecTmplSignatureGetSignMethodNode(xmlNodePtr signNode)351 xmlSecTmplSignatureGetSignMethodNode(xmlNodePtr signNode) {
352     xmlNodePtr signedInfoNode;
353 
354     xmlSecAssert2(signNode != NULL, NULL);
355 
356     signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
357     if(signedInfoNode == NULL) {
358         xmlSecNodeNotFoundError("xmlSecFindChild", signNode,
359                                 xmlSecNodeSignedInfo, NULL);
360         return(NULL);
361     }
362     return(xmlSecFindChild(signedInfoNode, xmlSecNodeSignatureMethod, xmlSecDSigNs));
363 }
364 
365 /**
366  * xmlSecTmplSignatureGetC14NMethodNode:
367  * @signNode:           the pointer to <dsig:Signature /> node.
368  *
369  * Gets pointer to <dsig:CanonicalizationMethod/> child of <dsig:KeyInfo/> node.
370  *
371  * Returns: pointer to <dsig:CanonicalizationMethod /> node or NULL if an error occurs.
372  */
373 xmlNodePtr
xmlSecTmplSignatureGetC14NMethodNode(xmlNodePtr signNode)374 xmlSecTmplSignatureGetC14NMethodNode(xmlNodePtr signNode) {
375     xmlNodePtr signedInfoNode;
376 
377     xmlSecAssert2(signNode != NULL, NULL);
378 
379     signedInfoNode = xmlSecFindChild(signNode, xmlSecNodeSignedInfo, xmlSecDSigNs);
380     if(signedInfoNode == NULL) {
381         xmlSecNodeNotFoundError("xmlSecFindChild", signNode,
382                                 xmlSecNodeSignedInfo, NULL);
383         return(NULL);
384     }
385     return(xmlSecFindChild(signedInfoNode, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs));
386 }
387 
388 /**
389  * xmlSecTmplReferenceAddTransform:
390  * @referenceNode:              the pointer to <dsig:Reference/> node.
391  * @transformId:                the transform method id.
392  *
393  * Adds <dsig:Transform/> node to the <dsig:Reference/> node @referenceNode.
394  *
395  * Returns: the pointer to newly created <dsig:Transform/> node or NULL if an
396  * error occurs.
397  */
398 xmlNodePtr
xmlSecTmplReferenceAddTransform(xmlNodePtr referenceNode,xmlSecTransformId transformId)399 xmlSecTmplReferenceAddTransform(xmlNodePtr referenceNode, xmlSecTransformId transformId) {
400     xmlNodePtr transformsNode;
401     xmlNodePtr res;
402 
403     xmlSecAssert2(referenceNode != NULL, NULL);
404     xmlSecAssert2(transformId != NULL, NULL);
405     xmlSecAssert2(transformId->href != NULL, NULL);
406 
407     /* do we need to create Transforms node first */
408     transformsNode = xmlSecFindChild(referenceNode, xmlSecNodeTransforms, xmlSecDSigNs);
409     if(transformsNode == NULL) {
410         xmlNodePtr tmp;
411 
412         tmp = xmlSecGetNextElementNode(referenceNode->children);
413         if(tmp == NULL) {
414             transformsNode = xmlSecAddChild(referenceNode, xmlSecNodeTransforms, xmlSecDSigNs);
415             if(transformsNode == NULL) {
416                 xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransforms)", NULL);
417                 return(NULL);
418             }
419         } else {
420             transformsNode = xmlSecAddPrevSibling(tmp, xmlSecNodeTransforms, xmlSecDSigNs);
421             if(transformsNode == NULL) {
422                 xmlSecInternalError("xmlSecAddPrevSibling(xmlSecNodeTransforms)", NULL);
423                 return(NULL);
424             }
425         }
426     }
427 
428     res = xmlSecAddChild(transformsNode, xmlSecNodeTransform, xmlSecDSigNs);
429     if(res == NULL) {
430         xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransform)", NULL);
431         return(NULL);
432     }
433 
434     if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
435         xmlSecXmlError2("xmlSetProp", NULL,
436                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
437         xmlUnlinkNode(res);
438         xmlFreeNode(res);
439         return(NULL);
440     }
441 
442     return(res);
443 }
444 
445 /**
446  * xmlSecTmplObjectAddSignProperties:
447  * @objectNode:         the  pointer to <dsig:Object/> node.
448  * @id:                 the node id (may be NULL).
449  * @target:             the Target  (may be NULL).
450  *
451  * Adds <dsig:SignatureProperties/> node to the <dsig:Object/> node @objectNode.
452  *
453  * Returns: the pointer to newly created <dsig:SignatureProperties/> node or NULL
454  * if an error occurs.
455  */
456 xmlNodePtr
xmlSecTmplObjectAddSignProperties(xmlNodePtr objectNode,const xmlChar * id,const xmlChar * target)457 xmlSecTmplObjectAddSignProperties(xmlNodePtr objectNode, const xmlChar *id, const xmlChar *target) {
458     xmlNodePtr res;
459 
460     xmlSecAssert2(objectNode != NULL, NULL);
461 
462     res = xmlSecAddChild(objectNode, xmlSecNodeSignatureProperties, xmlSecDSigNs);
463     if(res == NULL) {
464         xmlSecInternalError("xmlSecAddChild(xmlSecNodeSignatureProperties)", NULL);
465         return(NULL);
466     }
467     if(id != NULL) {
468         xmlSetProp(res, xmlSecAttrId, id);
469     }
470     if(target != NULL) {
471         xmlSetProp(res, xmlSecAttrTarget, target);
472     }
473     return(res);
474 }
475 
476 /**
477  * xmlSecTmplObjectAddManifest:
478  * @objectNode:         the  pointer to <dsig:Object/> node.
479  * @id:                 the node id (may be NULL).
480  *
481  * Adds <dsig:Manifest/> node to the <dsig:Object/> node @objectNode.
482  *
483  * Returns: the pointer to newly created <dsig:Manifest/> node or NULL
484  * if an error occurs.
485  */
486 xmlNodePtr
xmlSecTmplObjectAddManifest(xmlNodePtr objectNode,const xmlChar * id)487 xmlSecTmplObjectAddManifest(xmlNodePtr objectNode,  const xmlChar *id) {
488     xmlNodePtr res;
489 
490     xmlSecAssert2(objectNode != NULL, NULL);
491 
492     res = xmlSecAddChild(objectNode, xmlSecNodeManifest, xmlSecDSigNs);
493     if(res == NULL) {
494         xmlSecInternalError("xmlSecAddChild(xmlSecNodeManifest)", NULL);
495         return(NULL);
496     }
497     if(id != NULL) {
498         xmlSetProp(res, xmlSecAttrId, id);
499     }
500     return(res);
501 }
502 
503 /**
504  * xmlSecTmplManifestAddReference:
505  * @manifestNode:       the pointer to <dsig:Manifest/> node.
506  * @digestMethodId:     the reference digest method.
507  * @id:                 the node id (may be NULL).
508  * @uri:                the reference node uri (may be NULL).
509  * @type:               the reference node type (may be NULL).
510  *
511  * Adds <dsig:Reference/> node with specified URI (@uri), Id (@id) and
512  * Type (@type) attributes and the required children <dsig:DigestMethod/> and
513  * <dsig:DigestValue/> to the <dsig:Manifest/> node @manifestNode.
514  *
515  * Returns: the pointer to newly created <dsig:Reference/> node or NULL
516  * if an error occurs.
517  */
518 xmlNodePtr
xmlSecTmplManifestAddReference(xmlNodePtr manifestNode,xmlSecTransformId digestMethodId,const xmlChar * id,const xmlChar * uri,const xmlChar * type)519 xmlSecTmplManifestAddReference(xmlNodePtr manifestNode, xmlSecTransformId digestMethodId,
520                               const xmlChar *id, const xmlChar *uri, const xmlChar *type) {
521     return(xmlSecTmplAddReference(manifestNode, digestMethodId, id, uri, type));
522 }
523 
524 /**************************************************************************
525  *
526  * <enc:EncryptedData/> node
527  *
528  **************************************************************************/
529 /**
530  * xmlSecTmplEncDataCreate:
531  * @doc:                the pointer to signature document or NULL; in the later
532  *                      case, application must later call @xmlSetTreeDoc to ensure
533  *                      that all the children nodes have correct pointer to XML document.
534  * @encMethodId:        the encryption method (may be NULL).
535  * @id:                 the Id attribute (optional).
536  * @type:               the Type attribute (optional)
537  * @mimeType:           the MimeType attribute (optional)
538  * @encoding:           the Encoding attribute (optional)
539  *
540  * Creates new <enc:EncryptedData /> node for encryption template.
541  *
542  * Returns: the pointer newly created  <enc:EncryptedData/> node or NULL
543  * if an error occurs.
544  */
545 xmlNodePtr
xmlSecTmplEncDataCreate(xmlDocPtr doc,xmlSecTransformId encMethodId,const xmlChar * id,const xmlChar * type,const xmlChar * mimeType,const xmlChar * encoding)546 xmlSecTmplEncDataCreate(xmlDocPtr doc, xmlSecTransformId encMethodId,
547                             const xmlChar *id, const xmlChar *type,
548                             const xmlChar *mimeType, const xmlChar *encoding) {
549     xmlNodePtr encNode;
550     xmlNsPtr ns;
551 
552     encNode = xmlNewDocNode(doc, NULL, xmlSecNodeEncryptedData, NULL);
553     if(encNode == NULL) {
554         xmlSecXmlError2("xmlNewDocNode", NULL,
555                         "node=%s", xmlSecErrorsSafeString(xmlSecNodeEncryptedData));
556         return(NULL);
557     }
558 
559     ns = xmlNewNs(encNode, xmlSecEncNs, NULL);
560     if(ns == NULL) {
561         xmlSecXmlError2("xmlNewNs", NULL,
562                         "ns=%s", xmlSecErrorsSafeString(xmlSecEncNs));
563         return(NULL);
564     }
565     xmlSetNs(encNode, ns);
566 
567     if(id != NULL) {
568         xmlSetProp(encNode, xmlSecAttrId, id);
569     }
570     if(type != NULL) {
571         xmlSetProp(encNode, xmlSecAttrType, type);
572     }
573     if(mimeType != NULL) {
574         xmlSetProp(encNode, xmlSecAttrMimeType, mimeType);
575     }
576     if(encoding != NULL) {
577         xmlSetProp(encNode, xmlSecAttrEncoding, encoding);
578     }
579 
580     if(xmlSecTmplPrepareEncData(encNode, encMethodId) < 0) {
581         xmlFreeNode(encNode);
582         return(NULL);
583     }
584     return(encNode);
585 }
586 
587 static int
xmlSecTmplPrepareEncData(xmlNodePtr parentNode,xmlSecTransformId encMethodId)588 xmlSecTmplPrepareEncData(xmlNodePtr parentNode, xmlSecTransformId encMethodId) {
589     xmlNodePtr cur;
590 
591     xmlSecAssert2(parentNode != NULL, -1);
592     xmlSecAssert2((encMethodId == NULL) || (encMethodId->href != NULL), -1);
593 
594     /* add EncryptionMethod node if requested */
595     if(encMethodId != NULL) {
596         cur = xmlSecAddChild(parentNode, xmlSecNodeEncryptionMethod, xmlSecEncNs);
597         if(cur == NULL) {
598             xmlSecInternalError("xmlSecAddChild(xmlSecNodeEncryptionMethod)", NULL);
599             return(-1);
600         }
601         if(xmlSetProp(cur, xmlSecAttrAlgorithm, encMethodId->href) == NULL) {
602             xmlSecXmlError2("xmlSetProp", NULL,
603                             "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
604             return(-1);
605         }
606     }
607 
608     /* and CipherData node */
609     cur = xmlSecAddChild(parentNode, xmlSecNodeCipherData, xmlSecEncNs);
610     if(cur == NULL) {
611         xmlSecInternalError("xmlSecAddChild(xmlSecNodeCipherData)", NULL);
612         return(-1);
613     }
614 
615     return(0);
616 }
617 
618 
619 /**
620  * xmlSecTmplEncDataEnsureKeyInfo:
621  * @encNode:            the pointer to <enc:EncryptedData/> node.
622  * @id:                 the Id attrbibute (optional).
623  *
624  * Adds <dsig:KeyInfo/> to the  <enc:EncryptedData/> node @encNode.
625  *
626  * Returns: the pointer to newly created <dsig:KeyInfo/> node or
627  * NULL if an error occurs.
628  */
629 xmlNodePtr
xmlSecTmplEncDataEnsureKeyInfo(xmlNodePtr encNode,const xmlChar * id)630 xmlSecTmplEncDataEnsureKeyInfo(xmlNodePtr encNode, const xmlChar* id) {
631     xmlNodePtr res;
632 
633     xmlSecAssert2(encNode != NULL, NULL);
634 
635     res = xmlSecFindChild(encNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
636     if(res == NULL) {
637         xmlNodePtr cipherDataNode;
638 
639         cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
640         if(cipherDataNode == NULL) {
641             xmlSecNodeNotFoundError("xmlSecFindChild", encNode,
642                                     xmlSecNodeCipherData, NULL);
643             return(NULL);
644         }
645 
646         res = xmlSecAddPrevSibling(cipherDataNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
647         if(res == NULL) {
648             xmlSecInternalError("xmlSecAddPrevSibling(xmlSecNodeKeyInfo)", NULL);
649             return(NULL);
650         }
651     }
652     if(id != NULL) {
653         xmlSetProp(res, xmlSecAttrId, id);
654     }
655     return(res);
656 }
657 
658 /**
659  * xmlSecTmplEncDataEnsureEncProperties:
660  * @encNode:            the pointer to <enc:EncryptedData/> node.
661  * @id:                 the Id attribute (optional).
662  *
663  * Adds <enc:EncryptionProperties/> node to the <enc:EncryptedData/>
664  * node @encNode.
665  *
666  * Returns: the pointer to newly created <enc:EncryptionProperties/> node or
667  * NULL if an error occurs.
668  */
669 xmlNodePtr
xmlSecTmplEncDataEnsureEncProperties(xmlNodePtr encNode,const xmlChar * id)670 xmlSecTmplEncDataEnsureEncProperties(xmlNodePtr encNode, const xmlChar *id) {
671     xmlNodePtr res;
672 
673     xmlSecAssert2(encNode != NULL, NULL);
674 
675     res = xmlSecFindChild(encNode, xmlSecNodeEncryptionProperties, xmlSecEncNs);
676     if(res == NULL) {
677         res = xmlSecAddChild(encNode, xmlSecNodeEncryptionProperties, xmlSecEncNs);
678         if(res == NULL) {
679             xmlSecInternalError("xmlSecAddChild(xmlSecNodeEncryptionProperties)", NULL);
680             return(NULL);
681         }
682     }
683 
684     if(id != NULL) {
685         xmlSetProp(res, xmlSecAttrId, id);
686     }
687 
688     return(res);
689 }
690 
691 /**
692  * xmlSecTmplEncDataAddEncProperty:
693  * @encNode:            the pointer to <enc:EncryptedData/> node.
694  * @id:                 the Id attribute (optional).
695  * @target:             the Target attribute (optional).
696  *
697  * Adds <enc:EncryptionProperty/> node (and the parent
698  * <enc:EncryptionProperties/> node if required) to the
699  * <enc:EncryptedData/> node @encNode.
700  *
701  * Returns: the pointer to newly created <enc:EncryptionProperty/> node or
702  * NULL if an error occurs.
703  */
704 xmlNodePtr
xmlSecTmplEncDataAddEncProperty(xmlNodePtr encNode,const xmlChar * id,const xmlChar * target)705 xmlSecTmplEncDataAddEncProperty(xmlNodePtr encNode, const xmlChar *id, const xmlChar *target) {
706     xmlNodePtr encProps;
707     xmlNodePtr res;
708 
709     xmlSecAssert2(encNode != NULL, NULL);
710 
711     encProps = xmlSecTmplEncDataEnsureEncProperties(encNode, NULL);
712     if(encProps == NULL) {
713         xmlSecInternalError("xmlSecTmplEncDataEnsureEncProperties", NULL);
714         return(NULL);
715     }
716 
717     res = xmlSecAddChild(encProps, xmlSecNodeEncryptionProperty, xmlSecEncNs);
718     if(res == NULL) {
719         xmlSecInternalError("xmlSecAddChild(xmlSecNodeEncryptionProperty)", NULL);
720         return(NULL);
721     }
722     if(id != NULL) {
723         xmlSetProp(res, xmlSecAttrId, id);
724     }
725     if(target != NULL) {
726         xmlSetProp(res, xmlSecAttrTarget, target);
727     }
728 
729     return(res);
730 }
731 
732 /**
733  * xmlSecTmplEncDataEnsureCipherValue:
734  * @encNode:            the pointer to <enc:EncryptedData/> node.
735  *
736  * Adds <enc:CipherValue/> to the <enc:EncryptedData/> node @encNode.
737  *
738  * Returns: the pointer to newly created <enc:CipherValue/> node or
739  * NULL if an error occurs.
740  */
741 xmlNodePtr
xmlSecTmplEncDataEnsureCipherValue(xmlNodePtr encNode)742 xmlSecTmplEncDataEnsureCipherValue(xmlNodePtr encNode) {
743     xmlNodePtr cipherDataNode;
744     xmlNodePtr res, tmp;
745 
746     xmlSecAssert2(encNode != NULL, NULL);
747 
748     cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
749     if(cipherDataNode == NULL) {
750         xmlSecNodeNotFoundError("xmlSecFindChild", encNode,
751                                 xmlSecNodeCipherData, NULL);
752         return(NULL);
753     }
754 
755     /* check that we don;t have CipherReference node */
756     tmp = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
757     if(tmp != NULL) {
758         xmlSecNodeAlreadyPresentError(cipherDataNode, xmlSecNodeCipherReference, NULL);
759         return(NULL);
760     }
761 
762     res = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
763     if(res == NULL) {
764         res = xmlSecAddChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
765         if(res == NULL) {
766             xmlSecInternalError("xmlSecAddChild(xmlSecNodeCipherValue)", NULL);
767             return(NULL);
768         }
769     }
770 
771     return(res);
772 }
773 
774 /**
775  * xmlSecTmplEncDataEnsureCipherReference:
776  * @encNode:            the pointer to <enc:EncryptedData/> node.
777  * @uri:                the URI attribute (may be NULL).
778  *
779  * Adds <enc:CipherReference/> node with specified URI attribute @uri
780  * to the <enc:EncryptedData/> node @encNode.
781  *
782  * Returns: the pointer to newly created <enc:CipherReference/> node or
783  * NULL if an error occurs.
784  */
785 xmlNodePtr
xmlSecTmplEncDataEnsureCipherReference(xmlNodePtr encNode,const xmlChar * uri)786 xmlSecTmplEncDataEnsureCipherReference(xmlNodePtr encNode, const xmlChar *uri) {
787     xmlNodePtr cipherDataNode;
788     xmlNodePtr res, tmp;
789 
790     xmlSecAssert2(encNode != NULL, NULL);
791 
792     cipherDataNode = xmlSecFindChild(encNode, xmlSecNodeCipherData, xmlSecEncNs);
793     if(cipherDataNode == NULL) {
794         xmlSecNodeNotFoundError("xmlSecFindChild", encNode,
795                                 xmlSecNodeCipherData, NULL);
796         return(NULL);
797     }
798 
799     /* check that we don;t have CipherValue node */
800     tmp = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherValue, xmlSecEncNs);
801     if(tmp != NULL) {
802         xmlSecNodeAlreadyPresentError(cipherDataNode, xmlSecNodeCipherValue, NULL);
803         return(NULL);
804     }
805 
806     res = xmlSecFindChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
807     if(res == NULL) {
808         res = xmlSecAddChild(cipherDataNode, xmlSecNodeCipherReference, xmlSecEncNs);
809         if(res == NULL) {
810             xmlSecInternalError("xmlSecAddChild(xmlSecNodeCipherReference)", NULL);
811             return(NULL);
812         }
813     }
814 
815     if(uri != NULL) {
816         xmlSetProp(res, xmlSecAttrURI, uri);
817     }
818 
819     return(res);
820 }
821 
822 /**
823  * xmlSecTmplEncDataGetEncMethodNode:
824  * @encNode:            the pointer to <enc:EcnryptedData /> node.
825  *
826  * Gets pointer to <enc:EncryptionMethod/> node.
827  *
828  * Returns: pointer to <enc:EncryptionMethod /> node or NULL if an error occurs.
829  */
830 xmlNodePtr
xmlSecTmplEncDataGetEncMethodNode(xmlNodePtr encNode)831 xmlSecTmplEncDataGetEncMethodNode(xmlNodePtr encNode) {
832     xmlSecAssert2(encNode != NULL, NULL);
833 
834     return(xmlSecFindChild(encNode, xmlSecNodeEncryptionMethod, xmlSecEncNs));
835 }
836 
837 /**
838  * xmlSecTmplCipherReferenceAddTransform:
839  * @cipherReferenceNode:        the pointer to <enc:CipherReference/> node.
840  * @transformId:                the transform id.
841  *
842  * Adds <dsig:Transform/> node (and the parent <dsig:Transforms/> node)
843  * with specified transform methods @transform to the <enc:CipherReference/>
844  * child node of the <enc:EncryptedData/> node @encNode.
845  *
846  * Returns: the pointer to newly created <dsig:Transform/> node or
847  * NULL if an error occurs.
848  */
849 xmlNodePtr
xmlSecTmplCipherReferenceAddTransform(xmlNodePtr cipherReferenceNode,xmlSecTransformId transformId)850 xmlSecTmplCipherReferenceAddTransform(xmlNodePtr cipherReferenceNode,
851                                   xmlSecTransformId transformId) {
852     xmlNodePtr transformsNode;
853     xmlNodePtr res;
854 
855     xmlSecAssert2(cipherReferenceNode != NULL, NULL);
856     xmlSecAssert2(transformId != NULL, NULL);
857     xmlSecAssert2(transformId->href != NULL, NULL);
858 
859     transformsNode = xmlSecFindChild(cipherReferenceNode, xmlSecNodeTransforms, xmlSecEncNs);
860     if(transformsNode == NULL) {
861         transformsNode = xmlSecAddChild(cipherReferenceNode, xmlSecNodeTransforms, xmlSecEncNs);
862         if(transformsNode == NULL) {
863             xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransforms)", NULL);
864             return(NULL);
865         }
866     }
867 
868     res = xmlSecAddChild(transformsNode,  xmlSecNodeTransform, xmlSecDSigNs);
869     if(res == NULL) {
870         xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransform)", NULL);
871         return(NULL);
872     }
873 
874     if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
875         xmlSecXmlError2("xmlSetProp", NULL,
876                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
877         xmlUnlinkNode(res);
878         xmlFreeNode(res);
879         return(NULL);
880     }
881 
882     return(res);
883 }
884 
885 
886 /***********************************************************************
887  *
888  * <enc:EncryptedKey> node
889  *
890  **********************************************************************/
891 
892 /**
893  * xmlSecTmplReferenceListAddDataReference:
894  * @encNode:                    the pointer to <enc:EncryptedKey/> node.
895  * @uri:                        uri to reference (optional)
896  *
897  * Adds <enc:DataReference/> and the parent <enc:ReferenceList/> node (if needed).
898  *
899  * Returns: the pointer to newly created <enc:DataReference/> node or
900  * NULL if an error occurs.
901  */
902 xmlNodePtr
xmlSecTmplReferenceListAddDataReference(xmlNodePtr encNode,const xmlChar * uri)903 xmlSecTmplReferenceListAddDataReference(xmlNodePtr encNode, const xmlChar *uri) {
904     xmlNodePtr refListNode, res;
905 
906     xmlSecAssert2(encNode != NULL, NULL);
907 
908     refListNode = xmlSecFindChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
909     if(refListNode == NULL) {
910         refListNode = xmlSecAddChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
911         if(refListNode == NULL) {
912             xmlSecInternalError("xmlSecAddChild(xmlSecNodeReferenceList)", NULL);
913             return(NULL);
914         }
915     }
916 
917     res = xmlSecAddChild(refListNode,  xmlSecNodeDataReference, xmlSecEncNs);
918     if(res == NULL) {
919         xmlSecInternalError("xmlSecAddChild(xmlSecNodeDataReference)", NULL);
920         return(NULL);
921     }
922 
923     if(uri != NULL) {
924         if(xmlSetProp(res, xmlSecAttrURI, uri) == NULL) {
925             xmlSecXmlError2("xmlSetProp", NULL,
926                             "name=%s", xmlSecErrorsSafeString(xmlSecAttrURI));
927             xmlUnlinkNode(res);
928             xmlFreeNode(res);
929             return(NULL);
930         }
931     }
932 
933     return(res);
934 }
935 
936 /**
937  * xmlSecTmplReferenceListAddKeyReference:
938  * @encNode:                    the pointer to <enc:EncryptedKey/> node.
939  * @uri:                        uri to reference (optional)
940  *
941  * Adds <enc:KeyReference/> and the parent <enc:ReferenceList/> node (if needed).
942  *
943  * Returns: the pointer to newly created <enc:KeyReference/> node or
944  * NULL if an error occurs.
945  */
946 xmlNodePtr
xmlSecTmplReferenceListAddKeyReference(xmlNodePtr encNode,const xmlChar * uri)947 xmlSecTmplReferenceListAddKeyReference(xmlNodePtr encNode, const xmlChar *uri) {
948     xmlNodePtr refListNode, res;
949 
950     xmlSecAssert2(encNode != NULL, NULL);
951 
952     refListNode = xmlSecFindChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
953     if(refListNode == NULL) {
954         refListNode = xmlSecAddChild(encNode, xmlSecNodeReferenceList, xmlSecEncNs);
955         if(refListNode == NULL) {
956             xmlSecInternalError("xmlSecAddChild(xmlSecNodeReferenceList)", NULL);
957             return(NULL);
958         }
959     }
960 
961     res = xmlSecAddChild(refListNode,  xmlSecNodeKeyReference, xmlSecEncNs);
962     if(res == NULL) {
963         xmlSecInternalError("xmlSecAddChild(xmlSecNodeKeyReference)", NULL);
964         return(NULL);
965     }
966 
967     if(uri != NULL) {
968         if(xmlSetProp(res, xmlSecAttrURI, uri) == NULL) {
969             xmlSecXmlError2("xmlSetProp", NULL,
970                             "name=%s", xmlSecErrorsSafeString(xmlSecAttrURI));
971             xmlUnlinkNode(res);
972             xmlFreeNode(res);
973             return(NULL);
974         }
975     }
976 
977     return(res);
978 }
979 
980 
981 /**************************************************************************
982  *
983  * <dsig:KeyInfo/> node
984  *
985  **************************************************************************/
986 
987 /**
988  * xmlSecTmplKeyInfoAddKeyName:
989  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
990  * @name:               the key name (optional).
991  *
992  * Adds <dsig:KeyName/> node to the <dsig:KeyInfo/> node @keyInfoNode.
993  *
994  * Returns: the pointer to the newly created <dsig:KeyName/> node or
995  * NULL if an error occurs.
996  */
997 xmlNodePtr
xmlSecTmplKeyInfoAddKeyName(xmlNodePtr keyInfoNode,const xmlChar * name)998 xmlSecTmplKeyInfoAddKeyName(xmlNodePtr keyInfoNode, const xmlChar* name) {
999     xmlNodePtr res;
1000     int ret;
1001 
1002     xmlSecAssert2(keyInfoNode != NULL, NULL);
1003 
1004     res = xmlSecAddChild(keyInfoNode, xmlSecNodeKeyName, xmlSecDSigNs);
1005     if(res == NULL) {
1006         xmlSecInternalError("xmlSecAddChild(xmlSecNodeKeyName)", NULL);
1007         return(NULL);
1008     }
1009     if(name != NULL) {
1010         ret = xmlSecNodeEncodeAndSetContent(res, name);
1011         if(ret < 0) {
1012             xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1013             return(NULL);
1014         }
1015     }
1016     return(res);
1017 }
1018 
1019 /**
1020  * xmlSecTmplKeyInfoAddKeyValue:
1021  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
1022  *
1023  * Adds <dsig:KeyValue/> node to the <dsig:KeyInfo/> node @keyInfoNode.
1024  *
1025  * Returns: the pointer to the newly created <dsig:KeyValue/> node or
1026  * NULL if an error occurs.
1027  */
1028 xmlNodePtr
xmlSecTmplKeyInfoAddKeyValue(xmlNodePtr keyInfoNode)1029 xmlSecTmplKeyInfoAddKeyValue(xmlNodePtr keyInfoNode) {
1030     xmlNodePtr res;
1031 
1032     xmlSecAssert2(keyInfoNode != NULL, NULL);
1033 
1034     res = xmlSecAddChild(keyInfoNode, xmlSecNodeKeyValue, xmlSecDSigNs);
1035     if(res == NULL) {
1036         xmlSecInternalError("xmlSecAddChild(xmlSecNodeKeyValue)", NULL);
1037         return(NULL);
1038     }
1039 
1040     return(res);
1041 }
1042 
1043 /**
1044  * xmlSecTmplKeyInfoAddX509Data:
1045  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
1046  *
1047  * Adds <dsig:X509Data/> node to the <dsig:KeyInfo/> node @keyInfoNode.
1048  *
1049  * Returns: the pointer to the newly created <dsig:X509Data/> node or
1050  * NULL if an error occurs.
1051  */
1052 xmlNodePtr
xmlSecTmplKeyInfoAddX509Data(xmlNodePtr keyInfoNode)1053 xmlSecTmplKeyInfoAddX509Data(xmlNodePtr keyInfoNode) {
1054     xmlNodePtr res;
1055 
1056     xmlSecAssert2(keyInfoNode != NULL, NULL);
1057 
1058     res = xmlSecAddChild(keyInfoNode, xmlSecNodeX509Data, xmlSecDSigNs);
1059     if(res == NULL) {
1060         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509Data)", NULL);
1061         return(NULL);
1062     }
1063 
1064     return(res);
1065 }
1066 
1067 /**
1068  * xmlSecTmplKeyInfoAddRetrievalMethod:
1069  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
1070  * @uri:                the URI attribute (optional).
1071  * @type:               the Type attribute(optional).
1072  *
1073  * Adds <dsig:RetrievalMethod/> node to the <dsig:KeyInfo/> node @keyInfoNode.
1074  *
1075  * Returns: the pointer to the newly created <dsig:RetrievalMethod/> node or
1076  * NULL if an error occurs.
1077  */
1078 xmlNodePtr
xmlSecTmplKeyInfoAddRetrievalMethod(xmlNodePtr keyInfoNode,const xmlChar * uri,const xmlChar * type)1079 xmlSecTmplKeyInfoAddRetrievalMethod(xmlNodePtr keyInfoNode, const xmlChar *uri,
1080                              const xmlChar *type) {
1081     xmlNodePtr res;
1082 
1083     xmlSecAssert2(keyInfoNode != NULL, NULL);
1084 
1085     res = xmlSecAddChild(keyInfoNode, xmlSecNodeRetrievalMethod, xmlSecDSigNs);
1086     if(res == NULL) {
1087         xmlSecInternalError("xmlSecAddChild(xmlSecNodeRetrievalMethod)", NULL);
1088         return(NULL);
1089     }
1090 
1091     if(uri != NULL) {
1092         xmlSetProp(res, xmlSecAttrURI, uri);
1093     }
1094     if(type != NULL) {
1095         xmlSetProp(res, xmlSecAttrType, type);
1096     }
1097     return(res);
1098 }
1099 
1100 /**
1101  * xmlSecTmplRetrievalMethodAddTransform:
1102  * @retrMethodNode:     the pointer to <dsig:RetrievalMethod/> node.
1103  * @transformId:        the transform id.
1104  *
1105  * Adds <dsig:Transform/> node (and the parent <dsig:Transforms/> node
1106  * if required) to the <dsig:RetrievalMethod/> node @retrMethod.
1107  *
1108  * Returns: the pointer to the newly created <dsig:Transforms/> node or
1109  * NULL if an error occurs.
1110  */
1111 xmlNodePtr
xmlSecTmplRetrievalMethodAddTransform(xmlNodePtr retrMethodNode,xmlSecTransformId transformId)1112 xmlSecTmplRetrievalMethodAddTransform(xmlNodePtr retrMethodNode, xmlSecTransformId transformId) {
1113     xmlNodePtr transformsNode;
1114     xmlNodePtr res;
1115 
1116     xmlSecAssert2(retrMethodNode != NULL, NULL);
1117     xmlSecAssert2(transformId != NULL, NULL);
1118     xmlSecAssert2(transformId->href != NULL, NULL);
1119 
1120     transformsNode = xmlSecFindChild(retrMethodNode, xmlSecNodeTransforms, xmlSecDSigNs);
1121     if(transformsNode == NULL) {
1122         transformsNode = xmlSecAddChild(retrMethodNode, xmlSecNodeTransforms, xmlSecDSigNs);
1123         if(transformsNode == NULL) {
1124             xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransforms)", NULL);
1125             return(NULL);
1126         }
1127     }
1128 
1129     res = xmlSecAddChild(transformsNode,  xmlSecNodeTransform, xmlSecDSigNs);
1130     if(res == NULL) {
1131         xmlSecInternalError("xmlSecAddChild(xmlSecNodeTransform)", NULL);
1132         return(NULL);
1133     }
1134 
1135     if(xmlSetProp(res, xmlSecAttrAlgorithm, transformId->href) == NULL) {
1136         xmlSecXmlError2("xmlSetProp", NULL,
1137                         "name=%s", xmlSecErrorsSafeString(xmlSecAttrAlgorithm));
1138         xmlUnlinkNode(res);
1139         xmlFreeNode(res);
1140         return(NULL);
1141     }
1142 
1143     return(res);
1144 }
1145 
1146 
1147 /**
1148  * xmlSecTmplKeyInfoAddEncryptedKey:
1149  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
1150  * @encMethodId:        the encryption method (optional).
1151  * @id:                 the Id attribute (optional).
1152  * @type:               the Type attribute (optional).
1153  * @recipient:          the Recipient attribute (optional).
1154  *
1155  * Adds <enc:EncryptedKey/> node with given attributes to
1156  * the <dsig:KeyInfo/> node @keyInfoNode.
1157  *
1158  * Returns: the pointer to the newly created <enc:EncryptedKey/> node or
1159  * NULL if an error occurs.
1160  */
1161 xmlNodePtr
xmlSecTmplKeyInfoAddEncryptedKey(xmlNodePtr keyInfoNode,xmlSecTransformId encMethodId,const xmlChar * id,const xmlChar * type,const xmlChar * recipient)1162 xmlSecTmplKeyInfoAddEncryptedKey(xmlNodePtr keyInfoNode, xmlSecTransformId encMethodId,
1163                          const xmlChar* id, const xmlChar* type, const xmlChar* recipient) {
1164     xmlNodePtr encKeyNode;
1165 
1166     xmlSecAssert2(keyInfoNode != NULL, NULL);
1167 
1168     /* we allow multiple encrypted key elements */
1169     encKeyNode = xmlSecAddChild(keyInfoNode, xmlSecNodeEncryptedKey, xmlSecEncNs);
1170     if(encKeyNode == NULL) {
1171         xmlSecInternalError("xmlSecAddChild(xmlSecNodeEncryptedKey)", NULL);
1172         return(NULL);
1173     }
1174 
1175     if(id != NULL) {
1176         xmlSetProp(encKeyNode, xmlSecAttrId, id);
1177     }
1178     if(type != NULL) {
1179         xmlSetProp(encKeyNode, xmlSecAttrType, type);
1180     }
1181     if(recipient != NULL) {
1182         xmlSetProp(encKeyNode, xmlSecAttrRecipient, recipient);
1183     }
1184 
1185     if(xmlSecTmplPrepareEncData(encKeyNode, encMethodId) < 0) {
1186         xmlUnlinkNode(encKeyNode);
1187         xmlFreeNode(encKeyNode);
1188         return(NULL);
1189     }
1190     return(encKeyNode);
1191 }
1192 
1193 /***********************************************************************
1194  *
1195  * <dsig:X509Data> node
1196  *
1197  **********************************************************************/
1198 /**
1199  * xmlSecTmplX509DataAddIssuerSerial:
1200  * @x509DataNode:       the pointer to <dsig:X509Data/> node.
1201  *
1202  * Adds <dsig:X509IssuerSerial/> node to the given <dsig:X509Data/> node.
1203  *
1204  * Returns: the pointer to the newly created <dsig:X509IssuerSerial/> node or
1205  * NULL if an error occurs.
1206  */
1207 
1208 xmlNodePtr
xmlSecTmplX509DataAddIssuerSerial(xmlNodePtr x509DataNode)1209 xmlSecTmplX509DataAddIssuerSerial(xmlNodePtr x509DataNode) {
1210     xmlNodePtr cur;
1211 
1212     xmlSecAssert2(x509DataNode != NULL, NULL);
1213 
1214     cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
1215     if(cur != NULL) {
1216         xmlSecNodeAlreadyPresentError(x509DataNode, xmlSecNodeX509IssuerSerial, NULL);
1217         return(NULL);
1218     }
1219 
1220     cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
1221     if(cur == NULL) {
1222         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509IssuerSerial)", NULL);
1223         return(NULL);
1224     }
1225 
1226     return (cur);
1227 }
1228 
1229 /**
1230  * xmlSecTmplX509IssuerSerialAddIssuerName:
1231  * @x509IssuerSerialNode:       the pointer to <dsig:X509IssuerSerial/> node.
1232  * @issuerName:         the issuer name (optional).
1233  *
1234  * Adds <dsig:X509IssuerName/> node to the <dsig:X509IssuerSerial/> node @x509IssuerSerialNode.
1235  *
1236  * Returns: the pointer to the newly created <dsig:X509IssuerName/> node or
1237  * NULL if an error occurs.
1238  */
1239 xmlNodePtr
xmlSecTmplX509IssuerSerialAddIssuerName(xmlNodePtr x509IssuerSerialNode,const xmlChar * issuerName)1240 xmlSecTmplX509IssuerSerialAddIssuerName(xmlNodePtr x509IssuerSerialNode, const xmlChar* issuerName) {
1241     xmlNodePtr res;
1242     int ret;
1243 
1244     xmlSecAssert2(x509IssuerSerialNode != NULL, NULL);
1245     if(xmlSecFindChild(x509IssuerSerialNode, xmlSecNodeX509IssuerName, xmlSecDSigNs) != NULL) {
1246         xmlSecNodeAlreadyPresentError(x509IssuerSerialNode, xmlSecNodeX509IssuerName, NULL);
1247         return(NULL);
1248     }
1249 
1250     res = xmlSecAddChild(x509IssuerSerialNode, xmlSecNodeX509IssuerName, xmlSecDSigNs);
1251     if(res == NULL) {
1252         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509IssuerName)", NULL);
1253         return(NULL);
1254     }
1255 
1256     if (issuerName != NULL) {
1257         ret = xmlSecNodeEncodeAndSetContent(res, issuerName);
1258         if(ret < 0) {
1259             xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1260             return(NULL);
1261         }
1262     }
1263     return(res);
1264 }
1265 
1266 /**
1267  * xmlSecTmplX509IssuerSerialAddSerialNumber:
1268  * @x509IssuerSerialNode:       the pointer to <dsig:X509IssuerSerial/> node.
1269  * @serial:             the serial number (optional).
1270  *
1271  * Adds <dsig:X509SerialNumber/> node to the <dsig:X509IssuerSerial/> node @x509IssuerSerialNode.
1272  *
1273  * Returns: the pointer to the newly created <dsig:X509SerialNumber/> node or
1274  * NULL if an error occurs.
1275  */
1276 xmlNodePtr
xmlSecTmplX509IssuerSerialAddSerialNumber(xmlNodePtr x509IssuerSerialNode,const xmlChar * serial)1277 xmlSecTmplX509IssuerSerialAddSerialNumber(xmlNodePtr x509IssuerSerialNode, const xmlChar* serial) {
1278     xmlNodePtr res;
1279     int ret;
1280 
1281     xmlSecAssert2(x509IssuerSerialNode != NULL, NULL);
1282 
1283     if(xmlSecFindChild(x509IssuerSerialNode, xmlSecNodeX509SerialNumber, xmlSecDSigNs) != NULL) {
1284         xmlSecNodeAlreadyPresentError(x509IssuerSerialNode, xmlSecNodeX509SerialNumber, NULL);
1285         return(NULL);
1286     }
1287 
1288     res = xmlSecAddChild(x509IssuerSerialNode, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
1289     if(res == NULL) {
1290         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509SerialNumber)", NULL);
1291         return(NULL);
1292     }
1293 
1294     if (serial != NULL) {
1295         ret = xmlSecNodeEncodeAndSetContent(res, serial);
1296         if(ret < 0) {
1297             xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1298             return(NULL);
1299         }
1300     }
1301     return(res);
1302 }
1303 
1304 /**
1305  * xmlSecTmplX509DataAddSubjectName:
1306  * @x509DataNode:       the pointer to <dsig:X509Data/> node.
1307  *
1308  * Adds <dsig:X509SubjectName/> node to the given <dsig:X509Data/> node.
1309  *
1310  * Returns: the pointer to the newly created <dsig:X509SubjectName/> node or
1311  * NULL if an error occurs.
1312  */
1313 
1314 xmlNodePtr
xmlSecTmplX509DataAddSubjectName(xmlNodePtr x509DataNode)1315 xmlSecTmplX509DataAddSubjectName(xmlNodePtr x509DataNode) {
1316     xmlNodePtr cur;
1317 
1318     xmlSecAssert2(x509DataNode != NULL, NULL);
1319 
1320     cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509SubjectName, xmlSecDSigNs);
1321     if(cur != NULL) {
1322         xmlSecNodeAlreadyPresentError(x509DataNode, xmlSecNodeX509SubjectName, NULL);
1323         return(NULL);
1324     }
1325 
1326     cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509SubjectName, xmlSecDSigNs);
1327     if(cur == NULL) {
1328         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509SubjectName)", NULL);
1329         return(NULL);
1330     }
1331 
1332     return (cur);
1333 }
1334 
1335 /**
1336  * xmlSecTmplX509DataAddSKI:
1337  * @x509DataNode:       the pointer to <dsig:X509Data/> node.
1338  *
1339  * Adds <dsig:X509SKI/> node to the given <dsig:X509Data/> node.
1340  *
1341  * Returns: the pointer to the newly created <dsig:X509SKI/> node or
1342  * NULL if an error occurs.
1343  */
1344 
1345 xmlNodePtr
xmlSecTmplX509DataAddSKI(xmlNodePtr x509DataNode)1346 xmlSecTmplX509DataAddSKI(xmlNodePtr x509DataNode) {
1347     xmlNodePtr cur;
1348 
1349     xmlSecAssert2(x509DataNode != NULL, NULL);
1350 
1351     cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509SKI, xmlSecDSigNs);
1352     if(cur != NULL) {
1353         xmlSecNodeAlreadyPresentError(x509DataNode, xmlSecNodeX509SKI, NULL);
1354         return(NULL);
1355     }
1356 
1357     cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509SKI, xmlSecDSigNs);
1358     if(cur == NULL) {
1359         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509SKI)", NULL);
1360         return(NULL);
1361     }
1362 
1363     return (cur);
1364 }
1365 
1366 
1367 /**
1368  * xmlSecTmplX509DataAddCertificate:
1369  * @x509DataNode:       the pointer to <dsig:X509Data/> node.
1370  *
1371  * Adds <dsig:X509Certificate/> node to the given <dsig:X509Data/> node.
1372  *
1373  * Returns: the pointer to the newly created <dsig:X509Certificate/> node or
1374  * NULL if an error occurs.
1375  */
1376 
1377 xmlNodePtr
xmlSecTmplX509DataAddCertificate(xmlNodePtr x509DataNode)1378 xmlSecTmplX509DataAddCertificate(xmlNodePtr x509DataNode) {
1379     xmlNodePtr cur;
1380 
1381     xmlSecAssert2(x509DataNode != NULL, NULL);
1382 
1383     cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509Certificate, xmlSecDSigNs);
1384     if(cur != NULL) {
1385         xmlSecNodeAlreadyPresentError(x509DataNode, xmlSecNodeX509Certificate, NULL);
1386         return(NULL);
1387     }
1388 
1389     cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509Certificate, xmlSecDSigNs);
1390     if(cur == NULL) {
1391         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509Certificate)", NULL);
1392         return(NULL);
1393     }
1394 
1395     return (cur);
1396 }
1397 
1398 /**
1399  * xmlSecTmplX509DataAddCRL:
1400  * @x509DataNode:       the pointer to <dsig:X509Data/> node.
1401  *
1402  * Adds <dsig:X509CRL/> node to the given <dsig:X509Data/> node.
1403  *
1404  * Returns: the pointer to the newly created <dsig:X509CRL/> node or
1405  * NULL if an error occurs.
1406  */
1407 
1408 xmlNodePtr
xmlSecTmplX509DataAddCRL(xmlNodePtr x509DataNode)1409 xmlSecTmplX509DataAddCRL(xmlNodePtr x509DataNode) {
1410     xmlNodePtr cur;
1411 
1412     xmlSecAssert2(x509DataNode != NULL, NULL);
1413 
1414     cur = xmlSecFindChild(x509DataNode, xmlSecNodeX509CRL, xmlSecDSigNs);
1415     if(cur != NULL) {
1416         xmlSecNodeAlreadyPresentError(x509DataNode, xmlSecNodeX509CRL, NULL);
1417         return(NULL);
1418     }
1419 
1420     cur = xmlSecAddChild(x509DataNode, xmlSecNodeX509CRL, xmlSecDSigNs);
1421     if(cur == NULL) {
1422         xmlSecInternalError("xmlSecAddChild(xmlSecNodeX509CRL)", NULL);
1423         return(NULL);
1424     }
1425 
1426     return (cur);
1427 }
1428 
1429 /*************************************************************************
1430  *
1431  * <dsig:Transform/> node
1432  *
1433  ************************************************************************/
1434 
1435 /**
1436  * xmlSecTmplTransformAddHmacOutputLength:
1437  * @transformNode:      the pointer to <dsig:Transform/> node
1438  * @bitsLen:            the required length in bits
1439  *
1440  * Creates <dsig:HMACOutputLength/> child for the HMAC transform
1441  * node @node.
1442  *
1443  * Returns: 0 on success and a negative value otherwise.
1444  */
1445 int
xmlSecTmplTransformAddHmacOutputLength(xmlNodePtr transformNode,xmlSecSize bitsLen)1446 xmlSecTmplTransformAddHmacOutputLength(xmlNodePtr transformNode, xmlSecSize bitsLen) {
1447     xmlNodePtr cur;
1448     char buf[64];
1449 
1450     xmlSecAssert2(transformNode != NULL, -1);
1451     xmlSecAssert2(bitsLen > 0, -1);
1452 
1453     cur = xmlSecFindChild(transformNode, xmlSecNodeHMACOutputLength, xmlSecDSigNs);
1454     if(cur != NULL) {
1455         xmlSecNodeAlreadyPresentError(transformNode, xmlSecNodeHMACOutputLength, NULL);
1456         return(-1);
1457     }
1458 
1459     cur = xmlSecAddChild(transformNode, xmlSecNodeHMACOutputLength, xmlSecDSigNs);
1460     if(cur == NULL) {
1461         xmlSecInternalError("xmlSecAddChild(xmlSecNodeHMACOutputLength)", NULL);
1462         return(-1);
1463     }
1464 
1465 #ifdef WIN32
1466     sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)bitsLen);
1467 #else  /* WIN32 */
1468     sprintf(buf, "%lu", (unsigned long)bitsLen);
1469 #endif /* WIN32 */
1470     xmlNodeSetContent(cur, BAD_CAST buf);
1471     return(0);
1472 }
1473 
1474 /**
1475  * xmlSecTmplTransformAddRsaOaepParam:
1476  * @transformNode:      the pointer to <dsig:Transform/> node.
1477  * @buf:                the OAEP param buffer.
1478  * @size:               the OAEP param buffer size.
1479  *
1480  * Creates <enc:OAEPParam/> child node in the @node.
1481  *
1482  * Returns: 0 on success or a negative value if an error occurs.
1483  */
1484 int
xmlSecTmplTransformAddRsaOaepParam(xmlNodePtr transformNode,const xmlSecByte * buf,xmlSecSize size)1485 xmlSecTmplTransformAddRsaOaepParam(xmlNodePtr transformNode,
1486                         const xmlSecByte *buf, xmlSecSize size) {
1487     xmlNodePtr oaepParamNode;
1488     xmlChar *base64;
1489 
1490     xmlSecAssert2(transformNode != NULL, -1);
1491     xmlSecAssert2(buf != NULL, -1);
1492     xmlSecAssert2(size > 0, -1);
1493 
1494     oaepParamNode = xmlSecFindChild(transformNode, xmlSecNodeRsaOAEPparams, xmlSecEncNs);
1495     if(oaepParamNode != NULL) {
1496         xmlSecNodeAlreadyPresentError(transformNode, xmlSecNodeRsaOAEPparams, NULL);
1497         return(-1);
1498     }
1499 
1500     oaepParamNode = xmlSecAddChild(transformNode, xmlSecNodeRsaOAEPparams, xmlSecEncNs);
1501     if(oaepParamNode == NULL) {
1502         xmlSecInternalError("xmlSecAddChild(xmlSecNodeRsaOAEPparams)", NULL);
1503         return(-1);
1504     }
1505 
1506     base64 = xmlSecBase64Encode(buf, size, 0);
1507     if(base64 == NULL) {
1508         xmlSecInternalError2("xmlSecBase64Encode", NULL, "size=%d", size);
1509         return(-1);
1510     }
1511 
1512     xmlNodeSetContent(oaepParamNode, base64);
1513     xmlFree(base64);
1514     return(0);
1515 }
1516 
1517 /**
1518  * xmlSecTmplTransformAddXsltStylesheet:
1519  * @transformNode:      the pointer to <dsig:Transform/> node.
1520  * @xslt:               the XSLT transform expression.
1521  *
1522  * Writes the XSLT transform expression to the @node.
1523  *
1524  * Returns: 0 on success or a negative value otherwise.
1525  */
1526 int
xmlSecTmplTransformAddXsltStylesheet(xmlNodePtr transformNode,const xmlChar * xslt)1527 xmlSecTmplTransformAddXsltStylesheet(xmlNodePtr transformNode, const xmlChar *xslt) {
1528     xmlDocPtr xsltDoc;
1529     int ret;
1530 
1531     xmlSecAssert2(transformNode != NULL, -1);
1532     xmlSecAssert2(xslt != NULL, -1);
1533 
1534     xsltDoc = xmlParseMemory((const char*)xslt, xmlStrlen(xslt));
1535     if(xsltDoc == NULL) {
1536         xmlSecXmlError("xmlParseMemory", NULL);
1537         return(-1);
1538     }
1539 
1540     ret = xmlSecReplaceContent(transformNode, xmlDocGetRootElement(xsltDoc));
1541     if(ret < 0) {
1542         xmlSecInternalError("xmlSecReplaceContent", NULL);
1543         xmlFreeDoc(xsltDoc);
1544         return(-1);
1545     }
1546 
1547     xmlFreeDoc(xsltDoc);
1548     return(0);
1549 }
1550 
1551 /**
1552  * xmlSecTmplTransformAddC14NInclNamespaces:
1553  * @transformNode:      the pointer to <dsig:Transform/> node.
1554  * @prefixList:         the white space delimited  list of namespace prefixes,
1555  *                      where "#default" indicates the default namespace
1556  *                      (optional).
1557  *
1558  * Adds "inclusive" namespaces to the ExcC14N transform node @node.
1559  *
1560  * Returns: 0 if success or a negative value otherwise.
1561  */
1562 int
xmlSecTmplTransformAddC14NInclNamespaces(xmlNodePtr transformNode,const xmlChar * prefixList)1563 xmlSecTmplTransformAddC14NInclNamespaces(xmlNodePtr transformNode,
1564                                          const xmlChar *prefixList) {
1565     xmlNodePtr cur;
1566 
1567     xmlSecAssert2(transformNode != NULL, -1);
1568     xmlSecAssert2(prefixList != NULL, -1);
1569 
1570     cur = xmlSecFindChild(transformNode, xmlSecNodeInclusiveNamespaces, xmlSecNsExcC14N);
1571     if(cur != NULL) {
1572         xmlSecNodeAlreadyPresentError(transformNode, xmlSecNodeInclusiveNamespaces, NULL);
1573         return(-1);
1574     }
1575 
1576     cur = xmlSecAddChild(transformNode, xmlSecNodeInclusiveNamespaces, xmlSecNsExcC14N);
1577     if(cur == NULL) {
1578         xmlSecInternalError("xmlSecAddChild(xmlSecNodeInclusiveNamespaces)",
1579                             xmlSecNodeGetName(transformNode));
1580         return(-1);
1581     }
1582 
1583     xmlSetProp(cur, xmlSecAttrPrefixList, prefixList);
1584     return(0);
1585 }
1586 
1587 /**
1588  * xmlSecTmplTransformAddXPath:
1589  * @transformNode:      the pointer to the <dsig:Transform/> node.
1590  * @expression:         the XPath expression.
1591  * @nsList:             the NULL terminated list of namespace prefix/href pairs
1592  *                      (optional).
1593  *
1594  * Writes XPath transform information to the <dsig:Transform/> node
1595  * @node.
1596  *
1597  * Returns: 0 for success or a negative value otherwise.
1598  */
1599 int
xmlSecTmplTransformAddXPath(xmlNodePtr transformNode,const xmlChar * expression,const xmlChar ** nsList)1600 xmlSecTmplTransformAddXPath(xmlNodePtr transformNode, const xmlChar *expression,
1601                          const xmlChar **nsList) {
1602     xmlNodePtr xpathNode;
1603     int ret;
1604 
1605     xmlSecAssert2(transformNode != NULL, -1);
1606     xmlSecAssert2(expression != NULL, -1);
1607 
1608     xpathNode = xmlSecFindChild(transformNode, xmlSecNodeXPath, xmlSecDSigNs);
1609     if(xpathNode != NULL) {
1610         xmlSecNodeAlreadyPresentError(transformNode, xmlSecNodeXPath, NULL);
1611         return(-1);
1612     }
1613 
1614     xpathNode = xmlSecAddChild(transformNode, xmlSecNodeXPath, xmlSecDSigNs);
1615     if(xpathNode == NULL) {
1616         xmlSecInternalError("xmlSecAddChild(xmlSecNodeXPath)", NULL);
1617         return(-1);
1618     }
1619 
1620     ret = xmlSecNodeEncodeAndSetContent(xpathNode, expression);
1621     if(ret < 0) {
1622         xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1623         return(-1);
1624     }
1625 
1626     return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpathNode, nsList) : 0);
1627 }
1628 
1629 /**
1630  * xmlSecTmplTransformAddXPath2:
1631  * @transformNode:      the pointer to the <dsig:Transform/> node.
1632  * @type:               the XPath2 transform type ("union", "intersect" or "subtract").
1633  * @expression:         the XPath expression.
1634  * @nsList:             the NULL terminated list of namespace prefix/href pairs.
1635  *                      (optional).
1636  *
1637  * Writes XPath2 transform information to the <dsig:Transform/> node
1638  * @node.
1639  *
1640  * Returns: 0 for success or a negative value otherwise.
1641  */
1642 int
xmlSecTmplTransformAddXPath2(xmlNodePtr transformNode,const xmlChar * type,const xmlChar * expression,const xmlChar ** nsList)1643 xmlSecTmplTransformAddXPath2(xmlNodePtr transformNode, const xmlChar* type,
1644                         const xmlChar *expression, const xmlChar **nsList) {
1645     xmlNodePtr xpathNode;
1646     int ret;
1647 
1648     xmlSecAssert2(transformNode != NULL, -1);
1649     xmlSecAssert2(type != NULL, -1);
1650     xmlSecAssert2(expression != NULL, -1);
1651 
1652     xpathNode = xmlSecAddChild(transformNode, xmlSecNodeXPath, xmlSecXPath2Ns);
1653     if(xpathNode == NULL) {
1654         xmlSecInternalError("xmlSecAddChild(xmlSecNodeXPath)", NULL);
1655         return(-1);
1656     }
1657     xmlSetProp(xpathNode, xmlSecAttrFilter, type);
1658 
1659     ret = xmlSecNodeEncodeAndSetContent(xpathNode, expression);
1660     if(ret < 0) {
1661         xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1662         return(-1);
1663     }
1664 
1665     return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpathNode, nsList) : 0);
1666 }
1667 
1668 /**
1669  * xmlSecTmplTransformAddXPointer:
1670  * @transformNode:      the pointer to the <dsig:Transform/> node.
1671  * @expression:         the XPath expression.
1672  * @nsList:             the NULL terminated list of namespace prefix/href pairs.
1673  *                      (optional).
1674  *
1675  * Writes XPointer transform information to the <dsig:Transform/> node
1676  * @node.
1677  *
1678  * Returns: 0 for success or a negative value otherwise.
1679  */
1680 int
xmlSecTmplTransformAddXPointer(xmlNodePtr transformNode,const xmlChar * expression,const xmlChar ** nsList)1681 xmlSecTmplTransformAddXPointer(xmlNodePtr transformNode, const xmlChar *expression,
1682                          const xmlChar **nsList) {
1683     xmlNodePtr xpointerNode;
1684     int ret;
1685 
1686     xmlSecAssert2(expression != NULL, -1);
1687     xmlSecAssert2(transformNode != NULL, -1);
1688 
1689     xpointerNode = xmlSecFindChild(transformNode, xmlSecNodeXPointer, xmlSecXPointerNs);
1690     if(xpointerNode != NULL) {
1691         xmlSecNodeAlreadyPresentError(transformNode, xmlSecNodeXPointer, NULL);
1692         return(-1);
1693     }
1694 
1695     xpointerNode = xmlSecAddChild(transformNode, xmlSecNodeXPointer, xmlSecXPointerNs);
1696     if(xpointerNode == NULL) {
1697         xmlSecInternalError("xmlSecAddChild(xmlSecNodeXPointer)", NULL);
1698         return(-1);
1699     }
1700 
1701     ret = xmlSecNodeEncodeAndSetContent(xpointerNode, expression);
1702     if(ret < 0) {
1703         xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
1704         return(-1);
1705     }
1706 
1707     return((nsList != NULL) ? xmlSecTmplNodeWriteNsList(xpointerNode, nsList) : 0);
1708 }
1709 
1710 static int
xmlSecTmplNodeWriteNsList(xmlNodePtr parentNode,const xmlChar ** nsList)1711 xmlSecTmplNodeWriteNsList(xmlNodePtr parentNode, const xmlChar** nsList) {
1712     xmlNsPtr ns;
1713     const xmlChar *prefix;
1714     const xmlChar *href;
1715     const xmlChar **ptr;
1716 
1717     xmlSecAssert2(parentNode != NULL, -1);
1718     xmlSecAssert2(nsList != NULL, -1);
1719 
1720     /* nsList contains pairs of prefix/href with NULL at the end. We use special
1721     "#default" prefix instead of NULL prefix */
1722     ptr = nsList;
1723     while((*ptr) != NULL) {
1724         /* get next prefix/href pair */
1725         if(xmlStrEqual(BAD_CAST "#default", (*ptr))) {
1726             prefix = NULL;
1727         } else {
1728             prefix = (*ptr);
1729         }
1730         href = *(++ptr);
1731         if(href == NULL) {
1732             xmlSecInvalidDataError("unexpected end of ns list", NULL);
1733             return(-1);
1734         }
1735 
1736         /* create namespace node */
1737         ns = xmlNewNs(parentNode, href, prefix);
1738         if(ns == NULL) {
1739             xmlSecXmlError2("xmlNewNs", NULL,
1740                             "prefix=%s", xmlSecErrorsSafeString(prefix));
1741             return(-1);
1742         }
1743 
1744         /* next pair */
1745         ++ptr;
1746     }
1747     return(0);
1748 }
1749